2

I want to bundle some React libs with Browserify and --require them, but was put off by the file size.

I use the following Browserify command:

browserify path/to/react.min.js path/to/react-dom.min.js > libs.js

Now, react.min.js is 21k, react-dom.min.js is 122k, but libs.js results in a whopping 269k. Surely there is not a Browserify overhead of 126k? When I look at libs.js there is a lot of added (unminified) React code. Where does this come from?

GijsjanB
  • 9,944
  • 4
  • 23
  • 27
  • So this looks like a similar question (http://stackoverflow.com/questions/27922208/how-to-keep-browserify-bundle-size-sensible-when-using-requires-for-thirdparty-s). Also I found this blog post that talks about remedies (https://shellmonger.com/2016/01/12/reduce-the-size-of-your-react-applications/) – Max Baldwin Dec 22 '16 at 19:21

1 Answers1

4

The problem is that Browserify is resolving the require call(s) in react-dom to the react module in node_modules. The package.json for that module specifies main as react.js - so you end up with a bundle that contains the the non-minified source in addition to react.min.js.

Note that if you bundle only react.min.js:

browserify \
--require ./node_modules/react/dist/react.min.js:react \
> bundle-react.js

The bundle size is only slightly larger than react.min.js:

ls -l node_modules/react/dist/react.min.js
... 21339 Dec 23 09:43 node_modules/react/dist/react.min.js

ls -l bundle-react.js
... 22006 Dec 23 11:56 bundle-react.js

To solve the problem, you need to tell Browserify to exclude react and react-dom, as you are going to provide an alternate mechanism for their being required - that is, you are going to specify the --require option:

browserify \
--exclude react \
--require ./node_modules/react/dist/react.min.js:react \
--exclude react-dom \
--require ./node_modules/react-dom/dist/react-dom.min.js:react-dom \
> bundle-lib.js

The bundle size should now be much closer to the combined, minified files:

ls -l node_modules/react/dist/react.min.js
... 21339 Dec 23 09:43 node_modules/react/dist/react.min.js

ls -l node_modules/react-dom/dist/react-dom.min.js
... 123996 Dec 23 09:43 node_modules/react-dom/dist/react-dom.min.js

ls -l bundle-lib.js
... 146227 Dec 23 11:39 bundle-lib.js

You should then be able to create an application bundle that requires react and react-dom from your library bundle. Note that the Browserify command to create the application bundle should specify the --exclude option for react and react-dom - so that they are required from the library bundle and not from node_modules:

browserify \
--exclude react \
--exclude react-dom \
app.js > bundle-app.js
cartant
  • 57,105
  • 17
  • 163
  • 197
  • Great explanation! Thank you. I'd much rather have Browserify and UglifyJS take care of it, but the build size difference is huge! When I create a `bundle-libs.js` with the unminified versions, `NODE_ENV=production` and pipe through UglifyJS, I end up with a 280k sized file. Is Facebooks minifier so much better than UglifyJS? – GijsjanB Dec 23 '16 at 07:56
  • I've not looked at it closely, but there are lots of files/modules in the `lib` directories inside `react` and `react-dom`. Each of those will get some Browserify boilerplate. It's possible that the mechanism used in the minified `dist` files is less verbose. Also, if you are using UglifyJS via a Browserify transform, the minification won't be applied to Browserify's boilerplate - only to the content of the modules imported into the bundle. – cartant Dec 23 '16 at 08:46