Loadable-components: Async chunks are not updated on the server

Created on 10 Feb 2019  路  2Comments  路  Source: gregberge/loadable-components

馃悰 Bug Report

Hi! Thanks for such a great tool!

Changes made to async modules after the first render are not reflected in the subsequently rendered html. It looks like async chunks are cached and won't get re-required after initial require on the server.

To Reproduce

  1. cd ./examples/server-side-rendering
  2. (optional) You might want to update ignore in nodemon.json from client to src/client to make sure that server will not get restarted on every change
  3. yarn dev
  4. Open http://localhost:9000 in browser, everything works as expected
  5. Make changes to src/client/letters/A.js
  6. Refresh the page

You will see something like

react-dom.development.js:506 Warning: Text content did not match. Server: "A" Client: "AA"

Server renders outdated html.

Expected behavior

Server renders html that is up-to-date.

Link to repo

https://github.com/smooth-code/loadable-components/tree/master/examples/server-side-rendering

envinfo

## System:
 - OS: macOS High Sierra 10.13.6
 - CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
 - Memory: 283.53 MB / 8.00 GB
 - Shell: 5.6 - /usr/local/bin/zsh
## Binaries:
 - Node: 10.15.1 - ~/.nvm/versions/node/v10.15.1/bin/node
 - Yarn: 1.9.2 - /usr/local/bin/yarn
 - npm: 6.4.1 - ~/.nvm/versions/node/v10.15.1/bin/npm
bug good first issue 馃 help wanted 馃啒

Most helpful comment

Hello @Vladislao, actually there is a bug yes, splitted chunks are not flushed form cache. We have to fix it. The smartRequire automatically clears cache in dev mode. And it is used to load the "main chunk", but it is not used to load splitted chunks.

The best workaround is to clean all splitted chunks (we know them thanks to stats) in the requireEntryPoint method.

If someone want to fix it, he is welcome!

All 2 comments

Deleting changed chunks from require.cache after webpack emits files seems to solve the problem. I've ended up using a simple plugin for 'node' compiler.

{
  apply(compiler) {
    compiler.hooks.afterEmit.tapAsync("webpack-invalidate-require", (stats, cb) => {
      const updatedFiles = stats.chunks
        .filter(v => v.rendered)
        .reduce((acc, v) => acc.concat(v.files), []);

      updatedFiles.forEach(v => {
        const fullpath = path.resolve(stats.compiler.outputPath, v);
        if (require.cache[fullpath]) {
          delete require.cache[fullpath];
        }
      })
      cb();
    });
  }
}

Hello @Vladislao, actually there is a bug yes, splitted chunks are not flushed form cache. We have to fix it. The smartRequire automatically clears cache in dev mode. And it is used to load the "main chunk", but it is not used to load splitted chunks.

The best workaround is to clean all splitted chunks (we know them thanks to stats) in the requireEntryPoint method.

If someone want to fix it, he is welcome!

Was this page helpful?
0 / 5 - 0 ratings