JavaScript Development Space

How to Package Component Libraries with Rollup Instead of Webpack

When developing component libraries, choosing the right bundler is critical for delivering optimized and compatible packages. While Webpack is a versatile tool for web application bundling, Rollup is often preferred for packaging libraries due to its cleaner outputs, efficient tree-shaking, and robust plugin system. This article dives into the reasons why Rollup is a superior choice for component library packaging, along with practical examples comparing it to Webpack.

Why Rollup for Component Libraries?

Rollup is purpose-built for bundling JavaScript libraries. Unlike Webpack, which is designed for web applications and includes runtime management, Rollup focuses on generating minimal, dependency-free bundles. This makes it ideal for libraries that need to be lightweight and compatible with multiple environments.

  • Clean Output: Rollup avoids including runtime code, producing lean bundles.
  • Multiple Module Formats: Rollup natively supports ESM, CommonJS, and UMD, crucial for distributing libraries.
  • Tree-Shaking: Rollup’s default tree-shaking eliminates unused code, reducing bundle size.
  • Extensibility: The plugin system simplifies customization and modularity.
  • Integration with Modern Tools: Tools like Vite use Rollup for production builds.

Comparison: Rollup vs. Webpack

Rollup vs Webpack

1. Packaging Example

To illustrate the differences, let’s package a simple project using both Rollup and Webpack.

Project Structure

We’ll use two basic modules:

src/index.js:

js
1 import { add } from './utils';
2
3 function main() {
4 console.log(add(1, 2));
5 }
6
7 export default main;

src/utils.js:

js
1 function add(a, b) {
2 return a + b;
3 }
4
5 export { add };

Using Rollup

1. Install Rollup:

npm install --save-dev rollup

2. Create Configuration:

rollup.config.js:

js
1 /** @type {import('rollup').RollupOptions} */
2 export default {
3 input: 'src/index.js',
4 output: [
5 { file: 'dist/esm.js', format: 'esm' },
6 { file: 'dist/cjs.js', format: 'cjs' },
7 { file: 'dist/umd.js', name: 'LibraryName', format: 'umd' },
8 ],
9 };

3. Build:

npx rollup -c rollup.config.js

Output:

  • Clean bundles for ESM, CommonJS, and UMD, free of runtime code.

Using Webpack

1. Install Webpack:

npm install --save-dev webpack webpack-cli

2. Create Configuration:

webpack.config.mjs:

js
1 import path from 'path';
2
3 /** @type {import('webpack').Configuration} */
4 export default {
5 entry: './src/index.js',
6 mode: 'development',
7 devtool: false,
8 output: {
9 path: path.resolve(process.cwd(), 'dist'),
10 filename: 'bundle.js',
11 libraryTarget: 'commonjs2',
12 },
13 };

3. Build:

npx webpack-cli -c webpack.config.mjs

Output:

  • The bundle includes over 100 lines of runtime code, even in simple scenarios.

CSS Handling: Rollup vs. Webpack

Component libraries often require separate CSS files. Let’s see how both bundlers handle this.

Packaging CSS with Rollup

1. Install PostCSS Plugin:

npm install --save-dev rollup-plugin-postcss

2. Configure Rollup for CSS Extraction:

rollup.config.js:

js
1 import postcss from 'rollup-plugin-postcss';
2
3 /** @type {import('rollup').RollupOptions} */
4 export default {
5 input: 'src/index.js',
6 output: [
7 { file: 'dist/esm.js', format: 'esm' },
8 { file: 'dist/cjs.js', format: 'cjs' },
9 { file: 'dist/umd.js', name: 'LibraryName', format: 'umd' },
10 ],
11 plugins: [
12 postcss({
13 extract: 'styles.css', // Extracts CSS to a separate file
14 }),
15 ],
16 };

3. Build:

npx rollup -c rollup.config.js

Result:

  • The CSS is extracted into styles.css, while the JS remains clean.

Packaging CSS with Webpack

1. Install CSS Loaders:

npm install --save-dev css-loader style-loader mini-css-extract-plugin

2. Configure Webpack for CSS:

webpack.config.mjs:

js
1 import path from 'path';
2 import MiniCssExtractPlugin from 'mini-css-extract-plugin';
3
4 /** @type {import('webpack').Configuration} */
5 export default {
6 entry: './src/index.js',
7 mode: 'development',
8 devtool: false,
9 output: {
10 path: path.resolve(process.cwd(), 'dist'),
11 filename: 'bundle.js',
12 },
13 module: {
14 rules: [
15 {
16 test: /\.css$/i,
17 use: [MiniCssExtractPlugin.loader, 'css-loader'],
18 },
19 ],
20 },
21 plugins: [
22 new MiniCssExtractPlugin({ filename: 'styles.css' }),
23 ],
24 };

3. Build:

npx webpack-cli -c webpack.config.mjs

Result:

  • CSS is extracted into styles.css, but the JS bundle still contains references to runtime helpers.

When to Use Rollup vs. Webpack

Use Rollup for:

  • Packaging libraries (e.g., JavaScript utilities, React/Vue component libraries).
  • Scenarios requiring clean, runtime-free bundles.
  • Projects targeting multiple module formats.

Use Webpack for:

  • Bundling web applications.
  • Handling complex assets like images, fonts, and dynamic imports.
  • Scenarios requiring advanced development server features.

Rollup in Modern Toolchains

Tools like Vite and SvelteKit use Rollup under the hood for production builds. While Vite employs esbuild for development due to its speed, Rollup’s plugin system powers production packaging. This hybrid approach combines speed and flexibility.

Conclusion

Rollup is a focused, efficient tool for library packaging, offering clean outputs and multiple format support. While Webpack dominates application bundling, Rollup excels in scenarios where simplicity, tree-shaking, and modularity are paramount. By understanding their strengths, developers can choose the right tool for their projects.

Whether you're building a JavaScript library, a UI component library, or exploring tools like Vite, Rollup is an indispensable part of modern bundling workflows.

JavaScript Development Space

© 2024 JavaScript Development Space - Master JS and NodeJS. All rights reserved.