The opinions in this presentation are my own. This is not a statement from the webpack team.
You have to deal with problems you didn't have before.
Why isn't everyone just using ES modules?
No bare module specifiers:
No optional file extensions:
The following proposals are in very early stages. Take them with a grain of salt.
We don't need JS bundlers for that, it's already possible with ESM.
But: our current problem is resolving.
Things we can do: not rely on "cute" (Ryan Dahl) resolving features.
Advantages of BMS:
There is an intent to implement from the Blink team.
As a replacement for HTML imports:
There is an intent to implement from the Edge team.
CSS modules export a Constructable Stylesheet:
The goal: Turn this imperative API...
...into a declarative API:
Challenge: Allow cyclic dependencies between non-JS modules.Source: Lin Clark's presentation about WebAssembly ES module integration.
Cyclic dependencies between two WASM modules probably won't work at all.Source: Lin Clark's presentation about WebAssembly ES module integration.
Interesting proposal: Asset references
Another interesting proposal: import as-proposal
Advantages of these proposals:
One thing to note:
These are proposals to do the resource transformation on run time.
In order to get it fast for production, you would probably want to move this transformation to build time.
Hence, the transformation should be statically analyzable.
This is kind of hard to standardize because bundlers, Node.js and browsers have very different requirements.
But there is an interesting alternative to loaders...
Babel macros is a Babel plugin that allows you to evaluate code on build time.
How can this substitute loaders?
A good example of why modules should be able to configure their own loaders.
But how would that work without Babel?
With a package switch:
Current problem of Babel macros:
They require synchronous I/O on build and on run time.
Authors will slowly adopt the common denominator:
Bundlers won't be necessary because of compatibility reasons.
My hope: Platform independent APIs will converge some day.
Good example: the
Will be less relevant with evergreen browsers and incremental language updates, but probably still necessary for production builds.
Also polyfills still require a lot of manual configuration.
Current problems with ESM and H2 push:
H2 push is still hard.
As implementations mature, we need to re-evaluate the question whether we should create chunks or not.
Let's assume that we really, really wanted to use H2 push.
How would it work?
There are two possible solutions:
Creating a dependency graph for H2 push is not the only performance optimization a bundler can do.
But the problem is: Getting the best performance requires a lot of configuration.
The solution: Give more data to the bundler so that it can perform automated decisions.
It could add resource hints automatically, like
preconnect for all hosts that have been parsed
from the source code.
webpackPreload: true for render critical fonts.
But these manual hints can get outdated over time.
Example: Create optimized subsets of fonts based on the actual usage of glyphs.
Another example: Inline render critical CSS.
Running automated critical render path tests works especially well with the JAMstack.
But these automated tests are also error prone because we have to select popular routes.
What if instead of artifical usage data we used...
Data-driven user experiences: When real usage data drives the decisions about how to optimize the app.
And this is already possible today...
navigator.connection.effectiveTypeto avoid over-fetching and thus wasting expensive data on mobile.
Calculating content hashes and updating URLs will always require a bundler.
But there's another problem: In order to avoid propagating content hashes, we need to use an out-of-band configuration.
A single change invalidates all content hashes.
All these optimizations are still necessary:
This is the reason why you will always have a build step for high-performance websites.
Bundlers were invented to use Node.js modules in the web, but this has changed.
Today, we use bundlers for a lot of reasons, like dev experience, compatibility and optimizations.
Yes, because bundlers can do stuff on build time that would otherwise need to be done on run time.
But the scope of bundlers will probably change.
In order to make that happen without configuration overhead, we need to give bundlers more insights into our application...
Unified module systems
Optimized resource loading
HTML, CSS & WASM modules
New language features
Smaller file sizes
Short feedback loop