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

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

Without gzip:

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?
Tree shaking (parcel build --experimental-tree-shaking) should do precisely that. But there are (at least two issues):
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'.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
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.
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.
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.
Sorry, I always mix up these terms.
No worries, thanks for helping out.
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).
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.
Should be fixed by https://github.com/parcel-bundler/parcel/pull/2979.
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.
@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.
@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)