Why should I bundle a library (with Rollup or Webpack) insetad of just transpiling with Babel?

Viewed 724

If I am writing a library in Javascript, what is the advantage of bundling with something like Rollup or Webpack over just transpiling with Babel? The only thing I can think of is that, if I just transpile, then perhaps all of my dependencies may effectively be peer dependencies (although I'm not 100% sure if that is true). However, if I'm doing a relatively vanilla React component (or I am building on top of a larger library like material-ui), I probably want them to be peer dependencies anyways, so that should only be an issue if I depend on multiple smaller libraries my consumer is less likely to install anyways. Additionally, if I just transpile, theoretically it is easier for consumers to import just the parts they want (since each file will be transpiled and importable) vs. complicated configs in the bundler to output multiple bundles.

Am I missing something? Is there some work a bundler does for me that, as a library developer, I would want over just making sure that the code is more directly usable in older browsers that may not implement modern language features I want to use?

1 Answers

Disclaimer: This answer assumes that you write code using ECMAScript Module Syntax, which is by now the industry standard.

To bundle or not to bundle? First, recognize that bundlers do two things:

  1. They combine multiple source files into one
  2. They can generate code in multiple module formats (ESM, CommonJS, UMD)

Pros of Bundling

Providing a Single File

Providing a single file has its benefits. Even in this day and age, some people prefer drag-and-dropping a single *.js file into their project. This includes beginners who don't know how to use a bundler.

Also, a single file can be easily imported from CDNs like unpkg and JSDelivr, which allow hotlinking files in NPM packages. A library distributed as multiple files will cost multiple network requests, which increases initial load times.

Supporting Old Browsers and Runtimes

You can choose to bundle or not independent of transpilation and polyfilling. So you need a bundler to support old browsers argument is generally not true.

However, old browsers that don't support ES Modules are an exception--you do need to consider bundling for them. (Read below for a counterargument)

There are also a small number of non-Node.js JavaScript runtimes (e.g. Mozilla Rhino) that don't support ES Modules.

Limiting the API Surface

theoretically it is easier for consumers to import just the parts they want

This can backfire if your users attempt to dig into your package and import individual files:

import {someFunc} from 'amazing-lib/dist/some/file.js'

someFunc() // Accessing an internal feature!

This allows them to access internals of your library in ways that you didn't anticipate, possibly causing unintended side effects. Also, should you later decide to modify the implementation, people will complain about you suddenly breaking their app with a patch version bump.

Bundling makes it generally impossible to access the internals of your code. This allow you to confidently change your library without violating the mutual contract between you and your users.

Note that this is less of a concern now that we have package entry points. From the docs:

Existing packages introducing the "exports" field will prevent consumers of the package from using any entry points that are not defined

Cons of Bundling

More Work

Obviously you need to install and configure your bundler. This is not only tedious (despite massive improvements in tooling), but makes your deployment slower. Oh, and your node_modules will be fatter.

Who doesn't bundle, anyway?

Anyone who is seriously into modern webdev will likely use a bundler for their project. Especially those poor souls who must target browsers without ESM support will need a bundler, because more and more library authors are not bothering to provide CJS or UMD bundles. Bundling your library benefits a fading subset of users.

Related