-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
I've been looking into this today, and to sum up, I think we should do it.
Up till now, the main blocker for this has been our desire to keep time-to-first-render low. According to research in #3153 by @jfirebaugh, the amount of code evaluated on the worker side is the biggest factor in that, so we've been assuming we need to automatically create slim worker bundles from the main bundle, stripping out all the unnecessary code. So far, this has only been possible with Browserify because it keeps all the code in a dependency tree which we can traverse at runtime. There's no way to do that in Rollup — see rollup/rollup#1029.
Note that when we implemented slimming down the worker bundle (browserify/webworkify#30), the overall effect on TTFR was not that big — only ~200ms despite the bundle becoming ~2x smaller.
Today, I decided to take a small part of GL JS and convert it to Rollup to see how it would look — specifically, the expression code. When uglified/gzipped, the ES modules based build is approximately 10% smaller than the browserify-based one. Additionally, I wrapped the whole code with a simple console.time/timeEnd — the browserify-based build executed in 5.5ms in Node but the rollup one in just 1.2ms. Then I also remembered this article by Nolan Lawson that benchmarked the runtime cost of different bundlers (and showed Browserify having a huge hit compared to Rollup).
All this made me realize that maybe we should have looked at Browserify itself as the culprit of long evaluation times, and not just the size of the bundle. What if the switch from Browserify to ES Modules / Rollup reduces TTFR so dramatically that we no longer have to worry about worker bundle size much? Then, we could just make a custom rollup prelude that would launch the whole bundle as workers without traversing the deps at runtime.
My hunch is that we should take the plunge with ES Modules. The only big drawback I see is that we'll have to complicate the unit test setup (possibly relying on something like @std/esm), but advantages are great:
- smaller bundle
- possibly better time-to-first-render
- modern code base without the awkward mix of ES-like flow type imports and CommonJS
- more strict compile-time checking of dependencies
What do you think?