Snowpack + Rollup : A match made in heaven
Rajasegar Chandran
Posted on April 1, 2020
In this previous post, we saw how Snowpack works or bundles the dependencies of your application into ESM compatible modules so that you can directly import them in your HTML files.
This post explores some of the tools used by Snowpack to do the same. In fact, we will explore one tool called Rollup.
Snowpack uses Rollup to do the heavy-lifting work by making use of a bunch of Rollup plugins, some of which are official plugins part of the Rollup plugins repository and other, which are custom-built by the Snowpack team.
Rollup
Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger and more complex,
such as a library or application. It uses the new ESM (EcmaScript Modules) format using import and export included in the ES6 revision of JavaScript, instead of CommonJS or AMD.
Plugins
The following is the list of Rollup plugins used by Snowpack.
Official Rollup Plugins
Custom-built Plugins for Snowpack
These plugins are part of the Snowpack codebase itself.
Now we will take a brief look at what each and every plugin contributes to how Snowpack bundles your dependencies into ESM compatible modules for the browser.
rollup-plugin-node-resolve
This plugin locates and bundles third-party dependencies in node_modules
using the Node resolution algorithm.
rollupPluginNodeResolve({
mainFields: ['browser:module', 'module', 'browser', !isStrict && 'main'].filter(isTruthy),
modulesOnly: isStrict, // Default: false
extensions: ['.mjs', '.cjs', '.js', '.json'], // Default: [ '.mjs', '.js', '.json', '.node' ]
// whether to prefer built-in modules (e.g. `fs`, `path`) or local ones with the same names
preferBuiltins: false, // Default: true
dedupe,
}),
Using with @rollup/plugin-commonjs
Since most packages in your node_modules folder are probably legacy CommonJS rather than JavaScript modules, you may need to use @rollup/plugin-commonjs
:
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default {
input: 'main.js',
output: {
file: 'bundle.js',
format: 'iife',
name: 'MyModule'
},
plugins: [resolve(), commonjs()]
};
rollup-plugin-json
This plugin converts .json
files to ES6 modules.
With an accompanying file src/index.js
, the local package.json
file would now be importable as seen below:
rollupPluginJson({
preferConst: true,
indent: ' ',
compact: isOptimized,
namedExports: true,
}),
rollup-plugin-commonjs
A Rollup plugin to convert CommonJS modules to ES6, so they can be included in a Rollup bundle.
rollupPluginCommonjs({
extensions: ['.js', '.cjs'], // Default: [ '.js' ]
namedExports: knownNamedExports,
}),
rollup-plugin-babel
This plugin provides seamless integration between Rollup and Babel.
If you're using Babel to transpile your ES6/7 code and Rollup to generate a standalone bundle, you have a couple of options:
- Run the code through Babel first, being careful to exclude the module transformer, or
- Run the code through Rollup first, and then pass it to Babel.
Both approaches have disadvantages – in the first case, on top of the additional configuration complexity, you may end up with Babel's helpers repeated throughout your code.
In the second case, transpiling is likely to be slower, because transpiling a large bundle is much more work for Babel than transpiling a set of small files.
Either way, you have to worry about a place to put the intermediate files, and getting sourcemaps to behave becomes a royal pain.
Using Rollup with this plugin makes the process far easier.
rollupPluginBabel({
compact: false,
babelrc: false,
configFile: false,
presets: [
[
babelPresetEnv,
{
modules: false,
targets: hasBrowserlistConfig
? undefined
: '>0.75%, not ie 11, not UCAndroid >0, not OperaMini all',
},
],
],
}),
rollup-plugin-terser
Rollup plugin to minify generated ES bundle. Uses terser under the hood.
// rollup.config.js
import { terser } from "rollup-plugin-terser";
export default {
input: "index.js",
output: [
{ file: "lib.js", format: "cjs" },
{ file: "lib.min.js", format: "cjs", plugins: [terser()] },
{ file: "lib.esm.js", format: "esm" }
]
};
rollup-plugin-stats
This plugin will display the file-size statistics when you run Snowpack with the --stat
option displaying both the compressed and uncompressed size information. It displays the compressed size using gzip
and brotli
compressions.
snowpack --stat
rollup-plugin-entrypoint-alias
Aliases any deep imports from a package to the package name, so that
chunking can happen more accurately.
rollup-plugin-remote-resolve
Rewrites imports for "remote packages" to point to the remote URL instead.
rollup-plugin-remote-cdn
Load import URLs from a remote CDN, sitting behind a local cache. The local cache acts as a go-between for the resolve & load step: when we get back a successful CDN resolution, we save the file to the local cache and then tell Rollup that it's safe to load from the cache in the load()
hook.
rollup-plugin-treeshake-inputs
This plugin is actually used to tree-shake the dependencies used in your applications. If you are interested in knowing how Snowpack does tree-shaking without a build step, I recommend this post
Tree-Shaking Without a Bundler? Here's How Snowpack Does It!
Fred K. Schott ・ Jan 16 ・ 2 min read
by Fred K. Schott, the creator of Snowpack, where he details how Rollup plays a big role in this process.
References:
Posted on April 1, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.