Skip to content

Rollup Cheatsheet

Rollup - Next-generation ES Module Bundler

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 standardized format for code modules included in the ES6 revision of JavaScript.

Table of Contents

Installation

Global Installation

# Install Rollup globally
npm install -g rollup

# Check version
rollup --version
# Initialize npm project
npm init -y

# Install Rollup locally
npm install --save-dev rollup

# Install common plugins
npm install --save-dev @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-babel

Package.json Scripts

{
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w",
    "build:prod": "NODE_ENV=production rollup -c"
  }
}

Basic Configuration

Minimal rollup.config.js

export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'iife'
  }
};

Complete Basic Configuration

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife',
    name: 'MyBundle',
    sourcemap: true
  },
  plugins: [
    resolve(),
    commonjs(),
    terser()
  ]
};

Multiple Configurations

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

const configs = [
  // ES module build
  {
    input: 'src/main.js',
    output: {
      file: 'dist/bundle.esm.js',
      format: 'es'
    },
    plugins: [resolve(), commonjs()]
  },
  // UMD build
  {
    input: 'src/main.js',
    output: {
      file: 'dist/bundle.umd.js',
      format: 'umd',
      name: 'MyLibrary'
    },
    plugins: [resolve(), commonjs()]
  }
];

export default configs;

Environment-based Configuration

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';

const production = !process.env.ROLLUP_WATCH;

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife',
    sourcemap: !production
  },
  plugins: [
    resolve(),
    commonjs(),
    production && terser()
  ]
};

Input Options

Single Entry Point

export default {
  input: 'src/main.js'
};

Multiple Entry Points

export default {
  input: {
    main: 'src/main.js',
    admin: 'src/admin.js',
    vendor: 'src/vendor.js'
  }
};

Dynamic Entry Points

import glob from 'glob';

const entries = glob.sync('src/pages/*.js').reduce((acc, path) => {
  const entry = path.replace('src/pages/', '').replace('.js', '');
  acc[entry] = path;
  return acc;
}, {});

export default {
  input: entries
};

Entry with External Dependencies

export default {
  input: 'src/main.js',
  external: ['lodash', 'react', 'react-dom']
};

Output Options

Output Formats

// ES Module
export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.esm.js',
    format: 'es'
  }
};

// CommonJS
export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.cjs.js',
    format: 'cjs'
  }
};

// UMD (Universal Module Definition)
export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.umd.js',
    format: 'umd',
    name: 'MyLibrary'
  }
};

// IIFE (Immediately Invoked Function Expression)
export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife',
    name: 'MyApp'
  }
};

// AMD (Asynchronous Module Definition)
export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.amd.js',
    format: 'amd'
  }
};

// SystemJS
export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.system.js',
    format: 'system'
  }
};

Multiple Output Formats

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

Output Directory

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

Source Maps

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife',
    sourcemap: true, // Generate external source map
    // sourcemap: 'inline', // Inline source map
    // sourcemap: 'hidden' // Generate but don't reference
  }
};

Plugins

Essential Plugins

# Install essential plugins
npm install --save-dev @rollup/plugin-node-resolve
npm install --save-dev @rollup/plugin-commonjs
npm install --save-dev @rollup/plugin-babel
npm install --save-dev @rollup/plugin-terser

Node Resolve Plugin

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

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    resolve({
      browser: true, // Use browser field in package.json
      preferBuiltins: false, // Don't prefer Node.js built-ins
      extensions: ['.js', '.jsx', '.ts', '.tsx']
    })
  ]
};

CommonJS Plugin

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

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    commonjs({
      include: 'node_modules/**', // Convert CommonJS modules
      exclude: ['node_modules/foo/**'], // Exclude specific modules
      transformMixedEsModules: true // Handle mixed ES/CommonJS modules
    })
  ]
};

Babel Plugin

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

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    babel({
      babelHelpers: 'bundled',
      exclude: 'node_modules/**',
      presets: [
        ['@babel/preset-env', {
          targets: {
            browsers: ['> 1%', 'last 2 versions']
          }
        }]
      ]
    })
  ]
};

Terser Plugin (Minification)

import { terser } from 'rollup-plugin-terser';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    terser({
      compress: {
        drop_console: true, // Remove console.log
        drop_debugger: true // Remove debugger statements
      },
      format: {
        comments: false // Remove comments
      }
    })
  ]
};

Replace Plugin

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

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    replace({
      'process.env.NODE_ENV': JSON.stringify('production'),
      '__VERSION__': JSON.stringify(process.env.npm_package_version)
    })
  ]
};

JSON Plugin

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

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    json()
  ]
};

// Usage in code
import { version } from '../package.json';
console.log(version);

URL Plugin (Assets)

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

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    url({
      limit: 10 * 1024, // 10KB limit for inline
      include: ['**/*.svg', '**/*.png', '**/*.jpg', '**/*.gif'],
      emitFiles: true
    })
  ]
};

External Dependencies

Basic External Configuration

export default {
  input: 'src/main.js',
  external: ['lodash', 'react', 'react-dom'],
  output: {
    file: 'dist/bundle.js',
    format: 'umd',
    globals: {
      'lodash': '_',
      'react': 'React',
      'react-dom': 'ReactDOM'
    }
  }
};

Dynamic External Function

export default {
  input: 'src/main.js',
  external: (id) => {
    // Mark all node_modules as external
    return id.includes('node_modules');
  },
  output: {
    file: 'dist/bundle.js',
    format: 'es'
  }
};

Peer Dependencies as External

import pkg from './package.json';

export default {
  input: 'src/main.js',
  external: Object.keys(pkg.peerDependencies || {}),
  output: {
    file: 'dist/bundle.js',
    format: 'es'
  }
};

Tree Shaking

Enabling Tree Shaking

// Rollup automatically tree-shakes ES modules
export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'es'
  }
};

Tree Shaking with Side Effects

// package.json
{
  "sideEffects": false // No side effects, safe to tree-shake
}

// Or specify files with side effects
{
  "sideEffects": [
    "*.css",
    "./src/polyfills.js"
  ]
}

Preserving Side Effects

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'es'
  },
  treeshake: {
    moduleSideEffects: false, // Assume no side effects
    // moduleSideEffects: (id) => id.includes('polyfill')
  }
};

Tree Shaking Example

// utils.js
export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

export function multiply(a, b) {
  console.log('This has a side effect!');
  return a * b;
}

// main.js
import { add } from './utils.js'; // Only 'add' will be included

console.log(add(2, 3));

Code Splitting

Dynamic Imports

// main.js
async function loadModule() {
  const module = await import('./heavy-module.js');
  return module.default();
}

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

Manual Chunks

export default {
  input: 'src/main.js',
  output: {
    dir: 'dist',
    format: 'es',
    manualChunks: {
      vendor: ['lodash', 'react'],
      utils: ['src/utils/helpers.js', 'src/utils/constants.js']
    }
  }
};

Dynamic Manual Chunks

export default {
  input: 'src/main.js',
  output: {
    dir: 'dist',
    format: 'es',
    manualChunks: (id) => {
      if (id.includes('node_modules')) {
        return 'vendor';
      }
      if (id.includes('src/utils')) {
        return 'utils';
      }
    }
  }
};

Entry Point Splitting

export default {
  input: {
    main: 'src/main.js',
    admin: 'src/admin.js',
    vendor: 'src/vendor.js'
  },
  output: {
    dir: 'dist',
    format: 'es'
  }
};

Watch Mode

Basic Watch Mode

# Watch for changes
rollup -c -w

# Or with npm script
npm run dev

Watch Configuration

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

Watch with Plugins

import livereload from 'rollup-plugin-livereload';
import serve from 'rollup-plugin-serve';

const production = !process.env.ROLLUP_WATCH;

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife',
    sourcemap: !production
  },
  plugins: [
    // ... other plugins
    !production && serve({
      open: true,
      contentBase: 'dist',
      port: 3000
    }),
    !production && livereload('dist')
  ]
};

Development vs Production

Environment-based Configuration

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
import replace from '@rollup/plugin-replace';

const production = process.env.NODE_ENV === 'production';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife',
    sourcemap: !production
  },
  plugins: [
    resolve(),
    commonjs(),
    replace({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
    }),
    production && terser()
  ].filter(Boolean)
};

Separate Config Files

// rollup.config.dev.js
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife',
    sourcemap: true
  },
  plugins: [
    serve({
      contentBase: 'dist',
      port: 3000
    }),
    livereload('dist')
  ]
};

// rollup.config.prod.js
import { terser } from 'rollup-plugin-terser';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    terser()
  ]
};

Package.json Scripts

{
  "scripts": {
    "dev": "rollup -c rollup.config.dev.js -w",
    "build": "NODE_ENV=production rollup -c rollup.config.prod.js"
  }
}

TypeScript Integration

TypeScript Plugin

# Install TypeScript plugin
npm install --save-dev @rollup/plugin-typescript typescript
import typescript from '@rollup/plugin-typescript';

export default {
  input: 'src/main.ts',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    typescript({
      tsconfig: './tsconfig.json'
    })
  ]
};

TypeScript Configuration

// tsconfig.json
{
  "compilerOptions": {
    "target": "es2018",
    "module": "esnext",
    "lib": ["dom", "dom.iterable", "es6"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": false,
    "declaration": true,
    "outDir": "dist"
  },
  "include": [
    "src"
  ]
}

TypeScript with Babel

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

export default {
  input: 'src/main.ts',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    typescript(),
    babel({
      babelHelpers: 'bundled',
      extensions: ['.js', '.ts']
    })
  ]
};

CSS and Assets

PostCSS Plugin

# Install PostCSS plugin
npm install --save-dev rollup-plugin-postcss
import postcss from 'rollup-plugin-postcss';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    postcss({
      extract: true, // Extract to separate CSS file
      minimize: true, // Minify CSS
      sourceMap: true
    })
  ]
};

SCSS/Sass Support

import postcss from 'rollup-plugin-postcss';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    postcss({
      extract: 'styles.css',
      use: ['sass']
    })
  ]
};

Asset Handling

import url from '@rollup/plugin-url';
import copy from 'rollup-plugin-copy';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    url({
      limit: 10 * 1024, // 10KB
      include: ['**/*.svg', '**/*.png', '**/*.jpg'],
      emitFiles: true
    }),
    copy({
      targets: [
        { src: 'src/assets/images/*', dest: 'dist/images' },
        { src: 'src/assets/fonts/*', dest: 'dist/fonts' }
      ]
    })
  ]
};

Library Development

Library Configuration

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
import pkg from './package.json';

export default [
  // ES module build
  {
    input: 'src/index.js',
    external: Object.keys(pkg.peerDependencies || {}),
    output: {
      file: pkg.module,
      format: 'es'
    },
    plugins: [
      resolve(),
      commonjs()
    ]
  },
  // CommonJS build
  {
    input: 'src/index.js',
    external: Object.keys(pkg.peerDependencies || {}),
    output: {
      file: pkg.main,
      format: 'cjs'
    },
    plugins: [
      resolve(),
      commonjs()
    ]
  },
  // UMD build
  {
    input: 'src/index.js',
    output: {
      file: pkg.browser,
      format: 'umd',
      name: 'MyLibrary',
      globals: {
        'react': 'React',
        'react-dom': 'ReactDOM'
      }
    },
    plugins: [
      resolve(),
      commonjs(),
      terser()
    ]
  }
];

Package.json for Library

{
  "name": "my-library",
  "version": "1.0.0",
  "main": "dist/index.cjs.js",
  "module": "dist/index.esm.js",
  "browser": "dist/index.umd.js",
  "types": "dist/index.d.ts",
  "files": [
    "dist"
  ],
  "scripts": {
    "build": "rollup -c",
    "prepublishOnly": "npm run build"
  },
  "peerDependencies": {
    "react": "^17.0.0",
    "react-dom": "^17.0.0"
  }
}

TypeScript Library

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

export default {
  input: 'src/index.ts',
  output: [
    {
      file: 'dist/index.esm.js',
      format: 'es'
    },
    {
      file: 'dist/index.cjs.js',
      format: 'cjs'
    }
  ],
  plugins: [
    typescript({
      declaration: true,
      declarationDir: 'dist'
    }),
    resolve(),
    commonjs()
  ]
};

Advanced Configuration

Custom Plugin

function myPlugin() {
  return {
    name: 'my-plugin',
    buildStart(opts) {
      console.log('Build started');
    },
    transform(code, id) {
      if (id.endsWith('.special')) {
        return `export default ${JSON.stringify(code)}`;
      }
    },
    generateBundle(opts, bundle) {
      console.log('Bundle generated');
    }
  };
}

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    myPlugin()
  ]
};

Conditional Builds

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';

const configs = [];

// Development build
if (process.env.NODE_ENV !== 'production') {
  configs.push({
    input: 'src/main.js',
    output: {
      file: 'dist/bundle.dev.js',
      format: 'iife',
      sourcemap: true
    },
    plugins: [resolve(), commonjs()]
  });
}

// Production build
if (process.env.NODE_ENV === 'production') {
  configs.push({
    input: 'src/main.js',
    output: {
      file: 'dist/bundle.min.js',
      format: 'iife'
    },
    plugins: [resolve(), commonjs(), terser()]
  });
}

export default configs;

Multi-entry with Shared Dependencies

export default {
  input: {
    main: 'src/main.js',
    admin: 'src/admin.js'
  },
  output: {
    dir: 'dist',
    format: 'es',
    manualChunks: {
      vendor: ['lodash', 'react'],
      shared: ['src/utils/shared.js']
    }
  }
};

Performance Optimization

Bundle Analysis

# Install bundle analyzer
npm install --save-dev rollup-plugin-analyzer

# Use in config
import analyze from 'rollup-plugin-analyzer';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    analyze({
      summaryOnly: true,
      limit: 10
    })
  ]
};

Optimize Dependencies

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

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    resolve({
      preferBuiltins: false,
      browser: true
    }),
    commonjs({
      include: 'node_modules/**'
    })
  ]
};

Minimize Bundle Size

import { terser } from 'rollup-plugin-terser';
import replace from '@rollup/plugin-replace';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    replace({
      'process.env.NODE_ENV': JSON.stringify('production')
    }),
    terser({
      compress: {
        drop_console: true,
        drop_debugger: true,
        pure_funcs: ['console.log', 'console.info']
      }
    })
  ]
};

Troubleshooting

Common Issues and Solutions

Circular Dependencies

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  onwarn: (warning, warn) => {
    if (warning.code === 'CIRCULAR_DEPENDENCY') {
      console.warn('Circular dependency:', warning.message);
      return;
    }
    warn(warning);
  }
};

External Dependencies Not Found

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

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    resolve({
      browser: true,
      preferBuiltins: false
    })
  ]
};

CommonJS Module Issues

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

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    commonjs({
      include: 'node_modules/**',
      transformMixedEsModules: true
    })
  ]
};

Memory Issues

# Increase Node.js memory limit
node --max-old-space-size=4096 node_modules/.bin/rollup -c

Debug Configuration

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  onwarn: (warning, warn) => {
    console.log('Warning:', warning);
    warn(warning);
  }
};

Best Practices

Configuration Organization

// rollup.config.js
import { createConfig } from './config/rollup.common.js';

const configs = [
  createConfig('es'),
  createConfig('cjs'),
  createConfig('umd')
];

export default configs;

// config/rollup.common.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';

export function createConfig(format) {
  return {
    input: 'src/index.js',
    output: {
      file: `dist/bundle.${format}.js`,
      format
    },
    plugins: [
      resolve(),
      commonjs()
    ]
  };
}

Performance Best Practices

  • Use ES modules for better tree shaking
  • Mark external dependencies to reduce bundle size
  • Enable code splitting for large applications
  • Use terser for production minification
  • Analyze bundles to identify optimization opportunities

Development Best Practices

  • Use watch mode for development
  • Enable source maps for debugging
  • Set up live reload for better DX
  • Configure linting with ESLint
  • Use TypeScript for better type safety

Library Development Best Practices

  • Provide multiple formats (ES, CJS, UMD)
  • Generate TypeScript declarations for TypeScript users
  • Mark peer dependencies as external
  • Use semantic versioning for releases
  • Test builds before publishing

Summary

Rollup is a powerful module bundler that excels at creating optimized bundles for libraries and applications. Key features include:

  • ES Module First: Native support for ES modules with excellent tree shaking
  • Multiple Output Formats: Support for ES, CJS, UMD, IIFE, AMD, and SystemJS
  • Plugin Ecosystem: Rich ecosystem of plugins for various transformations
  • Code Splitting: Advanced code splitting capabilities
  • Tree Shaking: Automatic dead code elimination
  • TypeScript Support: First-class TypeScript integration
  • Library Friendly: Excellent for building and distributing libraries

By leveraging Rollup's strengths and following best practices, you can create highly optimized bundles that are perfect for both library development and application building.