Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with watching JS dependencies declared in configuration #1312

Closed
zachleat opened this issue Jul 11, 2020 · 22 comments
Closed

Issues with watching JS dependencies declared in configuration #1312

zachleat opened this issue Jul 11, 2020 · 22 comments
Labels
bug: --serve restart Changes to projects shouldn’t need to restart dev server bug

Comments

@zachleat
Copy link
Member

Filed via @AnandChowdhary

image

#701 (comment)

@AurelienStebe
Copy link

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 :

module.exports = function deleteRequireCache(absoluteModulePath) {
const normalizedPath = path.normalize(absoluteModulePath);
delete require.cache[normalizedPath];
};

I could get a PR together, just checking for a green light and if such a fix is not already in the pipeline.

@esharri2
Copy link

esharri2 commented Jan 2, 2021

@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.

@AurelienStebe
Copy link

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.

@oliverjam
Copy link

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...

@tomglynch
Copy link

@zachleat is this in the pipeline or worth me getting a PR together?

@tomglynch
Copy link

tomglynch commented Feb 19, 2021

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?

@seb-celinedesign
Copy link

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.

@ZachSaucier
Copy link

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 })
);

@cnoss
Copy link

cnoss commented Oct 13, 2021

Hi, are there any solutions on this bug right now?

Snapstromegon added a commit to Snapstromegon/eleventy that referenced this issue Jul 1, 2022
This change adds a "PathNormalizer" with tests which converts all paths to be unix compatible (replace "\" with "/"). That way auto reloading dependencies of the config also works on windows.

Sadly nested dependencies still always lag exactly one update behind, so if you have the following dependency graph:
- .eleventy.js depends on
- middle.js depends on
- nested.js

and you update nested, you see the following:
- do update 1 -> no result
- do update 2 -> see update 1
- do update 3 -> see update 2

During a short lookaround, I was unable to resolve this issue.

Signed-off-by: Raphael Höser <[email protected]>
@JoshBeveridge
Copy link

JoshBeveridge commented Sep 19, 2022

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.

zachleat added a commit that referenced this issue Nov 18, 2022
…dency-monitoring

#1312 Improve situation for dependency monitoring
@zachleat
Copy link
Member Author

zachleat commented Nov 18, 2022

Shipping #2479 with 2.0.0-canary.18—would love a retest after the next canary ships! (and thank you to @Snapstromegon!)

@zachleat zachleat added this to the Eleventy 2.0.0 milestone Nov 18, 2022
@zachleat zachleat added the bug: --serve restart Changes to projects shouldn’t need to restart dev server label Nov 18, 2022
@zachleat
Copy link
Member Author

zachleat commented Dec 7, 2022

Closing as the PR was shipped!

@JoshBeveridge
Copy link

JoshBeveridge commented Apr 17, 2023

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 #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,
};

@zachleat
Copy link
Member Author

@substrae can you test the latest on GitHub? I’m guessing #2903 is the culprit

@JoshBeveridge
Copy link

@zachleat

You betcha! I'll take a peek after work today. 🚀

@JoshBeveridge
Copy link

JoshBeveridge commented Apr 17, 2023

@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.

@afreeorange
Copy link

afreeorange commented Sep 22, 2023

@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>
);

@briansunter
Copy link

Same issue with Preact and Typescript. Have to dynamic import/ require in the renderer for it to rebuild, when the imported components change.

@avinashkanaujiya
Copy link

same issue again

@JoshBeveridge
Copy link

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,
};

@kubarenatioN
Copy link

hey @zachleat , first of all, thank you and your team for such amazing tool!

I'd like to share, that I also experience the problem with my eleventy config not refreshing the browser with most recent changes in .js files, which were placed in separate folders and required into .eleventy.js (aka dependencies)

I have the following files structure:

  • config
    • shortcodes
      • shortcode-A.js
  • eleventy.js

then I require my dependency
const shortcodeA = require("./shortcodes/shortcode-A")

and register as shortcode
eleventyConfig.addPairedShortcode('shortcodeA', shortcodeA)

so when any changes were made in shortcode-A.js cli responds with "re-building" of _site folder, but actual result on the browser page still shows stale html.

on the other hand, when I manually save eleventy.js file, the same re-build happens but at this time browser also displays the most fresh changes from shortcode-A.js

using "@11ty/eleventy": "^3.0.0-alpha.17" and CommonJS

@zachleat
Copy link
Member Author

@kubarenatioN can you file a new issue with a reduced test case? I attempted to reproduce with your instructions and found that editing shortcode-A.js showed fresh content after update.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug: --serve restart Changes to projects shouldn’t need to restart dev server bug
Projects
None yet
Development

No branches or pull requests