Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why the production bundle size is significantly larger that create-react-app #2909

Closed
midnightcodr opened this issue Apr 9, 2019 · 11 comments · Fixed by #2979
Closed

Why the production bundle size is significantly larger that create-react-app #2909

midnightcodr opened this issue Apr 9, 2019 · 11 comments · Fixed by #2979

Comments

@midnightcodr
Copy link

I did a very simple experiment with the following settings

index.html (used for parcel-bundler only as create-react-app creates one automatically)

<html>
<body>
  <div id="root"></div>
  <script src="./index.js"></script>
</body>
</html>

index.js (also used in the project initialized with create-react-app)

import React from 'react'
import ReactDOM from 'react-dom'
import { FaBeer } from 'react-icons/fa'

const App = () => (
  <h1>
    Let's have some <FaBeer />!
  </h1>
)

ReactDOM.render(<App />, document.getElementById('root'))

./node_modules/.bin/parcel --version
1.12.3
./node_modules/.bin/parcel build index.html
parcel-build

While in a separate project initialized with create-react-app (2.1.8), the bundle size is way much smaller
cra-build-after-gzip

Without gzip:
cra-build

Nodejs version: 8.14.1
OS: Mac OSX Mojave

Can someone tell me why the bundle size difference is so significant? Are there any options I can use to improve/reduce the bundle size using parcel?

@mischnic
Copy link
Member

mischnic commented Apr 9, 2019

Tree shaking (parcel build --experimental-tree-shaking) should do precisely that. But there are (at least two issues):

  • react-icons has index.mjs and index.js in their react-icons/fa folder. To use the modern ES6 code suitable for treeshaking index.mjs needs to be preferred over index.js (this is quite an uncommon way of doing this). You can work around this by using import { FaBeer } from 'react-icons/fa/index.mjs'.

  • The bigger issue is that Parcel's treeshaking algorithm doesn't understand that exports like these can be shaken (currently, the second statement prevents that):

export var Fa500px = function (props) {
  return /*...*/;
};
Fa500px.displayName = "Fa500px"; // <--------------------

Discussion regarding bundle size in react-icons: https://github.com/react-icons/react-icons/issues/154

@midnightcodr
Copy link
Author

Thanks @mischnic for the quick response however I am getting

error: unknown option `--experimental-tree-shaking'

I am using version 1.12.3. Please advise.

@midnightcodr
Copy link
Author

Ok I found out the option is actually --experimental-scope-hoisting but it didn't help to reduce the bundle size much (using mjs import), I guess as @mischnic has already pointed out in the second problem of react-icons module, this bundle size issue won't be fixed until someone do something about react-icons or parcel-bundler, I am saying this is because create-react-app got it right.

@mischnic
Copy link
Member

Ok I found out the option is actually --experimental-scope-hoisting

Sorry, I always mix up these terms.
The rest of your comment is correct.

@midnightcodr
Copy link
Author

Sorry, I always mix up these terms.

No worries, thanks for helping out.

@mischnic
Copy link
Member

I'm keeping this open because

export var Fa500px = function (props) {
  return /*...*/;
};
Fa500px.displayName = "Fa500px";

is probably a common pattern and should be supported (at least this simple case).

@mischnic mischnic reopened this Apr 10, 2019
@midnightcodr
Copy link
Author

is probably a common pattern and should be supported (at least this simple case).

That would be great. I am struggling with this particular react-icons module at the moment and it doesn't make sense if I have to switch back to CRA just to keep the bundle size down.

@devongovett
Copy link
Member

Should be fixed by #2979.

@midnightcodr
Copy link
Author

Thanks @devongovett for making the changes. When will this update become available? At the moment the version of parcel-bundler stays at 1.12.3.

wbinnssmith pushed a commit that referenced this issue May 15, 2019
* WIP: v2 scope hoisting

* Support sideEffects flag

* Don't edit parcel 1

* Fix flow errors

* Type safe traversal filtering

* Run tests faster

* Base child assets on the same id base as parents

* Fix flow errors

* Only enable scope hoisting in production mode by default

* Fix lint

* Clean up

* Shake exports with pure property assignments (#2909)

* Send BundleGraph to packagers

* Lint

* Fix flow

* Clear scope cache before crawling

* Fix shake

* Define __esModule interop flag when requiring ES module from CommonJS

* Replace module.require in scope hoisting

* Fix assigning to exports from inside a function in scope hoisting

* Format
@JulienDemarque
Copy link

@devongovett Has parcel been tested out for tree-shaking react-icons? I just tried to update parcel to the latest version and the problem still persists.

@mischnic
Copy link
Member

mischnic commented Oct 9, 2019

@JulienDemarque I just tested this with the current Parcel 2 build and doing import { FaBeer } from 'react-icons/fa' will indeed only include that single icon. (Not in Parcel 1.x.x)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants