Skip to content

Commit

Permalink
Fixes #3338
Browse files Browse the repository at this point in the history
  • Loading branch information
zachleat committed Jun 28, 2024
1 parent 6d8e069 commit 1abffef
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 28 deletions.
11 changes: 7 additions & 4 deletions src/Eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ class Eleventy {
await this.eleventyConfig.setProjectConfigPath(this.options.configPath);
}

this.eleventyConfig.setRunMode(this.runMode);
this.eleventyConfig.setProjectUsingEsm(this.isEsm);
this.eleventyConfig.setLogger(this.logger);
this.eleventyConfig.setDirectories(this.directories);
Expand Down Expand Up @@ -204,9 +205,8 @@ class Eleventy {
this.watchManager = new EleventyWatch();

/** @member {Object} - tbd. */
this.watchTargets = new EleventyWatchTargets();
this.watchTargets = new EleventyWatchTargets(this.eleventyConfig);
this.watchTargets.addAndMakeGlob(this.config.additionalWatchTargets);
this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies;

/** @member {Object} - tbd. */
this.fileSystemSearch = new FileSystemSearch();
Expand Down Expand Up @@ -801,7 +801,10 @@ Arguments:

// Note: these are sync events!
// `templateModified` is an alias for resourceModified but all listeners for this are cleared out when the config is reset.
eventBus.emit("eleventy.templateModified", changedFilePath, usedByDependants);
eventBus.emit("eleventy.templateModified", changedFilePath, {
usedByDependants,
relevantLayouts,
});
eventBus.emit("eleventy.resourceModified", changedFilePath, usedByDependants, {
viaConfigReset: isResetConfig,
relevantLayouts,
Expand Down Expand Up @@ -1004,7 +1007,7 @@ Arguments:
* @method
*/
async _initWatchDependencies() {
if (!this.watchTargets.watchJavaScriptDependencies) {
if (!this.eleventyConfig.shouldSpiderJavaScriptDependencies()) {
return;
}

Expand Down
23 changes: 12 additions & 11 deletions src/EleventyWatchTargets.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,16 @@ import JavaScriptDependencies from "./Util/JavaScriptDependencies.js";
import eventBus from "./EventBus.js";

class EleventyWatchTargets {
constructor() {
#templateConfig;

constructor(templateConfig) {
this.targets = new Set();
this.dependencies = new Set();
this.newTargets = new Set();
this._watchJavaScriptDependencies = true;
this.isEsm = false;

this.graph = new DepGraph();
}

set watchJavaScriptDependencies(watch) {
this._watchJavaScriptDependencies = !!watch;
}

get watchJavaScriptDependencies() {
return this._watchJavaScriptDependencies;
this.#templateConfig = templateConfig;
}

setProjectUsingEsm(isEsmProject) {
Expand Down Expand Up @@ -111,7 +105,7 @@ class EleventyWatchTargets {

// add only a target’s dependencies
async addDependencies(targets, filterCallback) {
if (!this.watchJavaScriptDependencies) {
if (this.#templateConfig && !this.#templateConfig.shouldSpiderJavaScriptDependencies()) {
return;
}

Expand Down Expand Up @@ -146,6 +140,13 @@ class EleventyWatchTargets {
for (let dep of isImportedInTheChangedFile) {
paths.add(dep);
}

// Use GlobalDependencyMap
if (this.#templateConfig) {
for (let dep of this.#templateConfig.usesGraph.getDependantsFor(filePath)) {
paths.add(dep);
}
}
}

eventBus.emit("eleventy.importCacheReset", paths);
Expand Down
23 changes: 16 additions & 7 deletions src/Engines/JavaScript.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ class JavaScript extends TemplateEngine {
this.instances = {};

this.cacheable = false;
EventBusUtil.soloOn("eleventy.templateModified", (inputPath, usedByDependants = []) => {
EventBusUtil.soloOn("eleventy.templateModified", (inputPath, metadata = {}) => {
let { usedByDependants, relevantLayouts } = metadata;
// Remove from cached instances when modified
let instancesToDelete = [TemplatePath.addLeadingDotSlash(inputPath), ...usedByDependants];
let instancesToDelete = [
inputPath,
...(usedByDependants || []),
...(relevantLayouts || []),
].map((entry) => TemplatePath.addLeadingDotSlash(entry));
for (let inputPath of instancesToDelete) {
if (inputPath in this.instances) {
delete this.instances[inputPath];
Expand Down Expand Up @@ -74,11 +79,7 @@ class JavaScript extends TemplateEngine {
}
}

async getInstanceFromInputPath(inputPath) {
if (this.instances[inputPath]) {
return this.instances[inputPath];
}

async #getInstanceFromInputPath(inputPath) {
let isEsm = this.eleventyConfig.getIsProjectUsingEsm();
const mod = await EleventyImport(inputPath, isEsm ? "esm" : "cjs");

Expand All @@ -93,6 +94,14 @@ class JavaScript extends TemplateEngine {
return inst;
}

async getInstanceFromInputPath(inputPath) {
if (!this.instances[inputPath]) {
this.instances[inputPath] = this.#getInstanceFromInputPath(inputPath);
}

return this.instances[inputPath];
}

/**
* JavaScript files defer to the module loader rather than read the files to strings
*
Expand Down
23 changes: 20 additions & 3 deletions src/GlobalDependencyMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { DepGraph } from "dependency-graph";
import debugUtil from "debug";
import { TemplatePath } from "@11ty/eleventy-utils";

import JavaScriptDependencies from "./Util/JavaScriptDependencies.js";
import PathNormalizer from "./Util/PathNormalizer.js";

const debug = debugUtil("Eleventy:Dependencies");
Expand All @@ -11,10 +12,20 @@ class GlobalDependencyMap {
static LAYOUT_KEY = "layout";
static COLLECTION_PREFIX = "__collection:";

#templateConfig;

reset() {
this._map = undefined;
}

setIsEsm(isEsm) {
this.isEsm = isEsm;
}

setTemplateConfig(templateConfig) {
this.#templateConfig = templateConfig;
}

setConfig(config) {
if (this.config) {
return;
Expand All @@ -23,8 +34,8 @@ class GlobalDependencyMap {
this.config = config;

// These have leading dot slashes, but so do the paths from Eleventy
this.config.events.once("eleventy.layouts", (layouts) => {
this.addLayoutsToMap(layouts);
this.config.events.once("eleventy.layouts", async (layouts) => {
await this.addLayoutsToMap(layouts);
});
}

Expand Down Expand Up @@ -60,8 +71,9 @@ class GlobalDependencyMap {
}

// Eleventy Layouts don’t show up in the dependency graph, so we handle those separately
addLayoutsToMap(layouts) {
async addLayoutsToMap(layouts) {
let normalizedLayouts = this.normalizeLayoutsObject(layouts);

// Clear out any previous layout relationships to make way for the new ones
this.removeLayoutNodes(normalizedLayouts);

Expand All @@ -81,6 +93,11 @@ class GlobalDependencyMap {
for (let pageTemplate of normalizedLayouts[layout]) {
this.addDependency(pageTemplate, [layout]);
}

if (this.#templateConfig?.shouldSpiderJavaScriptDependencies()) {
let deps = await JavaScriptDependencies.getDependencies([layout], this.isEsm);
this.addDependency(layout, deps);
}
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/TemplateConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class EleventyPluginError extends EleventyBaseError {}
*/
class TemplateConfig {
#templateFormats;
#runMode;

constructor(customRootConfig, projectConfigPath) {
this.userConfig = new UserConfig();
Expand Down Expand Up @@ -119,6 +120,18 @@ class TemplateConfig {
return this.directories.input;
}

setRunMode(runMode) {
this.#runMode = runMode;
}

shouldSpiderJavaScriptDependencies() {
// not for a standard build
return (
(this.#runMode === "watch" || this.#runMode === "serve") &&
this.userConfig.watchJavaScriptDependencies
);
}

/**
* Normalises local project config file path.
*
Expand All @@ -143,6 +156,7 @@ class TemplateConfig {

setProjectUsingEsm(isEsmProject) {
this.isEsm = !!isEsmProject;
this.usesGraph.setIsEsm(isEsmProject);
}

getIsProjectUsingEsm() {
Expand Down Expand Up @@ -492,6 +506,8 @@ class TemplateConfig {
get usesGraph() {
if (!this._usesGraph) {
this._usesGraph = new GlobalDependencyMap();
this._usesGraph.setIsEsm(this.isEsm);
this._usesGraph.setTemplateConfig(this);
}
return this._usesGraph;
}
Expand Down
4 changes: 3 additions & 1 deletion src/Util/EsmResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ export async function resolve(specifier, context, nextResolve) {
// Not a relative import and not a file import
// Or from node_modules (perhaps better to check if the specifier is in the project directory instead)
if (
(!specifier.startsWith("./") && !specifier.startsWith("file:")) ||
(!specifier.startsWith("../") &&
!specifier.startsWith("./") &&
!specifier.startsWith("file:")) ||
context.parentURL.includes("/node_modules/")
) {
return nextResolve(specifier);
Expand Down
4 changes: 3 additions & 1 deletion test/EleventyTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ test("Eleventy process.ENV", async (t) => {
});

test("Eleventy file watching", async (t) => {
let elev = new Eleventy("./test/stubs", "./test/stubs/_site");
let elev = new Eleventy("./test/stubs", "./test/stubs/_site", {
runMode: "watch" // required to spider deps
});
elev.setFormats("njk");

await elev.init();
Expand Down
4 changes: 3 additions & 1 deletion test/EleventyWatchTargetsTest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import test from "ava";

import TemplateConfig from "../src/TemplateConfig.js";
import EleventyWatchTargets from "../src/EleventyWatchTargets.js";
import JavaScriptDependencies from "../src/Util/JavaScriptDependencies.js";

Expand Down Expand Up @@ -89,7 +90,8 @@ test("JavaScript addDependencies (one file has two dependencies)", async (t) =>
});

test("JavaScript addDependencies (skip JS deps)", async (t) => {
let targets = new EleventyWatchTargets();
let templateConfig = new TemplateConfig();
let targets = new EleventyWatchTargets(templateConfig);
targets.setProjectUsingEsm(true);
targets.watchJavaScriptDependencies = false;
await targets.addDependencies("./test/stubs/dependencies/two-deps.11ty.cjs");
Expand Down

0 comments on commit 1abffef

Please sign in to comment.