SalakCode SalakCode
Bundling

Rollup

Next-generation ES module bundler

Intermediate
bundling rollup libraries modules

Definition

Rollup is a JavaScript module bundler that compiles small pieces of code into larger, more complex applications or libraries. It’s particularly well-suited for building libraries that are published as ES modules, offering excellent tree-shaking capabilities and producing smaller, more efficient bundles than many alternatives.

Why Rollup?

Comparison

// Rollup excels at:
// - Library bundling
// - ES modules output
// - Tree-shaking
// - Smaller bundle sizes

// Webpack excels at:
// - Application bundling
// - Code splitting
// - Asset handling
// - Dev server/HMR

Bundle Size

// Input
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }

// Rollup output (using only add):
function add(a, b) { return a + b; }
export { add };
// Size: ~30 bytes

// Webpack output:
// ... webpack runtime + module system ...
// Size: ~500+ bytes

Basic Configuration

Simple Config

// rollup.config.js
export default {
  input: 'src/index.js',
  output: [
    {
      file: 'dist/bundle.cjs',
      format: 'cjs'
    },
    {
      file: 'dist/bundle.esm.js',
      format: 'es'
    },
    {
      file: 'dist/bundle.umd.js',
      format: 'umd',
      name: 'MyLibrary'
    }
  ]
};

Library Config

// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import { terser } from 'rollup-plugin-terser';

export default {
  input: 'src/index.ts',
  output: [
    {
      file: 'dist/index.cjs',
      format: 'cjs',
      sourcemap: true
    },
    {
      file: 'dist/index.mjs',
      format: 'es',
      sourcemap: true
    }
  ],
  plugins: [
    resolve(),      // Resolve node_modules
    commonjs(),     // Convert CommonJS to ES6
    typescript(),   // Compile TypeScript
    terser()        // Minify
  ],
  external: ['react', 'react-dom'] // Don't bundle these
};

Output Formats

ES Modules (es)

// Modern browsers and bundlers
// Tree-shakeable
export { add, subtract };

// Usage
import { add } from 'my-lib';

CommonJS (cjs)

// Node.js compatibility
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });
exports.add = add;

function add(a, b) {
  return a + b;
}

// Usage
const { add } = require('my-lib');

UMD (umd)

// Universal - works everywhere
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' 
    ? factory(exports) 
    : typeof define === 'function' && define.amd 
    ? define(['exports'], factory) 
    : (global = global || self, factory(global.myLib = {}));
}(this, function (exports) {
  'use strict';
  exports.add = function(a, b) { return a + b; };
}));

// Usage
// Browser: myLib.add(1, 2)
// AMD: require(['myLib'], ...)
// CommonJS: require('my-lib')

Plugins

Essential Plugins

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';

export default {
  input: 'src/index.js',
  output: { file: 'dist/bundle.js', format: 'es' },
  plugins: [
    // Resolve imports from node_modules
    resolve({
      browser: true,
      preferBuiltins: false
    }),
    
    // Convert CommonJS modules to ES6
    commonjs(),
    
    // Transpile with Babel
    babel({
      babelHelpers: 'bundled',
      exclude: 'node_modules/**'
    })
  ]
};

TypeScript

import typescript from '@rollup/plugin-typescript';

export default {
  input: 'src/index.ts',
  plugins: [
    typescript({
      tsconfig: './tsconfig.json'
    })
  ]
};

CSS

import postcss from 'rollup-plugin-postcss';

export default {
  plugins: [
    postcss({
      plugins: [require('autoprefixer')],
      extract: true,
      minimize: true
    })
  ]
};

Advanced Configuration

Code Splitting

export default {
  input: {
    main: 'src/index.js',
    utils: 'src/utils.js'
  },
  output: {
    dir: 'dist',
    format: 'es',
    entryFileNames: '[name].js',
    chunkFileNames: '[name]-[hash].js'
  }
};

Watch Mode

export default {
  input: 'src/index.js',
  output: { file: 'dist/bundle.js', format: 'es' },
  watch: {
    include: 'src/**',
    exclude: 'node_modules/**',
    clearScreen: false
  }
};

Preserving Shebang

import shebang from 'rollup-plugin-shebang';

export default {
  input: 'src/cli.js',
  output: { file: 'dist/cli.js', format: 'cjs' },
  plugins: [
    shebang({
      shebang: '#!/usr/bin/env node'
    })
  ]
};

Package.json Setup

{
  "name": "my-library",
  "version": "1.0.0",
  "main": "dist/index.cjs",
  "module": "dist/index.mjs",
  "types": "dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs",
      "types": "./dist/index.d.ts"
    }
  },
  "files": ["dist"],
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w",
    "prepublish": "npm run build"
  }
}

Best Practices

1. External Dependencies

export default {
  external: [
    // Don't bundle dependencies
    'react',
    'react-dom',
    'lodash'
  ]
};

2. Multiple Outputs

export default {
  input: 'src/index.js',
  output: [
    // Development
    {
      file: 'dist/my-lib.js',
      format: 'umd',
      name: 'MyLib',
      sourcemap: true
    },
    // Production (minified)
    {
      file: 'dist/my-lib.min.js',
      format: 'umd',
      name: 'MyLib',
      plugins: [terser()],
      sourcemap: true
    }
  ]
};

3. Tree-Shaking Friendly

// ✅ Good: Named exports
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }

// ❌ Bad: Default export with everything
export default {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b
};
Key Takeaway

Rollup is the bundler of choice for JavaScript libraries. It produces smaller, more efficient bundles with excellent tree-shaking. Configure multiple output formats for maximum compatibility, use plugins for transpilation and asset handling, and mark dependencies as external. Perfect for publishing to npm.

Resources

Related Topics