eleventy: Changes in dependencies to your Eleventy config file don’t cause the config file to be reloaded

Is your feature request related to a problem? Please describe. When a shortcode is defined in an external files and being require into .eleventy.js, modifying the shortcode will not reload the site

Reproduce steps:

  • Clone https://github.com/dephiros/11ty-tailwind/ and checkout 11ty-require-reload
  • Do yarn && yarn serve
  • Open the browser, notice TEST and TEST REQUIRE
  • Open .eleventy.js and modify Test shortcode, notice the browser will reload with the new change
  • Open _11ty/Test.js and change some text, notice the terminal is showing reload but the browser does not reflect the change

Describe the solution you’d like Change in code that is required by .eleventy.js should reflect in the browser

Describe alternatives you’ve considered I saw the issues mentioned in https://github.com/11ty/eleventy/issues/325 but it does not fix for me even with watch target. The shortcodes is still cached and require restarting the server

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 13
  • Comments: 16 (4 by maintainers)

Commits related to this issue

Most upvoted comments

Sorry to chime in super late here, y’all. This is indeed a bug. The goal is to not require re-starting the dev server (ever). But we have some work to get there, I think.

@jens-t Desired behavior would be that if a dependency of the config file changes it would reload the config, see https://www.11ty.dev/docs/watch-serve/#watch-javascript-dependencies I don’t think we need to add extra APIs here since we know the dependencies?

@chasemccoy, right. Even though shortcodes, filters, and so forth can reside in separate modules that you pass eleventyConfig, ultimately, they are all registered via .eleventy.js. That’s why those changes require the hard reload. Separate files or not, you’re technically modifying the configuration either way.

Is anyone getting this issue in 11ty 3? I’m on alpha 5, I’m using JavaScript components in a nested _src directory, e.g. in .eleventy.js:

import HeaderNav from './_src/components/global/HeaderNav.js';

export default function (eleventyConfig) {
  eleventyConfig.addShortcode('HeaderNav', function HeaderNavShortcode(currentPageUrl) {
    return new HeaderNav().render(currentPageUrl);
  });

  // The below makes no difference. Components changes are not reflected on refresh.
  // eleventyConfig.setServerOptions({
  //   watch: ['_src/components/**/*.js'],
  // });
}

Changes to HeaderNav trigger a refresh but the actual changes are not reflected unless I kill the server and start it up again. I should probably make a new issue for this if I can replicate.

The fix for this will ship with 2.0.0-canary.11

@zachleat The dependencies are not known for dynamic imports. Or maybe just not in my usecase?

I build an autoloader for my 11ty projects, so that all i have to do, is to create new files to add filter, shortcodes, transforms, tags and collections. This autoloader uses dynamic imports.

Example code for the autoloader:

const initAutoload = conf => {
  const typeMapping = [
    {
      type: 'filter',
      extension: 'js',
      method: 'addFilter'
    },
    {
      type: 'tags',
      extension: 'js',
      method: 'addNunjucksTag'
    },
    {
      type: 'collections',
      extension: 'js',
      method: 'addCollection'
    },
    {
      type: 'shortcodes',
      extension: 'js',
      method: (name, content) => {
        if (!content.paired || content.paired !== true) {
          (!content.async || content.async !== true)
            ? conf.addNunjucksShortcode(name, content.shortcode)
            : conf.addNunjucksAsyncShortcode(name, content.shortcode);
        }
        else {
          (!content.async || content.async !== true)
            ? conf.addPairedNunjucksShortcode(name, content.shortcode)
            : conf.addPairedNunjucksAsyncShortcode(name, content.shortcode);
        }
      }
    },
    {
      type: 'transforms',
      extension: 'js',
      method: 'addTransform'
    }
  ];

  const initType = data => {
    const files = path.resolve(conf11ty.paths[data.type]) + '/**/*.' + data.extension;
    glob.sync(files).forEach(file => {
      const name = path.parse(file).name;
      const content = require(file);
      typeof data.method === 'function'
        ? data.method(name, content)
        : conf[data.method](name, content);
    });
  };

  typeMapping.forEach(initType);
};

It’s akin to modifying the .eleventy.js file itself, which also requires an explicit call to rebuild/serve.

Actually, there is a config reset in watch mode, which is (only) triggered if .eleventy.js is modified (which was added in this commit: https://github.com/11ty/eleventy/commit/09973aecf48695b0e14d499b500bd9abd5015ac1).

I first thought, an easy workaround could be using the beforeWatch event to trigger a change event on .eleventy.js if there is a change in additonal imported config files, to trigger the built-in config reset. But this way the build would run twice, since there is no way to cancel the build from the beforeWatch event. So i ended up running my own chokidar instance for the files imported in .eleventy.js and trigger a change event on .eleventy.js from there. This feels very hacky, but still better than restarting the watch build on every change. 🙈

So a built-in way could perhaps be, to provide an option like addConfigResetGlob to have the option to configure additonal files that would trigger a config reset. 11ty watches these files automatically already (just static imports, not dynamic imports), but there is no config reset during watch for them.

@zachleat What do you think? Are there any disadvantages in providing something like this?