Static module loading and bundling
Tl;dr: Code in ES6, use ES6 module syntax and use webpack 2 for complex apps, rollup for libraries and simpler js.
Our old approach: Webpack 2
Managing dependencies is a complex task that bundlers like browserify, webpack and rollup aim to solve. A single react component for example could depend on many individual packages.
Webpack always stood out with a great all-in one experience and the possibility to create web applications with multiple entry points and use code splitting to create common dependencies which can be cached and reused.
Example: Saving bandwidth with Multiple Entry Points
As a short example a webapp with two sections to illustrate when this is useful:
- Section A (http://example.com/visualization/*): Has a 3D animation embedded in a react component.
- Section B (http://example.com/statistics/*): Has a graphing library in a react component
Unoptimized: So traditionally we would mash everything in a single bundle / file:
- Section A: bundle.js (React, Utility, Three.js, Chart.js) (800k)
Optimized: With multiple entry points this can be split more intelligently:
- Section A: base-bundle.js (React, Utility) (200k) + three-bundle.js (Three.js) (400k) = 600k
- Section B: base-bundle.js (React, Utility) (200k) + chart-bundle.js (Chart.js) (200k) = 400k
Our updated approach: Webpack 2 + Rollup
The new module builder Rollup uses ES6 natively and has many advantages. A comparison with the ES6 capabilities of webpack 2 is outlined in this comment from Rollups creator Richard Harris. The main advantages are:
- Rollup uses ES6 module syntax natively, which get’s you a cleaner syntax than commonjs and further future-proofing.
- It produces smaller bundles
- It provides us with the option to specify an own ES6 entry point in NPM packages which is extremely useful if you want to reuse your own code by packaging it. You will still have to build it, though, since there has to be a common set of advanced ES6 features across packages.
As Richard states: Rollup is by far the best choice for libraries, as it provides us with true ES6 interoperability and smaller bundles in complex scenarios. In complex applications webpack 2 still has the edge with advanced features like code splitting and while webpacks ES6 features don’t reach as deep as Rollup’s, it rarely makes a significant difference in production.
Dynamically Loading Modules
Tl;dr: Use webpack 2 and its “System.import”. You probably won’t need it in simpler applications.
In an ideal world all packages would provide ES6 syntax, our browsers would resolve and load those packages dynamically and we could forego using rollup altogether, but looking at the state of the implementations there is still a long way to go.
Webpack 2 provides us with asynchronous support for assets with the forward-facing “System.import” syntax, which allows us to very conveniently use it, for example, with react-router. But beware: Files included with System.import aren’t subject to tree-shaking, so every dependency will get included. As all imports have to be statically analyzable per ES6 module specification it is not possible to import assets based on runtime values.
If you have any pointers or questions, I’m happy to hear from you on twitter.