facebook / create-react-app

Set up a modern web app by running one command.
https://create-react-app.dev
MIT License
102.76k stars 26.87k forks source link

Modules not extracted to lazy loaded chunk if coming via an export of an index file #5989

Closed penx closed 5 years ago

penx commented 5 years ago

Is this a bug report?

Yes

Steps to Reproduce

Set up a project similar to https://github.com/penx/cra-code-splitting-exports

Specifically, say you have an index file for your components:

import Component1 from './component-one'
import Component2 from './component-two'

export {Component1, Component2};

Then in your application, you import Component1 in the main App and import Component2 via React.lazy/import()

Expected Behavior

I would expect the code from /src/components/component-two.js to be included in the lazy loaded chunk.

Actual Behavior

The code from /src/components/component-two.js is included on initial page load because it comes from /src/components/index.js so is included in the same bundle as src/components/component-one.js.

In the case of local modules, you can import from the module directly instead of going via an index file. Unfortunately you don't always have this option if you want to lazy load part of a dependency:

i.e.

if you have the following on app load:

import { someUtil } from 'my-library'

And the following is in a component that is lazy loaded:

import { aMuchLargerUtil } from 'my-library'

Then I would not want aMuchLargerUtil to be included in the initial bundle.

Reproducible demo

git clone git@github.com:penx/cra-code-splitting-exports.git
cd cra-code-splitting-exports
yarn && yarn build
serve -s build
miraage commented 5 years ago

When you import ./components in App.js, webpack loads the whole module and evaluates it. The only "issue" I can see here is why webpack can't tree-shake ComponentTwo, since it isn't used in main chunk.

miraage commented 5 years ago

I found a "documented hack". Create a package.json file in ./components directory with the following contents:

{
  "sideEffects": false
}
penx commented 5 years ago

ah that sounds good. I guess it means if ./components was actually a node module in dependencies, I could add it in to the package.json there... will give it a go.

penx commented 5 years ago

it worked! Thanks <3

penx commented 5 years ago

Demo of it working, including for CSS modules, here https://penx.github.io/govuk-frontend-react-example/