Skip to main content

rollup

Introduction

Overview

  • a module bundler for JavaScript
  • compiles small pieces of code into something larger and more complex, such as a library or application
  • uses the new standardized format for code modules

Installation

npm install --global rollup

Quick start

  • through a command line interface with an optional configuration file
  • through its JavaScript API

For browsers:

# compile to a <script> containing a self-executing function ('iife') 
rollup main.js --file bundle.js --format iife

For Node.js:

# compile to a CommonJS module ('cjs') 
rollup main.js --file bundle.js --format cjs

For both browsers and Node.js:

# UMD format requires a bundle name 
rollup main.js --file bundle.js --format umd --name "myBundle"

The Why

  • easier if break project into smaller separate pieces
  • JavaScript has not historically included this capability as a core feature in the language

Tree-Shaking

statically analyzes the code you are importing, and will exclude anything that isn't actually used

// import the entire utils object with CommonJS
const utils = require('./utils');
const query = 'Rollup';
// use the ajax method of the utils object
utils.ajax(`https://api.example.com?search=${query}`).then(handleResponse);

// import the ajax function with an ES6 import statement
import { ajax } from './utils';
const query = 'Rollup';
// call the ajax function
ajax(`https://api.example.com?search=${query}`).then(handleResponse);

it results in lighter, faster, and less complicated libraries and applications.

Compatibility

  • Importing CommonJS
  • Publishing ES Modules

Command Line Interface

Configuration Files

config file is an ES module that exports a default object with the desired options:

// rollup.config.js
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'cjs'
}
};
  • rollup.config.jsand sits in the root directory of your project
  • transpile and bundle this file and its relative dependencies to CommonJS before requiring it

use other languages for your configuration files like TypeScript:

npm install @rollup/plugin-typescript --save
rollup --config rollup.config.ts --configPlugin typescript

can export an array from your config file to build bundles from several unrelated inputs at once

// rollup.config.js (building more than one bundle)
export default [
{
input: 'main-a.js',
output: {
file: 'dist/bundle-a.js',
format: 'cjs'
}
},
{
input: 'main-b.js',
output: [
{
file: 'dist/bundle-b1.js',
format: 'cjs'
},
{
file: 'dist/bundle-b2.js',
format: 'es'
}
]
}
];

--config --configDebug

// rollup.config.js
import defaultConfig from './rollup.default.config.js';
import debugConfig from './rollup.debug.config.js';

export default commandLineArgs => {
if (commandLineArgs.configDebug === true) {
return debugConfig;
}
return defaultConfig;
};

make Rollup ignore command line arguments by deleting them

// rollup.config.js
export default commandLineArgs => {
const inputBase = commandLineArgs.input || 'main.js';

// this will make Rollup ignore the CLI argument
delete commandLineArgs.input;
return {
input: 'src/entries/' + inputBase,
output: {...}
}
}

Differences to the JavaScript API

config files limit how Rollup can be invoked and configured

  • using the JavaScript API, the configuration passed to rollup.rollup must be an object and cannot be wrapped in a Promise or a function
  • no longer use an array of configurations, should run rollup.rollup once for each set of inputOptions
  • the output option will be ignored, should run bundle.generate(outputOptions) or bundle.write(outputOptions) once for each set of outputOptions

Loading a configuration from a Node package

# this will first try to load the package "rollup-config-my-special-config";
# if that fails, it will then try to load "my-special-config"
rollup --config node:my-special-config

Command line flags

-c, --config <filename>     Use this config file (if argument is used but value
is unspecified, defaults to rollup.config.js)
-d, --dir <dirname> Directory for chunks (if absent, prints to stdout)
-e, --external <ids> Comma-separate list of module IDs to exclude
-f, --format <format> Type of output (amd, cjs, es, iife, umd, system)
-g, --globals <pairs> Comma-separate list of `moduleID:Global` pairs
-h, --help Show this help message
-i, --input <filename> Input (alternative to <entry file>)
-m, --sourcemap Generate sourcemap (`-m inline` for inline map)
-n, --name <name> Name for UMD export
-o, --file <output> Single output file (if absent, prints to stdout)
-p, --plugin <plugin> Use the plugin specified (may be repeated)
-v, --version Show version number
-w, --watch Watch files in bundle and rebuild on changes

JavaScript API

  • rollup.rollup
  • rollup.watch

ES Module Syntax

Importing

Imported values cannot be reassigned, though imported objects and arrays can be mutated

Named Imports

import { something } from './module.js'; 
import { something as somethingElse } from './module.js';

Namespace Imports

import * as module from './module.js';

Default Import

import something from './module.js';

Empty Import

import './module.js';

Dynamic Import

import('./modules.js').then(({ default: DefaultExport, NamedExport }) => {
// do something with modules.
});

Exporting

Named exports

const something = true;
export { something };
export { something as somethingElse };
// this works with `var`, `let`, `const`, `class`, and `function`
export const something = true;

Default Export

export default something;

How bindings work

// incrementer.js
export let count = 0;

export function increment() {
count += 1;
}
// main.js
import { count, increment } from './incrementer.js';

console.log(count); // 0
increment();
console.log(count); // 1

count += 1; // Error — only incrementer.js can change this

Tutorial

Creating Your First Bundle

// src/main.js
import foo from './foo.js';
export default function () {
console.log(foo);
}
// src/foo.js
export default 'hello world!';

rollup src/main.js -o bundle.js -f cjs

Using Config Files

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

rollup --config rollup.config.js

Installing Rollup locally

// install Rollup locally
npm install rollup --save-dev
yarn -D add rollup

npx rollup --config
yarn rollup --config
{
"scripts": {
"build": "rollup --config"
}
}

Using plugins

  • importing modules installed with NPM
  • compiling code with Babel
  • working with JSON files

change the behaviour of Rollup at key points in the bundling process

// package.json
{
"name": "rollup-tutorial",
"version": "1.0.0",
"scripts": {
"build": "rollup -c"
}
}

npm install --save-dev @rollup/plugin-json

// src/main.js
import { version } from '../package.json';

export default function () {
console.log('version ' + version);
}
// rollup.config.js
import json from '@rollup/plugin-json';

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

npm run build

'use strict';

// tree-shaking: Only the data we actually need gets imported
var version = '1.0.0';

function main() {
console.log('version ' + version);
}

module.exports = main;

Using output plugins

can only modify code after the main analysis of Rollup has completed

npm install --save-dev rollup-plugin-terser

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

export default {
input: 'src/main.js',
output: [
{
file: 'bundle.js',
format: 'cjs'
},
{
file: 'bundle.min.js',
format: 'iife',
name: 'version',
plugins: [terser()]
}
],
plugins: [json()]
};
// bundle.min.js
var version = (function () {
'use strict';
var n = '1.0.0';
return function () {
console.log('version ' + n);
};
})();

Code Splitting

Rollup splits code into chunks automatically

  • dynamic loading
  • multiple entry points
// src/main.js
export default function () {
import('./foo.js').then(({ default: foo }) => console.log(foo));
}

rollup src/main.js -f cjs -d dist

main.js, chunk-[hash].js

specify several entry points that share some dependencies

// src/main2.js
import foo from './foo.js';
export default function () {
console.log(foo);
}

rollup src/main.js src/main2.js -f cjs

//→ main.js:
'use strict';

function main() {
Promise.resolve(require('./chunk-b8774ea3.js')).then(({ default: foo }) => console.log(foo));
}

module.exports = main;

//→ main2.js:
('use strict');

var foo_js = require('./chunk-b8774ea3.js');

function main2() {
console.log(foo_js.default);
}

module.exports = main2;

//→ chunk-b8774ea3.js:
('use strict');

var foo = 'hello world!';

exports.default = foo;