2

I'm trying to make react-loadable work with ServerSide Rendering. I've got a quite big app using multiple HOCs which connect components, add routers etc.

Components seem to go okay, instead the smart components connected via react-redux or other HOCs. react-loadable doesn't seem to so this as seperate modules and in the .json that is created undefined is thrown.

Example of dumb components loaded correctly:

"common/HeaderTitle": [
    {
      "id": 667,
      "name": "./src/app/components/common/HeaderTitle.jsx",
      "file": "0.650d44243e1a15fa7627.js"
    },
    {
      "id": 667,
      "name": "./src/app/components/common/HeaderTitle.jsx",
      "file": "0.650d44243e1a15fa7627.js.map"
    },
    ...
],

Example of smart components which don't load:

"undefined": [
    {
      "id": 626,
      "name": "./src/app/components/modules/Home/index.jsx",
      "file": "0.650d44243e1a15fa7627.js"
    },
    ...
],

The html render of my server looks like the following. Everything in here is copied from the official docs:

app.use((req, res) => {
    const modules = [];

    const html = SSR ? renderToString(
        <Provider store={store}>
            <StaticRouter location={req.url} context={{}}>
                <Loadable.Capture report={moduleName => modules.push(moduleName)}>
                    <App />
                </Loadable.Capture>
            </StaticRouter>
        </Provider>,
    ) : ' ';

    console.log('modules', modules);
    const bundles = getBundles(stats, modules);
    console.log('bundles', bundles);

    res.status(200).send(renderFullPage({ html, bundles }));
});

Which logs as expected:

modules [ './modules/Home' ]
bundles [ undefined ]
TypeError: Cannot read property 'file' of undefined

This is really driving me crazy. The package seems really good and I would like to use it. But I can't find anything about issues like this and there ain't an issue section on Github.

Open to any suggestion or help. Thanks in advance.

ronnyrr
  • 1,481
  • 3
  • 26
  • 45

1 Answers1

2

Just a wild guess, but I think it has something to do with the fact you're importing the index.js, and react-loadable doesn't pick this up in Loadable.Capture. Or the wepback plugin doesn't create the correct mapping in the react-loadable.json file.

A trick I used in a production app (complete with react-router, redux, react-loadable) is to use webpack's named chunks:

const AsyncComponent = Loadable({
    loader: () => import(/* webpackChunkName: "myNamedChunk" */ './SomeComponent'),
    modules: ['myNamedChunk']
});

This way you control the module name and explicitly tell react-loadable what to map.

I also wrote an article on how to achieve this in a create-react-app project: https://medium.com/bucharestjs/upgrading-a-create-react-app-project-to-a-ssr-code-splitting-setup-9da57df2040a

Andrei Duca
  • 372
  • 2
  • 11
  • Thanks for your reply. Didn't knwo about the chunk names. I did add the chunk names, which is a great improvement. Unfortunately this doesn't solve my issue. Webpack is nicely creating the chunks, but in `react-loadable` it keeps indenting it in `undefined`. but it seems like the modules aren't even working. I've added modules `404` for the `NotFound` component but in the json it still refers to `"./common/NotFound"`. Also checked your article, didn't see any breaking changes there either.. But thanks again for your reply. Will try some other things.. – ronnyrr Jan 30 '18 at 18:26