Code Splitting in Create React App


#1

From @jayair on Sun May 21 2017 23:26:58 GMT+0000 (UTC)

Link to chapter - http://serverless-stack.com/chapters/code-splitting-in-create-react-app.html

Copied from original issue: https://github.com/AnomalyInnovations/serverless-stack-com/issues/90


#2

From @qborreda on Tue May 23 2017 09:05:51 GMT+0000 (UTC)

Ok, while this is very useful, it really assumes all components to be found exactly in the same folder, right? (at least the main ones, you can then compose your views from there), but how do you then those components have sub routes, or the different routes in a component lead to async load components in different folders? (first thing on the top of my mind would be to pass path as a prop)


#3

From @minhna on Tue May 23 2017 13:37:27 GMT+0000 (UTC)

const { default: component } = await import(``../containers/${componentName}``);
How is this possible? Dynamic import.


#4

From @jayair on Tue May 23 2017 14:10:52 GMT+0000 (UTC)

@qborreda Yeah, it does assume that. But I’m pushing an update soon that fixes this.

@minhna Yeah it is a dynamic import that’s available in the new CRA.


#5

From @jayair on Tue May 23 2017 15:24:49 GMT+0000 (UTC)

@qborreda Updated the chapter with a more generic way to do the imports and it also allows us to control the chunks that are generated - 3cf522260e1133c3055862b2a3a6e03afe511d07


#6

From @minhna on Wed May 24 2017 01:12:33 GMT+0000 (UTC)

@jayair I’m using meteor 1.5 rc6 and it doesn’t work. Do you have any idea? Thanks for your help.


#7

From @jayair on Wed May 24 2017 14:06:59 GMT+0000 (UTC)

@minhna This is for Create React App and it’s using Webpack 2 internally. I’m not sure how it works in other places.


#8

From @gaearon on Thu May 25 2017 22:07:23 GMT+0000 (UTC)

There’s one more issue: asyncComponent() is called in a rendering function so anytime it executes, a completely new component class is created. This will destroy all state of components below.


#9

From @gaearon on Thu May 25 2017 22:14:00 GMT+0000 (UTC)

It seems like you could make <AsyncRoute> instead of asyncComponent. <AsyncRoute> could take getComponent as a prop and do the same setState thing, rendering Route when the component in the state is ready. Since <AsyncRoute> is a regular component that’s the same every time, it wouldn’t have this issue.


#10

From @gaearon on Thu May 25 2017 23:23:23 GMT+0000 (UTC)

Hmm. Now that I think of it I guess it’s not a bug issue because the prop is only used once. But it’s still unfortunate the class is generated on every top level render. So AsyncRoute as a component would work better.


#11

From @jayair on Fri May 26 2017 08:04:01 GMT+0000 (UTC)

@gaearon That’s a good point. It doesn’t make sense that asyncComponent runs every time. Let me play around with turning it into a component.


#12

From @jayair on Tue May 30 2017 15:07:13 GMT+0000 (UTC)

Updated with fix. Now asyncComponent is only run once as opposed to every time - d0fe33f0828285396a0ec128a9bc8b041ac704e8

For folks looking for an explanation; React Router will create a new instance of the component if an inline function is passed into the component prop as opposed to simply updating the existing component. To avoid this, we run the asyncComponent once at the top and pass in the resulting component to the routes.


#13

From @chrisbro on Sat Jun 03 2017 18:59:21 GMT+0000 (UTC)

This was the first chapter that gave me a problem - saying “unexpected token” on the import statements in Routes.js.


#14

From @jayair on Mon Jun 05 2017 00:44:42 GMT+0000 (UTC)

@chrisbro We use the dynamic import() in this chapter and that’s available in the new Create React App. Can I see your package.json?


#15

From @chrisbro on Mon Jun 05 2017 23:45:38 GMT+0000 (UTC)

@jayair Sure thing. Here you go! Of note: I started creating this with node 4.8.3, and during troubleshooting this realized how far behind that was and upgraded to 8.0.0 with the same behavior. I suspect that the detection of an old version of node gave me an old version of something here? Some dependencies stripped out to simplify things.

{
  "name": "test",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^15.5.4",
    "react-bootstrap": "^0.31.0",
    "react-router-dom": "^4.1.1",
    "react-textarea-autosize": "^5.0.6"
  },
  "devDependencies": {
    "react-addons-test-utils": "^15.5.1",
    "react-dom": "^15.5.4",
    "react-scripts": "0.9.5",
    "react-test-renderer": "^15.5.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "predeploy": "npm run build",
    "eject": "react-scripts eject"
  }
}

#16

From @jayair on Tue Jun 06 2017 10:32:21 GMT+0000 (UTC)

@chrisbro Yeah the Create React App’s react-scripts is out of date for you. Here is the one that we have in the tutorial - https://github.com/AnomalyInnovations/serverless-stack-demo-client/blob/code-splitting-in-create-react-app/package.json#L14

Upgrading is pretty simple, here are the instructions - https://github.com/facebookincubator/create-react-app/releases/tag/v1.0.0


#17

From @chrisbro on Tue Jun 06 2017 23:47:52 GMT+0000 (UTC)

@jayair Upgraded and confirmed that was the problem. Thank you!


#18

From @tmedetbekov on Tue Jun 13 2017 06:37:06 GMT+0000 (UTC)

Can you please help me understand? Why after splitting the code the main.js size decreased to 1.2kb and 0.chunk.js size increased to 21kb?

Before:

after:


#19

From @jayair on Tue Jun 13 2017 17:55:21 GMT+0000 (UTC)

@tmedetbekov I’m not sure what your code is like, so I can’t give you an exact answer for your case. But AFAIK when you are code splitting, each chunk is bundled with it’s dependencies. So it is possible that chunk 0 is including a dependency that it needs and maybe that dependency is also needed in the main chunk. Hence, the size of main didn’t reduce all that much.


#20

From @origicom on Sat Aug 12 2017 11:54:37 GMT+0000 (UTC)

seems these lines are faulty:

const AsyncHome = Loadable({
  loader: () => import('./containers/Home'),
  LoadingComponent: MyLoadingComponent
});

LoadingComponent:
shouldnt that be

loading: