Skip to content

Commit

Permalink
Fixes #2773
Browse files Browse the repository at this point in the history
  • Loading branch information
zachleat committed Jan 25, 2023
1 parent 99140d8 commit 786105e
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 97 deletions.
32 changes: 13 additions & 19 deletions src/Eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const TemplateConfig = require("./TemplateConfig");
const FileSystemSearch = require("./FileSystemSearch");

const simplePlural = require("./Util/Pluralize");
const deleteRequireCache = require("./Util/DeleteRequireCache");
const checkPassthroughCopyBehavior = require("./Util/PassthroughCopyBehaviorCheck");
const debug = require("debug")("Eleventy");
const eventBus = require("./EventBus");
Expand Down Expand Up @@ -286,12 +285,6 @@ class Eleventy {
this.bench.reset();
this.eleventyFiles.restart();
this.extensionMap.reset();

// reload package.json values (if applicable)
// TODO only reset this if it changed
deleteRequireCache("package.json");

await this.init();
}

/**
Expand Down Expand Up @@ -374,7 +367,9 @@ class Eleventy {
* @method
* @returns {} - tbd.
*/
async init() {
async init(options = {}) {
options = Object.assign({ viaConfigReset: false }, options);

await this.config.events.emit("eleventy.config", this.eleventyConfig);

if (this.env) {
Expand Down Expand Up @@ -744,23 +739,18 @@ Arguments:
return true;
}

let returnValue = false;

for (const configFilePath of configFilePaths) {
// Any dependencies of the config file changed
let configFileDependencies = this.watchTargets.getDependenciesOf(configFilePath);

for (let dep of configFileDependencies) {
if (this.watchManager.hasQueuedFile(dep)) {
// Delete from require cache so that updates to the module are re-required
deleteRequireCache(dep);

returnValue = true;
return true;
}
}
}

return returnValue;
return false;
}

/**
Expand All @@ -780,14 +770,17 @@ Arguments:
await this.config.events.emit("beforeWatch", queue);
await this.config.events.emit("eleventy.beforeWatch", queue);

// reset and reload global configuration :O
if (this._shouldResetConfig()) {
// Clear `require` cache for all files that triggered the rebuild
this.watchTargets.clearRequireCacheFor(queue);

// reset and reload global configuration
let isResetConfig = this._shouldResetConfig();
if (isResetConfig) {
this.resetConfig();
}

await this.restart();

this.watchTargets.clearDependencyRequireCache();
await this.init({ viaConfigReset: isResetConfig });

let incrementalFile = this.watchManager.getIncrementalFile();
if (incrementalFile) {
Expand Down Expand Up @@ -876,6 +869,7 @@ Arguments:
this.watchManager = new EleventyWatch();
this.watchManager.incremental = this.isIncremental;

this.watchTargets.add(["./package.json"]);
this.watchTargets.add(this.eleventyFiles.getGlobWatcherFiles());
this.watchTargets.add(this.eleventyFiles.getIgnoreFiles());

Expand Down
13 changes: 10 additions & 3 deletions src/EleventyWatchTargets.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,16 @@ class EleventyWatchTargets {
this.writer = templateWriter;
}

clearDependencyRequireCache() {
for (let path of this.dependencies) {
deleteRequireCache(path);
clearRequireCacheFor(filePathArray) {
for (const filePath of filePathArray) {
deleteRequireCache(filePath);

// Any dependencies of the config file changed
let fileDeps = this.getDependenciesOf(filePath);
for (let dep of fileDeps) {
// Delete from require cache so that updates to the module are re-required
deleteRequireCache(dep);
}
}
}

Expand Down
36 changes: 16 additions & 20 deletions src/Engines/JavaScript.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ const { TemplatePath } = require("@11ty/eleventy-utils");

const TemplateEngine = require("./TemplateEngine");
const EleventyBaseError = require("../EleventyBaseError");
const deleteRequireCache = require("../Util/DeleteRequireCache");
const getJavaScriptData = require("../Util/GetJavaScriptData");
const eventBus = require("../EventBus");

class JavaScriptTemplateNotDefined extends EleventyBaseError {}

Expand All @@ -13,6 +13,15 @@ class JavaScript extends TemplateEngine {
this.instances = {};

this.cacheable = false;

eventBus.on("eleventy.resourceModified", (inputPath) => {
inputPath = TemplatePath.addLeadingDotSlash(inputPath);

// Remove from cached instances when modified
if (inputPath in this.instances) {
delete this.instances[inputPath];
}
});
}

normalize(result) {
Expand All @@ -34,10 +43,7 @@ class JavaScript extends TemplateEngine {
if (typeof mod === "string" || mod instanceof Buffer || mod.then) {
return { render: () => mod };
} else if (typeof mod === "function") {
if (
mod.prototype &&
("data" in mod.prototype || "render" in mod.prototype)
) {
if (mod.prototype && ("data" in mod.prototype || "render" in mod.prototype)) {
if (!("render" in mod.prototype)) {
mod.prototype.render = noop;
}
Expand All @@ -58,7 +64,7 @@ class JavaScript extends TemplateEngine {
return this.instances[inputPath];
}

const mod = this._getRequire(inputPath);
const mod = require(TemplatePath.absolutePath(inputPath));
let inst = this._getInstance(mod);

if (inst) {
Expand All @@ -71,11 +77,6 @@ class JavaScript extends TemplateEngine {
return inst;
}

_getRequire(inputPath) {
let requirePath = TemplatePath.absolutePath(inputPath);
return require(requirePath);
}

/**
* JavaScript files defer to the module loader rather than read the files to strings
*
Expand All @@ -85,15 +86,6 @@ class JavaScript extends TemplateEngine {
return false;
}

// only remove from cache once on startup (if it already exists)
initRequireCache(inputPath) {
deleteRequireCache(inputPath);

if (inputPath in this.instances) {
delete this.instances[inputPath];
}
}

async getExtraDataFromFile(inputPath) {
let inst = this.getInstanceFromInputPath(inputPath);
return getJavaScriptData(inst, inputPath);
Expand Down Expand Up @@ -137,8 +129,12 @@ class JavaScript extends TemplateEngine {
// For normal templates, str will be falsy.
inst = this.getInstanceFromInputPath(inputPath);
}

if (inst && "render" in inst) {
return function (data) {
// TODO does this do anything meaningful for non-classes?
// `inst` should have a normalized `render` function from _getInstance

// only blow away existing inst.page if it has a page.url
if (!inst.page || inst.page.url) {
inst.page = data.page;
Expand Down
4 changes: 0 additions & 4 deletions src/Engines/TemplateEngine.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,6 @@ class TemplateEngine {
return {};
}

initRequireCache() {
// do nothing
}

getCompileCacheKey(str, inputPath) {
// Changing to use inputPath and contents, using only file contents (`str`) caused issues when two
// different files had identical content (2.0.0-canary.16)
Expand Down
3 changes: 3 additions & 0 deletions src/Plugins/ServerlessBundlerPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const NetlifyRedirects = require("./Serverless/NetlifyRedirects");
const { EleventyRequire } = require("../Util/Require");
const DirContains = require("../Util/DirContains");
const JavaScriptDependencies = require("../Util/JavaScriptDependencies");
const deleteRequireCache = require("../Util/DeleteRequireCache");
const debug = require("debug")("Eleventy:Serverless");

// Provider specific
Expand Down Expand Up @@ -167,6 +168,8 @@ class BundlerHelper {
);

return async function EleventyServerlessMiddleware(req, res, next) {
deleteRequireCache(serverlessFilePath);

let serverlessFunction = EleventyRequire(serverlessFilepath);
let url = new URL(req.url, "http://localhost/"); // any domain will do here, we just want the searchParams

Expand Down
10 changes: 7 additions & 3 deletions src/Serverless.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const { match } = require("path-to-regexp");
const { TemplatePath } = require("@11ty/eleventy-utils");

const Eleventy = require("./Eleventy");
const { EleventyRequireAbsolute } = require("./Util/Require");
const normalizeServerlessUrl = require("./Util/NormalizeServerlessUrl");
const deleteRequireCache = require("./Util/DeleteRequireCache");
const debug = require("debug")("Eleventy:Serverless");

class Serverless {
Expand Down Expand Up @@ -100,15 +100,19 @@ class Serverless {
debug(`Including content map (maps output URLs to input files) from ${fullPath}`);

// TODO dedicated reset method, don’t delete this every time
return EleventyRequireAbsolute(fullPath);
deleteRequireCache(fullPath);

return require(fullPath);
}

getConfigInfo() {
let fullPath = TemplatePath.absolutePath(this.dir, this.configInfoFilename);
debug(`Including config info file from ${fullPath}`);

// TODO dedicated reset method, don’t delete this every time
return EleventyRequireAbsolute(fullPath);
deleteRequireCache(fullPath);

return require(fullPath);
}

isServerlessUrl(urlPath) {
Expand Down
1 change: 0 additions & 1 deletion src/TemplateData.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const { TemplatePath, isPlainObject } = require("@11ty/eleventy-utils");

const merge = require("./Util/Merge");
const unique = require("./Util/Unique");
const TemplateRender = require("./TemplateRender");
const TemplateGlob = require("./TemplateGlob");
const EleventyExtensionMap = require("./EleventyExtensionMap");
const EleventyBaseError = require("./EleventyBaseError");
Expand Down
46 changes: 9 additions & 37 deletions src/TemplateRender.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ class TemplateRenderUnknownEngineError extends EleventyBaseError {}
class TemplateRender {
constructor(tmplPath, inputDir, config) {
if (!tmplPath) {
throw new Error(
`TemplateRender requires a tmplPath argument, instead of ${tmplPath}`
);
throw new Error(`TemplateRender requires a tmplPath argument, instead of ${tmplPath}`);
}
if (!config) {
throw new TemplateRenderConfigError("Missing `config` argument.");
Expand All @@ -28,10 +26,7 @@ class TemplateRender {
this.engineNameOrPath = tmplPath;

this.inputDir = inputDir ? inputDir : this.config.dir.input;
this.includesDir = TemplatePath.join(
this.inputDir,
this.config.dir.includes
);
this.includesDir = TemplatePath.join(this.inputDir, this.config.dir.includes);

this.parseMarkdownWith = this.config.markdownTemplateEngine;
this.parseHtmlWith = this.config.htmlTemplateEngine;
Expand Down Expand Up @@ -60,11 +55,7 @@ class TemplateRender {
}

getEngineByName(name) {
let engine = this.extensionMap.engineManager.getEngine(
name,
this.getDirs(),
this.extensionMap
);
let engine = this.extensionMap.engineManager.getEngine(name, this.getDirs(), this.extensionMap);
engine.config = this.config;

return engine;
Expand All @@ -81,7 +72,6 @@ class TemplateRender {
}

this._engine = this.getEngineByName(this._engineName);
this._engine.initRequireCache(engineNameOrPath);

if (this.useMarkdown === undefined) {
this.setUseMarkdown(this._engineName === "md");
Expand All @@ -104,10 +94,7 @@ class TemplateRender {

static parseEngineOverrides(engineName) {
if (typeof (engineName || "") !== "string") {
throw new Error(
"Expected String passed to parseEngineOverrides. Received: " +
engineName
);
throw new Error("Expected String passed to parseEngineOverrides. Received: " + engineName);
}

let overlappingEngineWarningCount = 0;
Expand Down Expand Up @@ -155,9 +142,7 @@ class TemplateRender {

// used for error logging and console output.
getReadableEnginesList() {
return (
this.getReadableEnginesListDifferingFromFileExtension() || this.engineName
);
return this.getReadableEnginesListDifferingFromFileExtension() || this.engineName;
}

getReadableEnginesListDifferingFromFileExtension() {
Expand All @@ -175,11 +160,7 @@ class TemplateRender {
}
}

if (
this.engineName === "md" &&
this.useMarkdown &&
this.parseMarkdownWith
) {
if (this.engineName === "md" && this.useMarkdown && this.parseMarkdownWith) {
return this.parseMarkdownWith;
}
if (this.engineName === "html" && this.parseHtmlWith) {
Expand All @@ -206,16 +187,11 @@ class TemplateRender {
// We pass in templateEngineOverride here because it isn’t yet applied to templateRender
getEnginesList(engineOverride) {
if (engineOverride) {
let engines =
TemplateRender.parseEngineOverrides(engineOverride).reverse();
let engines = TemplateRender.parseEngineOverrides(engineOverride).reverse();
return engines.join(",");
}

if (
this.engineName === "md" &&
this.useMarkdown &&
this.parseMarkdownWith
) {
if (this.engineName === "md" && this.useMarkdown && this.parseMarkdownWith) {
return `${this.parseMarkdownWith},md`;
}
if (this.engineName === "html" && this.parseHtmlWith) {
Expand Down Expand Up @@ -297,11 +273,7 @@ class TemplateRender {
!this.useMarkdown
);
} else if (this.engineName === "html") {
return this.engine.compile(
str,
this.engineNameOrPath,
this.parseHtmlWith
);
return this.engine.compile(str, this.engineNameOrPath, this.parseHtmlWith);
} else {
return this.engine.compile(str, this.engineNameOrPath);
}
Expand Down
6 changes: 5 additions & 1 deletion src/Util/DeleteRequireCache.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const path = require("path");
const { TemplatePath } = require("@11ty/eleventy-utils");
const debug = require("debug")("Eleventy:DeleteRequireCache");

/**
* Removes a nodejs module from the cache.
Expand All @@ -8,6 +9,7 @@ const { TemplatePath } = require("@11ty/eleventy-utils");
*/
function deleteRequireCacheAbsolute(absolutePath) {
const normalizedPath = path.normalize(absolutePath);
debug("Deleting %o from `require` cache.", normalizedPath);
delete require.cache[normalizedPath];
}

Expand All @@ -16,5 +18,7 @@ function deleteRequireCache(localPath) {
deleteRequireCacheAbsolute(absolutePath);
}

module.exports = deleteRequireCache; // local paths
module.exports = deleteRequireCache; // will transform local paths to absolute

// Export for testing only
module.exports.deleteRequireCacheAbsolute = deleteRequireCacheAbsolute;
Loading

0 comments on commit 786105e

Please sign in to comment.