DEV Community

Cover image for Tree-Shaking Without a Bundler? Here's How Snowpack Does It!
Fred K. Schott for Pika

Posted on

Tree-Shaking Without a Bundler? Here's How Snowpack Does It!

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...

issue screenshot

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.

plugin screenshot

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.

GitHub logo guybedford / es-module-lexer

Low-overhead lexer dedicated to ES module parsing for fast analysis

ES Module Lexer

Build Status

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.

Built with Chomp

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
Enter fullscreen mode Exit fullscreen mode

Thanks for Reading!

Enjoyed this post? Throw Snowpack a 🌟on GH to help spread the word:

GitHub logo 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

💁 More info at the official Snowpack website ➞


Contributor Guidelines: CONTRIBUTING.md
License: MIT




Top comments (2)

Collapse
 
zhusjfaker profile image
zhushijie

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

Collapse
 
nickytonline profile image
Nick Taylor

Fred, I really enjoyed your discussion about Snowpack on the Syntax podcast. Snowpack looks very promising! ❄️

play pause Syntax - Tasty Web Development Treats