A dynamic module bundling pattern for modern web development
Until recently, the use of JavaScript modules required a build step to make them run in the browser. Since the general availability of ES6 modules in browsers, it is possible to use JavaScript’s built-in module system. What this means is we no longer require a build step to be able to write modular code that runs in the browser natively. Modules also can benefit from the addition of parallel loading made available with HTTP/2.
As we all know, with every development choice, there are new considerations that ultimately emerge over time.
For instance, with a build-step based workflow, your build time can start to take longer, and your compiler configuration can become exceedingly more complex as your project’s source code grows.
Modules don’t require the overhead of a build step, which is great, but loading too many sub-modules at once can create a bottleneck that can increase the time it takes to load your web page completely.
It is possible to get a long way without running into this issue, but if it does arise, cutting down on requests can help.
Enter Progressive Bundling
This pattern uses a cloud function to optimize the amount of JavaScript sent to the browser by bundling together modules and their sub-modules, into a single request, on-demand. Bundling these files together cuts down on the number of files being loaded in parallel by the browser. This bundled file is then “fingerprinted,” or named with an appended id representing the file’s contents. We then cache this generated file with this fingerprinted name for subsequent requests. The request is then redirected with a 302 status code to the newly bundled, fingerprinted, and cached file.
What makes this progressive is that you can start with stock JavaScript for development, which is easier to debug, then layer on bundling with a cloud function, and a standard HTTP redirect for an optimized build if you ever need it.
A delicate balance
It is always important to audit your site performance to understand when to employ optimization. It is possible to cut down on requests, but end-up loading too large a file that ultimately negatively impacts performance. The best bet is to always load as little JavaScript as possible.
Take it farther
Think about how you could apply this approach to delivering other payloads such as CSS or icons. You could even add a transpiler if you wanted.
Check out the Progressive Bundling Example
Where we step through the code of an example app using this pattern. Deploy your own Progressive Bundling example app on Begin.
Top comments (3)
Even with HTTP/2 multiplexing?
even the official recommendation from the V8 team says multiplexing isn't suitable for more than 100 modules. can dig on my Twitter if you need a source
Yes.
As I stated in the post, you can get a long way with multiplexing but at a point ( which is different for every app ) the waterfall created by loading submodules will become a bottleneck.
This isn't speculation either.
We have been 100% ES Modules since they have been in general availability.
I personally hit the limit while building begin.com.
You get to benefit from my pain ;)