Liam White
Is Webpack the best JS bundler we have?

Some time ago, the Phoenix project switched from using Brunch as its JS bundler to Webpack. Brunch is effectively abandoned, and Webpack is currently somewhat of an industry standard for web bundling, being also used by other web frameworks.

Since being on a rather outdated asset pipelines isn't really in anyone's best interest, we got this updated in Philomena. And while CSS compiling was fine, if a lot slower, there was a rather large regression in the size of our compiled JS:

Where did we get an extra 12KB from?

Modules

Webpack module support is not directly provided by a bundler like Rollup, the solution we originally used (as a Brunch plugin) for our code. It has its own module loader which it uses to resolve imports to things like CSS and other asset files and process them specially. While on its own this is fine, it interacts poorly with the next item.

Runtime chunk

When Webpack encounters an import that is a JS file, it inserts a UMD/CommonJS module support thunk that wraps each original source file so that the imports can be resolved at runtime. With the Rollup Brunch plugin, we were resolving all imports at compile time.

Babel

Webpack recommends Babel by default. Babel uses a list of supported browsers, or a default if one is not provided, and tries to automatically provide runtime shims ("polyfills") for functionality which is not supported by the user's browser. Some of these shims resulted in code becoming much larger than expected.

Conclusion

Use Webpack at your own peril. We have added the Rollup plugin to Philomena to restore the old bundling behavior, which has eliminated the chunks, configured our Babel browsers list to be a little more conservative in the polyfills it emits, and removed unused functionality from our code that was resulting in some unnecessary polyfills being emitted as well. Hopefully in the future, there will be a bundling solution that takes the place of Webpack.