eleventy
eleventy copied to clipboard
Issues with watching JS dependencies declared in configuration
Filed via @anandchowdhary
https://github.com/11ty/eleventy/issues/701#issuecomment-575613848
Following up on this discussion from Discord : https://discordapp.com/channels/741017160297611315/741017160297611319/757230379202773002
The issue at hand on Discord is in a JS template, but I think it is the exact same issue mentioned here.
The "DeleteRequireCache" utility should probably delete the Module children cache entries also, using require.cache[normalizedPath].children in a recursive loop here :
https://github.com/11ty/eleventy/blob/330191c10b9ab4b93a3abcf6406bbc350a47aa7d/src/Util/DeleteRequireCache.js#L8-L11
I could get a PR together, just checking for a green light and if such a fix is not already in the pipeline.
@AurelienStebe Did you develop a solution or workaround for this? I'm having a few issues with changes to required JS files not triggering a refresh (or in some cases requiring that I restart the server). I'm seeing it with files required in the config, and files required in layouts.
No, this was just a drive-by bug fix. I had the exact same issue in my own project the week before, so I knew the solution.
It should really just need a few lines of code : before deleting the module itself from the require cache, just loop on its children and call the function recursively. Unfortunately, it needs to be fixed in this very file in Eleventy, I don't think you can do much from outside (apart from deleting the whole cache maybe, but that's about the same as restarting the process). This should make sure that dependencies of dependencies are re-read from disk in "live" mode, however I don't know if they are all "watched" correctly (but there is eleventyConfig.addWatchTarget() for that).
I thought work was being done on the "--watch" mode and incremental builds, so I didn't move forward at the time.
Yeah I just hit the same problem. Any dependencies of an .11ty.js layout are not correctly updated when the page reloads. This makes it almost impossible to work with JS templates :/
I tried the recursive cache deletion of children suggested above but it doesn't seem to help. I've never really played with Node's cache before so I probably messed it up 😓
The easiest workaround I've found is to just inline all my components and helpers into the layout file for now, so I don't have to require anything...
@zachleat is this in the pipeline or worth me getting a PR together?
I tried the recursive cache deletion of children suggested above but it doesn't seem to help. I've never really played with Node's cache before so I probably messed it up
Same here. Couldn't get it to work either. @oliverjam could you post your code and I'll give it a run?
For those using js templates, one workaround is to manually require your js files and not calling shortcode with this.
You loose access to data pages but hot reloading is working.
Weird : dependencies in layout files are not reloading.
I had a similar issue where the page would hot reload but any changes made to includes were not being made in the rendered copy (unless I restarted eleventy via the command line).
I was able to resolve the issue by making sure chokidar was installed and watch: true was set in the FileSystemLoader options in my .eleventy.js file:
const nunjucksEnvironment = new Nunjucks.Environment(
new Nunjucks.FileSystemLoader("src/includes", { watch: true })
);
Hi, are there any solutions on this bug right now?
Just popping in here to say I'm running into the same issue on WSL2 with JS dependencies inside of my .11ty.js templates. 11ty seems to pick up the changes, but the output remains the original cached content.
Editing to say that manually requiring my JS layout files in the JS templates that call them seems to have fixed the issue as far as I can tell.
Shipping #2479 with 2.0.0-canary.18—would love a retest after the next canary ships! (and thank you to @Snapstromegon!)
Closing as the PR was shipped!
Hey @zachleat, I'm noticing this issue all over again on 2.0.1 using the new dev server on WSL2.
I have the following directory structure:
src
_includes
components
component.11ty.js
layouts
layout.11ty.js
content
index.11ty.js
Where index pulls layout via data { layout: 'layouts/layout.11ty.js' }, and layout requires component.
Updating component triggers 11ty to build, but the refreshed page doesn't display the changes. I'm forced to save layout twice, which then reflects the changes in component. Oddly enough, saving index doesn't trigger the changes either...
I'm assuming https://github.com/11ty/eleventy/issues/1435 is related.
Edit: looks like you can get around this by declaring component's require inside layout's render function:
function render(data) {
let component = require('../components/component.11ty').render(data);
return String.raw`
${component}
`;
}
module.exports = {
render,
};
@substrae can you test the latest on GitHub? I’m guessing #2903 is the culprit
@zachleat
You betcha! I'll take a peek after work today. 🚀
@zachleat Hmm, installing fresh from master results in the same problem I described above. I created a mock project with the exact same basic folder structure and imports, and saving component triggers a build, but the change isn't reflected in the browser despite the page refresh.
Edit: for reference, the compiled HTML doesn't contain the change either.
Edit 2: my temporary solution from above also still works here, where moving the require into the render function solves the problem.
@substrae: Thank you for this! 🤗 I am messing around with Preact and TypeScript for templating and couldn't figure out what was going on. This is what I have and I'm happy with it:
// base.11ty.tsx
import { h, Fragment } from "preact";
import { render as r } from "preact-render-to-string";
import type { EleventyData } from "../types/eleventy";
import { Shell } from "../components";
export function render(data: EleventyData) {
const { Post } = require("./post");
const { Photo } = require("./photo");
return r(
<Shell data={data}>
{data.category === "photos" ? (
<Photo data={data} />
) : (
<Post data={data} />
)}
</Shell>
);
}
And here's the Post component as an example:
// post.tsx
import { h } from "preact";
import { parse } from "preact-parser";
import { PostData } from "../types/data";
import { postDate } from "../helpers";
import { Tags } from "../components";
export const Post = ({ data }: { data: PostData }) => (
<article>
<header>
<h1>
<a href={data.url}>{data.title}</a>
</h1>
</header>
{parse(data.content)}
<footer>
<Tags tags={data.tags} />
<time>{postDate(data.date, "dd MMMM yy")}</time>
</footer>
</article>
);
Same issue with Preact and Typescript. Have to dynamic import/ require in the renderer for it to rebuild, when the imported components change.
same issue again
Still having this issue as well, and unfortunately I've run into a context where I can't move the require into the render() due to needing it in the data variable declaration. 😢
// Page data =======================================================================================
let data = {
pagination: {
data: 'guide_data',
size: 1,
},
guide_data: require('../_data/guides').heavensward, // This is causing the problem
permalink: function (data) {
return data.pagination.items[0].slug;
},
};
// Script ==========================================================================================
function render(data) {
// Local component imports
const guide_layout = require('../_layouts/guide.11ty');
// Return the layout render
return guide_layout.render(data, data.pagination.items[0]);
}
module.exports = {
data,
render,
};