Until Snowpack came on the scene, application bundling was the only way to do tree-shaking (dead-code elimination) on the web.
But Snowpack is the unbundler. It runs only on your dependencies without ever touching your application code. So how could it tree-shake?
Here's a quick post about how we made this production optimization happen for faster production apps, thanks to some essential help from the RollupJS team 🙌
The Setup
Bundlers "tree-shake" your web application by finding and removing unused code, shaving off valuable bytes when you deploy to production.
Since Snowpack never touches your application code, how could we do the same? We had to get creative.
Snowpack v1.0 added an initial "scan" phase behind the --optimize
flag. It runs a quick scan of your app to learn how you use each dependency.
... and that's it! We pass that info to our internal installer (powered by Rollup) and eliminate any dead code at install time.
The Challenge
"Passing that info to our Rollup-powered installer" was an interesting challenge: How do you tell Rollup that code in your top-level entrypoints is unused?
This was an unusual request, and something the Rollup team (rightfully!) didn't want to build into the bundler itself.
We created an issue on the Rollup repo to outline the problem, and with @lukastaegert's help came up with a really clever solution via a new plugin...
Here's how we solved it: We create an in-memory "envelope" wrapper for Rollup of every dep & fill it with the exact imports used by your app.
Rollup sees the envelope, reads the scanned imports to the real dep, & then automatically tree-shakes out everything not found in the ✉️
You can see exactly how it works here, coming in at only ~50 LOC.
This all runs behind the production-only --optimize
flag, so you can add & remove imports as you develop your app without worrying about tree-shaking or needing to re-install as your code changes.
But even when optimizing for production, just reading & scanning your application code should be a hell of a lot faster than reading, scanning AND BUNDLING your app code with a traditional bundler (so you can still expect fast production deployments).
What's Next?
We're experimenting with replacing our current import scanner with the even faster es-module-lexer by @guybedford, a WASM-powered scanner written in C.
guybedford / es-module-lexer
Low-overhead lexer dedicated to ES module parsing for fast analysis
ES Module Lexer
A JS module syntax lexer used in es-module-shims.
Outputs the list of exports and locations of import specifiers, including dynamic import and import meta handling.
Supports new syntax features including import attributes and source phase imports.
A very small single JS file (4KiB gzipped) that includes inlined Web Assembly for very fast source analysis of ECMAScript module syntax only.
For an example of the performance, Angular 1 (720KiB) is fully parsed in 5ms, in comparison to the fastest JS parser, Acorn which takes over 100ms.
Comprehensively handles the JS language grammar while remaining small and fast. - ~10ms per MB of JS cold and ~5ms per MB of JS warm, see benchmarks for more info.
Usage
npm install es-module-lexer
See types/lexer.d.ts for the type definitions.
For use in CommonJS:
const { init, parse } = require('es-module-lexer');
(async
…Thanks for Reading!
Enjoyed this post? Throw Snowpack a 🌟on GH to help spread the word:
FredKSchott / snowpack
ESM-powered frontend build tool. Instant, lightweight, unbundled development. ✌️
Update (April 20, 2022): Snowpack is no longer actively maintained and is not recommended for new projects.
Check out Vite for a well-maintained Snowpack alternative.
See also: esbuild, parcel
Snowpack
Snowpack is a lightning-fast frontend build tool, designed to leverage JavaScript's native module system (known as ESM). It is an alternative to heavier, more complex bundlers like webpack or Parcel in your development workflow.
Key Features
- Develop faster, with a dev server that starts up in 50ms or less.
- See changes reflected instantly in the browser.
- Integrate your favorite bundler for a production-optimized build.
- Enjoy out-of-the-box support for TypeScript, JSX, CSS Modules and more.
- Connect your favorite tools with third-party plugins.
💁 More info at the official Snowpack website ➞
Contributor Guidelines: CONTRIBUTING.md
License: MIT
- Learn more about Snowpack: https://www.snowpack.dev/
- Follow us on Twitter for updates: https://twitter.com/pikapkg
- Read & share the original Twitter thread that this was based on: https://twitter.com/pikapkg/status/1217509391668133888
Top comments (2)
c.ts
export * from './a';
export * from './b';
index.ts
import { TestBComponent } from './c';
snowpack will install a.ts & b.ts
treeshake is not work
Fred, I really enjoyed your discussion about Snowpack on the Syntax podcast. Snowpack looks very promising! ❄️