Menu
rollup.js

Introduction

Overview

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, instead of previous idiosyncratic solutions such as CommonJS and AMD. ES modules let you freely and seamlessly combine the most useful individual functions from your favorite libraries. This will eventually be possible natively everywhere, but Rollup lets you do it today.

Quick start

Install with npm install --global rollup. Rollup can be used either through a command line interface with an optional configuration file, or else through its JavaScript API. Run rollup --help to see the available options and parameters.

See rollup-starter-lib and rollup-starter-app to see example library and application projects using Rollup

These commands assume the entry point to your application is named main.js, and that you'd like all imports compiled into a single file named bundle.js.

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

Developing software is usually easier if you break your project into smaller separate pieces, since that often removes unexpected interactions and dramatically reduces the complexity of the problems you'll need to solve, and simply writing smaller projects in the first place isn't necessarily the answer. Unfortunately, JavaScript has not historically included this capability as a core feature in the language.

This finally changed with the ES6 revision of JavaScript, which includes a syntax for importing and exporting functions and data so they can be shared between separate scripts. The specification is now fixed, but it is only implemented in modern browsers and not finalised in Node.js. Rollup allows you to write your code using the new module system, and will then compile it back down to existing supported formats such as CommonJS modules, AMD modules, and IIFE-style scripts. This means that you get to write future-proof code, and you also get the tremendous benefits of...

Tree-Shaking

In addition to enabling the use of ES modules, Rollup also statically analyzes the code you are importing, and will exclude anything that isn't actually used. This allows you to build on top of existing tools and modules without adding extra dependencies or bloating the size of your project.

For example, with CommonJS, the entire tool or library must be imported.

// 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);

But with ES modules, instead of importing the whole utils object, we can just import the one ajax function we need:

// 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);

Because Rollup includes the bare minimum, it results in lighter, faster, and less complicated libraries and applications. Since this approach can utilise explicit import and export statements, it is more effective than simply running an automated minifier to detect unused variables in the compiled output code.

Compatibility

Importing CommonJS

Rollup can import existing CommonJS modules through a plugin.

Publishing ES Modules

To make sure your ES modules are immediately usable by tools that work with CommonJS such as Node.js and webpack, you can use Rollup to compile to UMD or CommonJS format, and then point to that compiled version with the main property in your package.json file. If your package.json file also has a module field, ESM-aware tools like Rollup and webpack 2+ will import the ES module version directly.

Command Line Interface

Rollup should typically be used from the command line. You can provide an optional Rollup configuration file to simplify command line usage and enable advanced Rollup functionality.

Configuration Files

Rollup configuration files are optional, but they are powerful and convenient and thus recommended.

A config file is an ES module that exports a default object with the desired options. Typically, it is called rollup.config.js and sits in the root directory of your project.

Also you can use CJS modules syntax for the config file.

module.exports = {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  }
};

It may be pertinent if you want to use the config file not only from the command line, but also from your custom scripts programmatically.

Consult the big list of options for details on each option you can include in your config file.

// rollup.config.js

export default { // can be an array (for multiple inputs)
  // core input options
  external,
  input, // required
  plugins,

  // advanced input options
  cache,
  inlineDynamicImports,
  manualChunks,
  onwarn,
  preserveModules,

  // danger zone
  acorn,
  acornInjectPlugins,
  context,
  moduleContext,
  preserveSymlinks,
  shimMissingExports,
  treeshake,

  // experimental
  chunkGroupingSize,
  experimentalCacheExpiry,
  experimentalOptimizeChunks,
  experimentalTopLevelAwait,
  perf,

  output: { // required (can be an array, for multiple outputs)
    // core output options
    dir,
    file,
    format, // required
    globals,
    name,

    // advanced output options
    assetFileNames,
    banner,
    chunkFileNames,
    compact,
    entryFileNames,
    extend,
    footer,
    interop,
    intro,
    outro,
    paths,
    sourcemap,
    sourcemapExcludeSources,
    sourcemapFile,
    sourcemapPathTransform,

    // danger zone
    amd,
    dynamicImportFunction,
    esModule,
    exports,
    freeze,
    indent,
    namespaceToStringTag,
    noConflict,
    preferConst,
    strict
  },

  watch: {
    chokidar,
    clearScreen,
    exclude,
    include
  }
};

You can export an array from your config file to build bundles from several different unrelated inputs at once, even in watch mode. To build different bundles with the same input, you supply an array of output options for each input:

// 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: 'esm'
    }
  ]
}];

If you want to create your config asynchronously, Rollup can also handle a Promise which resolves to an object or an array.

// rollup.config.js
import fetch from 'node-fetch';
export default fetch('/some-remote-service-or-file-which-returns-actual-config');

Similarly, you can do this as well:

// rollup.config.js (Promise resolving an array)
export default Promise.all([
  fetch('get-config-1'),
  fetch('get-config-2')
])

You must use a configuration file in order to do any of the following:

To use Rollup with a configuration file, pass the --config or -c flags.

# use Rollup with a rollup.config.js file
$ rollup --config

# alternatively, specify a custom config file location
$ rollup --config my.config.js

You can also export a function that returns any of the above configuration formats. This function will be passed the current command line arguments so that you can dynamically adapt your configuration to respect e.g. --silent. You can even define your own command line options if you prefix them with config:

// 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;
}

If you now run rollup --config --configDebug, the debug configuration will be used.

Command line flags

Many options have command line equivalents. In those cases, any arguments passed here will override the config file, if you're using one. This is a list of all supported options:

-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, esm, iife, umd)
-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)
-v, --version               Show version number
-w, --watch                 Watch files in bundle and rebuild on changes
--amd.id <id>               ID for AMD module (default is anonymous)
--amd.define <name>         Function to use in place of `define`
--assetFileNames <pattern>  Name pattern for emitted assets
--banner <text>             Code to insert at top of bundle (outside wrapper)
--chunkFileNames <pattern>  Name pattern for emitted secondary chunks
--compact                   Minify wrapper code
--context <variable>        Specify top-level `this` value
--dynamicImportFunction <name>         Rename the dynamic `import()` function
--entryFileNames <pattern>  Name pattern for emitted entry chunks
--environment <values>      Settings passed to config file (see example)
--no-esModule               Do not add __esModule property
--exports <mode>            Specify export mode (auto, default, named, none)
--extend                    Extend global variable defined by --name
--footer <text>             Code to insert at end of bundle (outside wrapper)
--no-freeze                 Do not freeze namespace objects
--no-indent                 Don't indent result
--no-interop                Do not include interop block
--inlineDynamicImports      Create single bundle when using dynamic imports
--intro <text>              Code to insert at top of bundle (inside wrapper)
--namespaceToStringTag      Create proper `.toString` methods for namespaces
--noConflict                Generate a noConflict method for UMD globals
--no-strict                 Don't emit `"use strict";` in the generated modules
--outro <text>              Code to insert at end of bundle (inside wrapper)
--preferConst               Use `const` instead of `var` for exports
--preserveModules           Preserve module structure
--preserveSymlinks          Do not follow symlinks when resolving files
--shimMissingExports        Create shim variables for missing exports
--silent                    Don't print warnings
--sourcemapExcludeSources   Do not include source code in source maps
--sourcemapFile <file>      Specify bundle position for source maps
--no-treeshake              Disable tree-shaking optimisations
--no-treeshake.annotations  Ignore pure call annotations
--no-treeshake.propertyReadSideEffects Ignore property access side-effects
--treeshake.pureExternalModules        Assume side-effect free externals

The flags listed below are only available via the command line interface. All other flags correspond to and override their config file equivalents, see the big list of options for details.

-h/--help

Print the help document.

-v/--version

Print the installed version number.

-w/--watch

Rebuild the bundle when its source files change on disk.

--silent

Don't print warnings to the console.

--environment <values>

Pass additional settings to the config file via process.ENV.

rollup -c --environment INCLUDE_DEPS,BUILD:production

will set process.env.INCLUDE_DEPS === 'true' and process.env.BUILD === 'production'. You can use this option several times. In that case, subsequently set variables will overwrite previous definitions. This enables you for instance to overwrite environment variables in package.json scripts:

// in package.json
{
  "scripts": {
    "build": "rollup -c --environment INCLUDE_DEPS,BUILD:production"
  }
}

If you call this script via:

npm run build -- --environment BUILD:development

then the config file will receive process.env.INCLUDE_DEPS === 'true' and process.env.BUILD === 'development'.

JavaScript API

Rollup provides a JavaScript API which is usable from Node.js. You will rarely need to use this, and should probably be using the command line API unless you are extending Rollup itself or using it for something esoteric, such as generating bundles programmatically.

rollup.rollup

The rollup.rollup function returns a Promise that resolves to a bundle object with various properties and methods shown here:

const rollup = require('rollup');

// see below for details on the options
const inputOptions = {...};
const outputOptions = {...};

async function build() {
  // create a bundle
  const bundle = await rollup.rollup(inputOptions);

  console.log(bundle.watchFiles); // an array of file names this bundle depends on

  // generate code
  const { output } = await bundle.generate(outputOptions);

  for (const chunkOrAsset of output) {
    if (chunkOrAsset.isAsset) {
      // For assets, this contains
      // {
      //   isAsset: true,                 // signifies that this is an asset
      //   fileName: string,              // the asset file name
      //   source: string | Buffer        // the asset source
      // }
      console.log('Asset', chunkOrAsset);
    } else {
      // For chunks, this contains
      // {
      //   code: string,                  // the generated JS code
      //   dynamicImports: string[],      // external modules imported dynamically by the chunk
      //   exports: string[],             // exported variable names
      //   facadeModuleId: string | null, // the id of a module that this chunk corresponds to
      //   fileName: string,              // the chunk file name
      //   imports: string[],             // external modules imported statically by the chunk
      //   isDynamicEntry: boolean,       // is this chunk a dynamic entry point
      //   isEntry: boolean,              // is this chunk a static entry point
      //   map: string | null,            // sourcemaps if present
      //   modules: {                     // information about the modules in this chunk
      //     [id: string]: {
      //       renderedExports: string[]; // exported variable names that were included
      //       removedExports: string[];  // exported variable names that were removed
      //       renderedLength: number;    // the length of the remaining code in this module
      //       originalLength: number;    // the original length of the code in this module
      //     };
      //   },
      //   name: string                   // the name of this chunk as used in naming patterns
      // }
      console.log('Chunk', chunkOrAsset.modules);
    }
  }

  // or write the bundle to disk
  await bundle.write(outputOptions);
}

build();

inputOptions

The inputOptions object can contain the following properties (see the big list of options for full details on these):

const inputOptions = {
  // core input options
  external,
  input, // required
  plugins,

  // advanced input options
  cache,
  inlineDynamicImports,
  manualChunks,
  onwarn,
  preserveModules,

  // danger zone
  acorn,
  acornInjectPlugins,
  context,
  moduleContext,
  preserveSymlinks,
  shimMissingExports,
  treeshake,

  // experimental
  chunkGroupingSize,
  experimentalCacheExpiry,
  experimentalOptimizeChunks,
  experimentalTopLevelAwait,
  perf
};

outputOptions

The outputOptions object can contain the following properties (see the big list of options for full details on these):

const outputOptions = {
    // core output options
    dir,
    file,
    format, // required
    globals,
    name,

    // advanced output options
    assetFileNames,
    banner,
    chunkFileNames,
    compact,
    entryFileNames,
    extend,
    footer,
    interop,
    intro,
    outro,
    paths,
    sourcemap,
    sourcemapExcludeSources,
    sourcemapFile,
    sourcemapPathTransform,

    // danger zone
    amd,
    dynamicImportFunction,
    esModule,
    exports,
    freeze,
    indent,
    namespaceToStringTag,
    noConflict,
    preferConst,
    strict
};

rollup.watch

Rollup also provides a rollup.watch function that rebuilds your bundle when it detects that the individual modules have changed on disk. It is used internally when you run Rollup from the command line with the --watch flag.

const rollup = require('rollup');

const watchOptions = {...};
const watcher = rollup.watch(watchOptions);

watcher.on('event', event => {
  // event.code can be one of:
  //   START        — the watcher is (re)starting
  //   BUNDLE_START — building an individual bundle
  //   BUNDLE_END   — finished building a bundle
  //   END          — finished building all bundles
  //   ERROR        — encountered an error while bundling
  //   FATAL        — encountered an unrecoverable error
});

// stop watching
watcher.close();

watchOptions

The watchOptions argument is a config (or an array of configs) that you would export from a config file.

const watchOptions = {
  ...inputOptions,
  output: [outputOptions],
  watch: {
    chokidar,
    clearScreen,
    exclude,
    include
  }
};

See above for details on inputOptions and outputOptions, or consult the big list of options for info on chokidar, include and exclude.

ES Module Syntax

The following is intended as a lightweight reference for the module behaviors defined in the ES2015 specification, since a proper understanding of the import and export statements are essential to the successful use of Rollup.

Importing

Imported values cannot be reassigned, though imported objects and arrays can be mutated (and the exporting module, and any other importers, will be affected by the mutation). In that way, they behave similarly to const declarations.

Named Imports

Import a specific item from a source module, with its original name.

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

Import a specific item from a source module, with a custom name assigned upon import.

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

Namespace Imports

Import everything from the source module as an object which exposes all the source module's named exports as properties and methods.

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

The something example from above would then be attached to the imported object as a property, e.g. module.something. If present, the default export can be accessed via module.default.

Default Import

Import the default export of the source module.

import something from './module.js';

Empty Import

Load the module code, but don't make any new objects available.

import './module.js';

This is useful for polyfills, or when the primary purpose of the imported code is to muck about with prototypes.

Dynamic Import

Import modules using the dynamic import API.

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

This is useful for code-splitting applications and using modules on-the-fly.

Exporting

Named exports

Export a value that has been previously declared:

const something = true;
export { something };

Rename on export:

export { something as somethingElse };

Export a value immediately upon declaration:

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

Default Export

Export a single value as the source module's default export:

export default something;

This practice is only recommended if your source module only has one export.

It is bad practice to mix default and named exports in the same module, though it is allowed by the specification.

How bindings work

ES modules export live bindings, not values, so values can be changed after they are initially imported as per this demo:

// 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

Before we begin, you'll need to have Node.js installed so that you can use NPM. You'll also need to know how to access the command line on your machine.

The easiest way to use Rollup is via the Command Line Interface (or CLI). For now, we'll install it globally (later on we'll learn how to install it locally to your project so that your build process is portable, but don't worry about that yet). Type this into the command line:

npm install rollup --global
# or `npm i rollup -g` for short

You can now run the rollup command. Try it!

rollup

Because no arguments were passed, Rollup prints usage instructions. This is the same as running rollup --help, or rollup -h.

Let's create a simple project:

mkdir -p my-rollup-project/src
cd my-rollup-project

First, we need an entry point. Paste this into a new file called src/main.js:

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

Then, let's create the foo.js module that our entry point imports:

// src/foo.js
export default 'hello world!';

Now we're ready to create a bundle:

rollup src/main.js -f cjs

The -f option (short for --format) specifies what kind of bundle we're creating — in this case, CommonJS (which will run in Node.js). Because we didn't specify an output file, it will be printed straight to stdout:

'use strict';

const foo = 'hello world!';

const main = function () {
  console.log(foo);
};

module.exports = main;

You can save the bundle as a file like so:

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

(You could also do rollup src/main.js -f cjs > bundle.js, but as we'll see later, this is less flexible if you're generating sourcemaps.)

Try running the code:

node
> var myBundle = require('./bundle.js');
> myBundle();
'hello world!'

Congratulations! You've created your first bundle with Rollup.

Using Config Files

So far, so good, but as we start adding more options it becomes a bit of a nuisance to type out the command.

To save repeating ourselves, we can create a config file containing all the options we need. A config file is written in JavaScript and is more flexible than the raw CLI.

Create a file in the project root called rollup.config.js, and add the following code:

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

(Note that you can use CJS modules as well, to wit, module.exports = {/* config */})

To use the config file, we use the --config or -c flag:

rm bundle.js # so we can check the command works!
rollup -c

You can override any of the options in the config file with the equivalent command line options:

rollup -c -o bundle-2.js # `-o` is equivalent to `--file` (formerly "output")

Note: Rollup itself processes the config file, which is why we're able to use export default syntax – the code isn't being transpiled with Babel or anything similar, so you can only use ES2015 features that are supported in the version of Node.js that you're running.

You can, if you like, specify a different config file from the default rollup.config.js:

rollup --config rollup.config.dev.js
rollup --config rollup.config.prod.js

Using plugins

So far, we've created a simple bundle from an entry point and a module imported via a relative path. As you build more complex bundles, you'll often need more flexibility – importing modules installed with NPM, compiling code with Babel, working with JSON files and so on.

For that, we use plugins, which change the behaviour of Rollup at key points in the bundling process. A list of awesome plugins is maintained on the Rollup Awesome List.

For this tutorial, we'll use rollup-plugin-json, which allows Rollup to import data from a JSON file.

Create a file in the project root called package.json, and add the following content:

{
  "name": "rollup-tutorial",
  "version": "1.0.0",
  "scripts": {
    "build": "rollup -c"
  }
}

Install rollup-plugin-json as a development dependency:

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

(We're using --save-dev rather than --save because our code doesn't actually depend on the plugin when it runs – only when we're building the bundle.)

Update your src/main.js file so that it imports from your package.json instead of src/foo.js:

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

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

Edit your rollup.config.js file to include the JSON plugin:

// rollup.config.js
import json from 'rollup-plugin-json';

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

Run Rollup with npm run build. The result should look like this:

'use strict';

const version = "1.0.0";

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

module.exports = main;

Note: Only the data we actually need gets imported – name and devDependencies and other parts of package.json are ignored. That's tree-shaking in action!

Code Splitting

To use the code splitting feature, we got back to the original example and modify src/main.js to load src/foo.js dynamically instead of statically:

// src/main.js
export default function () {
  import('./foo.js').then(({ default: foo }) => console.log(foo));
}

Rollup will use the dynamic import to create a separate chunk that is only loaded on demand. In order for Rollup to know where to place the second chunk, instead of passing the --file option we set a folder to output to with the --dir option:

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

This will create a folder dist containing two files, main.js and chunk-[hash].js, where [hash] is a content based hash string. You can supply your own naming patterns by specifying the output.chunkFileNames and output.entryFileNames options.

You can still run your code as before with the same output, albeit a little slower as loading and parsing of ./foo.js will only commence once we call the exported function for the first time.

node -e "require('./dist/main.js')()"

If we do not use the --dir option, Rollup will again print the chunks to stdout, adding comments to highlight the chunk boundaries:

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

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

module.exports = main;

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

var foo = 'hello world!';

exports.default = foo;

This is very useful if you want to load and parse expensive features only once they are used.

A different use for code-splitting is the ability to specify several entry points that share some dependencies. Again we extend our example to add a second entry point src/main2.js that statically imports src/foo.js just like we did in the original example:

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

If we supply both entry points to rollup, three chunks are created:

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

will output

//→ 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;

Notice how both entry points import the same shared chunk. Rollup will never duplicate code and instead create additional chunks to only ever load the bare minimum necessary. Again, passing the --dir option will write the files to disk.

You can build the same code for the browser via native ES modules, an AMD loader or SystemJS.

For example, with -f esm for native modules:

rollup src/main.js src/main2.js -f esm -d dist
<!doctype html>
<script type="module">
  import main2 from './dist/main2.js';
  main2();
</script>

Or alternatively, for SystemJS with -f system:

rollup src/main.js src/main2.js -f system -d dist

Install SystemJS via

npm install --save-dev systemjs

And then load either or both entry points in an HTML page as needed:

<!doctype html>
<script src="node_modules/systemjs/dist/system-production.js"></script>
<script>
  System.import('./dist/main2.js')
  .then(({ default: main }) => main());
</script>

See rollup-starter-code-splitting for an example on how to set up a web app that uses native ES modules on browsers that support them with a fallback to SystemJS if necessary.

Plugins

Plugins Overview

A Rollup plugin is an object with one or more of the properties and hooks described below, and which follows our conventions. A plugin should be distributed as a packages which exports a function that can be called with plugin specific options and returns such an object.

Plugins allow you to customise Rollup's behaviour by, for example, transpiling code before bundling, or finding third-party modules in your node_modules folder. For an example on how to use them, see Using plugins.

A List of Plugins may be found at https://github.com/rollup/awesome. If you would like to make a suggestion for a plugin, please submit a Pull Request.

A Simple Example

The following plugin will intercept any imports of virtual-module without accessing the file system. This is for instance necessary if you want to use Rollup in a browser. It can even be used to replace entry points as shown in the example.

// rollup-plugin-my-example.js
export default function myExample () {
  return {
    name: 'my-example', // this name will show up in warnings and errors
    resolveId ( source ) {
      if (source === 'virtual-module') {
        return source; // this signals that rollup should not ask other plugins or check the file system to find this id
      }
      return null; // other ids should be handled as usually
    },
    load ( id ) {
      if (id === 'virtual-module') {
        return 'export default "This is virtual!"'; // the source code for "virtual-module"
      }
      return null; // other ids should be handled as usually
    }
  };
}

// rollup.config.js
import myExample from './rollup-plugin-my-example.js';
export default ({
  input: 'virtual-module', // resolved by our plugin
  plugins: [myExample()],
  output: [{
    file: 'bundle.js',
    format: 'esm'
  }]
});

Conventions

  • Plugins should have a clear name with rollup-plugin- prefix.
  • Include rollup-plugin keyword in package.json.
  • Plugins should be tested. We recommend mocha or ava which support promises out of the box.
  • Use asynchronous methods when it is possible.
  • Document your plugin in English.
  • Make sure your plugin outputs correct source mappings if appropriate.
  • If your plugin uses 'virtual modules' (e.g. for helper functions), prefix the module ID with \0. This prevents other plugins from trying to process it.

Properties

name

Type: string

The name of the plugin, for use in error messages and warnings.

Hooks

In addition to properties defining the identity of your plugin, you may also specify properties that correspond to available build hooks. Hooks can affect how a build is run, provide information about a build, or modify a build once complete. There are different kinds of hooks:

  • async: The hook can also return a promise resolving to the same type of value; otherwise, the hook is marked as sync
  • first: If several plugins implement this hook, the hooks are run sequentially until a hook returns a value other than null or undefined
  • sequential: If this hook returns a promise, then other hooks of this kind will only be executed once this hook has resolved
  • parallel: If this hook returns a promise, then other hooks of this kind will not wait for this hook to be resolved

Type: string | (() => string)
Kind: async, parallel

Cf. output.banner/output.footer.

buildEnd

Type: (error?: Error) => void
Kind: async, parallel

Called when rollup has finished bundling, but before generate or write is called; you can also return a Promise. If an error occurred during the build, it is passed on to this hook.

buildStart

Type: (options: InputOptions) => void
Kind: async, parallel

Called on each rollup.rollup build.

Type: string | (() => string)
Kind: async, parallel

Cf. output.banner/output.footer.

generateBundle

Type: (options: OutputOptions, bundle: { [fileName: string]: AssetInfo | ChunkInfo }, isWrite: boolean) => void
Kind: async, sequential

Called at the end of bundle.generate() or immediately before the files are written in bundle.write(). To modify the files after they have been written, use the writeBundle hook. bundle provides the full list of files being written or generated along with their details:

// AssetInfo
{
  fileName: string,
  isAsset: true,
  source: string | Buffer
}

// ChunkInfo
{
  code: string,
  dynamicImports: string[],
  exports: string[],
  facadeModuleId: string | null,
  fileName: string,
  imports: string[],
  isDynamicEntry: boolean,
  isEntry: boolean,
  map: SourceMap | null,
  modules: {
    [id: string]: {
      renderedExports: string[],
      removedExports: string[],
      renderedLength: number,
      originalLength: number
    },
  },
  name: string
}

intro

Type: string | (() => string)
Kind: async, parallel

Cf. output.intro/output.outro.

load

Type: (id: string) => string | null | { code: string, map?: string | SourceMap, ast? : ESTree.Program, moduleSideEffects?: boolean | null }
Kind: async, first

Defines a custom loader. Returning null defers to other load functions (and eventually the default behavior of loading from the file system). To prevent additional parsing overhead in case e.g. this hook already used this.parse to generate an AST for some reason, this hook can optionally return a { code, ast } object. The ast must be a standard ESTree AST with start and end properties for each node.

If false is returned for moduleSideEffects and no other module imports anything from this module, then this module will not be included in the bundle without checking for actual side-effects inside the module. If true is returned, Rollup will use its default algorithm to include all statements in the module that have side-effects (such as modifying a global or exported variable). If null is returned or the flag is omitted, then moduleSideEffects will be determined by the first resolveId hook that resolved this module, the treeshake.moduleSideEffects option, or eventually default to true. The transform hook can override this.

You can use this.getModuleInfo to find out the previous value of moduleSideEffects inside this hook.

options

Type: (options: InputOptions) => InputOptions | null
Kind: sync, sequential

Reads and replaces or manipulates the options object passed to rollup.rollup. Returning null does not replace anything. This is the only hook that does not have access to most plugin context utility functions as it is run before rollup is fully configured.

outputOptions

Type: (outputOptions: OutputOptions) => OutputOptions | null
Kind: sync, sequential

Reads and replaces or manipulates the output options object passed to bundle.generate. Returning null does not replace anything.

outro

Type: string | (() => string)
Kind: async, parallel

Cf. output.intro/output.outro.

renderChunk

Type: (code: string, chunk: ChunkInfo, options: OutputOptions) => string | { code: string, map: SourceMap } | null
Kind: async, sequential

Can be used to transform individual chunks. Called for each Rollup output chunk file. Returning null will apply no transformations.

renderError

Type: (error: Error) => void
Kind: async, parallel

Called when rollup encounters an error during bundle.generate() or bundle.write(). The error is passed to this hook. To get notified when generation completes successfully, use the generateBundle hook.

renderStart

Type: () => void
Kind: async, parallel

Called initially each time bundle.generate() or bundle.write() is called. To get notified when generation has completed, use the generateBundle and renderError hooks.

resolveDynamicImport

Type: (specifier: string | ESTree.Node, importer: string) => string | false | null | {id: string, external?: boolean}
Kind: async, first

Defines a custom resolver for dynamic imports. Returning false signals that the import should be kept as it is and not be passed to other resolvers thus making it external. Similar to the resolveId hook, you can also return an object to resolve the import to a different id while marking it as external at the same time.

In case a dynamic import is passed a string as argument, a string returned from this hook will be interpreted as an existing module id while returning null will defer to other resolvers and eventually to resolveId .

In case a dynamic import is not passed a string as argument, this hook gets access to the raw AST nodes to analyze and behaves slightly different in the following ways:

  • If all plugins return null, the import is treated as external without a warning.
  • If a string is returned, this string is not interpreted as a module id but is instead used as a replacement for the import argument. It is the responsibility of the plugin to make sure the generated code is valid.
  • To resolve such an import to an existing module, you can still return an object {id, external}.

Note that the return value of this hook will not be passed to resolveId afterwards; if you need access to the static resolution algorithm, you can use this.resolve(source, importer) on the plugin context.

resolveFileUrl

Type: ({assetReferenceId: string | null, chunkId: string, chunkReferenceId: string | null, fileName: string, format: string, moduleId: string, relativePath: string}) => string | null
Kind: sync, first

Allows to customize how Rollup resolves URLs of files that were emitted by plugins via this.emitAsset or this.emitChunk. By default, Rollup will generate code for import.meta.ROLLUP_ASSET_URL_assetReferenceId and import.meta.ROLLUP_CHUNK_URL_chunkReferenceId that should correctly generate absolute URLs of emitted files independent of the output format and the host system where the code is deployed.

For that, all formats except CommonJS and UMD assume that they run in a browser environment where URL and document are available. In case that fails or to generate more optimized code, this hook can be used to customize this behaviour. To do that, the following information is available:

  • assetReferenceId: The asset reference id if we are resolving import.meta.ROLLUP_ASSET_URL_assetReferenceId, otherwise null.
  • chunkId: The id of the chunk this file is referenced from.
  • chunkReferenceId: The chunk reference id if we are resolving import.meta.ROLLUP_CHUNK_URL_chunkReferenceId, otherwise null.
  • fileName: The path and file name of the emitted asset, relative to output.dir without a leading ./.
  • format: The rendered output format.
  • moduleId: The id of the original module this file is referenced from. Useful for conditionally resolving certain assets differently.
  • relativePath: The path and file name of the emitted file, relative to the chunk the file is referenced from. This will path will contain no leading ./ but may contain a leading ../.

Note that since this hook has access to the filename of the current chunk, its return value will not be considered when generating the hash of this chunk.

The following plugin will always resolve all files relative to the current document:

// rollup.config.js
resolveFileUrl({fileName}) {
  return `new URL('${fileName}', document.baseURI).href`;
}

resolveId

Type: (source: string, importer: string) => string | false | null | {id: string, external?: boolean, moduleSideEffects?: boolean | null}
Kind: async, first

Defines a custom resolver. A resolver can be useful for e.g. locating third-party dependencies. Returning null defers to other resolveId functions and eventually the default resolution behavior; returning false signals that source should be treated as an external module and not included in the bundle.

If you return an object, then it is possible to resolve an import to a different id while excluding it from the bundle at the same time. This allows you to replace dependencies with external dependencies without the need for the user to mark them as "external" manually via the external option:

resolveId(source) {
  if (source === 'my-dependency') {
    return {source: 'my-dependency-develop', external: true};
  }
  return null;
}

If false is returned for moduleSideEffects in the first hook that resolves a module id and no other module imports anything from this module, then this module will not be included without checking for actual side-effects inside the module. If true is returned, Rollup will use its default algorithm to include all statements in the module that have side-effects (such as modifying a global or exported variable). If null is returned or the flag is omitted, then moduleSideEffects will be determined by the treeshake.moduleSideEffects option or default to true. The load and transform hooks can override this.

resolveImportMeta

Type: (property: string | null, {chunkId: string, moduleId: string, format: string}) => string | null
Kind: sync, first

Allows to customize how Rollup handles import.meta and import.meta.someProperty, in particular import.meta.url. In ES modules, import.meta is an object and import.meta.url contains the URL of the current module, e.g. http://server.net/bundle.js for browsers or file:///path/to/bundle.js in Node.

By default for formats other than ES modules, Rollup replaces import.meta.url with code that attempts to match this behaviour by returning the dynamic URL of the current chunk. Note that all formats except CommonJS and UMD assume that they run in a browser environment where URL and document are available. For other properties, import.meta.someProperty is replaced with undefined while import.meta is replaced with an object containing a url property.

This behaviour can be changed—also for ES modules—via this hook. For each occurrence of import.meta<.someProperty>, this hook is called with the name of the property or null if import.meta is accessed directly. For example, the following code will resolve import.meta.url using the relative path of the original module to the current working directory and again resolve this path against the base URL of the current document at runtime:

// rollup.config.js
resolveImportMeta(property, {moduleId}) {
  if (property === 'url') {
    return `new URL('${path.relative(process.cwd(), moduleId)}', document.baseURI).href`;
  }
  return null;
}

Note that since this hook has access to the filename of the current chunk, its return value will not be considered when generating the hash of this chunk.

transform

Type: (code: string, id: string) => string | null | { code: string, map?: string | SourceMap, ast? : ESTree.Program, moduleSideEffects?: boolean | null }
Kind: async, sequential

Can be used to transform individual modules. To prevent additional parsing overhead in case e.g. this hook already used this.parse to generate an AST for some reason, this hook can optionally return a { code, ast } object. The ast must be a standard ESTree AST with start and end properties for each node.

Note that in watch mode, the result of this hook is cached when rebuilding and the hook is only triggered again for a module id if either the code of the module has changed or a file has changed that was added via this.addWatchFile the last time the hook was triggered for this module.

If false is returned for moduleSideEffects and no other module imports anything from this module, then this module will not be included without checking for actual side-effects inside the module. If true is returned, Rollup will use its default algorithm to include all statements in the module that have side-effects (such as modifying a global or exported variable). If null is returned or the flag is omitted, then moduleSideEffects will be determined by the first resolveId hook that resolved this module, the treeshake.moduleSideEffects option, or eventually default to true.

You can use this.getModuleInfo to find out the previous value of moduleSideEffects inside this hook.

watchChange

Type: (id: string) => void
Kind: sync, sequential

Notifies a plugin whenever rollup has detected a change to a monitored file in --watch mode.

writeBundle

Type: ( bundle: { [fileName: string]: AssetInfo | ChunkInfo }) => void
Kind: async, parallel

Called only at the end of bundle.write() once all files have been written. Similar to the generateBundle hook, bundle provides the full list of files being written along with their details.

Deprecated Hooks

☢️ These hooks have been deprecated and may be removed in a future Rollup version.

  • ongenerate - Use generateBundle - Function hook called when bundle.generate() is being executed.

  • onwrite - Use generateBundle - Function hook called when bundle.write() is being executed, after the file has been written to disk.

  • resolveAssetUrl - Use resolveFileUrl - Function hook that allows to customize the generated code for asset URLs.

  • transformBundleUse renderChunk - A ( source, { format } ) => code or ( source, { format } ) => { code, map } bundle transformer function.

  • transformChunkUse renderChunk - A ( source, outputOptions, chunk ) => code | { code, map} chunk transformer function.

More properties may be supported in future, as and when they prove necessary.

Plugin Context

A number of utility functions and informational bits can be accessed from within most hooks via this:

this.addWatchFile(id: string) => void

Adds additional files to be monitored in watch mode so that changes to these files will trigger rebuilds. id can be an absolute path to a file or directory or a path relative to the current working directory. This context function can only be used in hooks during the build phase, i.e. in buildStart, load, resolveId, and transform.

Note: Usually in watch mode to improve rebuild speed, the transform hook will only be triggered for a given module if its contents actually changed. Using this.addWatchFile from within the transform hook will make sure the transform hook is also reevaluated for this module if the watched file changes.

In general, it is recommended to use this.addWatchfile from within the hook that depends on the watched file.

this.emitAsset(assetName: string, source: string) => string

Emits a custom file that is included in the build output, returning an assetReferenceId that can be used to reference the emitted file. You can defer setting the source if you provide it later via this.setAssetSource(assetReferenceId, source). A string or Buffer source must be set for each asset through either method or an error will be thrown on generate completion.

Emitted assets will follow the output.assetFileNames naming scheme. You can reference the URL of the file in any code returned by a load or transform plugin hook via import.meta.ROLLUP_ASSET_URL_assetReferenceId. See Asset URLs for more details and an example.

The generated code that replaces import.meta.ROLLUP_ASSET_URL_assetReferenceId can be customized via the resolveFileUrl plugin hook. Once the asset has been finalized during generate, you can also use this.getAssetFileName(assetReferenceId) to determine the file name.

this.emitChunk(moduleId: string, options?: {name?: string}) => string

Emits a new chunk with the given module as entry point. This will not result in duplicate modules in the graph, instead if necessary, existing chunks will be split. It returns a chunkReferenceId that can be used to later access the generated file name of the chunk.

Emitted chunks will follow the output.chunkFileNames, output.entryFileNames naming scheme. If a name is provided, this will be used for the [name] file name placeholder, otherwise the name will be derived from the file name. If a name is provided, this name must not conflict with any other entry point names unless the entry points reference the same entry module. You can reference the URL of the emitted chunk in any code returned by a load or transform plugin hook via import.meta.ROLLUP_CHUNK_URL_chunkReferenceId.

The generated code that replaces import.meta.ROLLUP_CHUNK_URL_chunkReferenceId can be customized via the resolveFileUrl plugin hook. Once the chunk has been rendered during generate, you can also use this.getChunkFileName(chunkReferenceId) to determine the file name.

this.error(error: string | Error, position?: number) => void

Structurally equivalent to this.warn, except that it will also abort the bundling process.

this.getAssetFileName(assetReferenceId: string) => string

Get the file name of an asset, according to the assetFileNames output option pattern. The file name will be relative to outputOptions.dir.

this.getChunkFileName(chunkReferenceId: string) => string

Get the file name of an emitted chunk. The file name will be relative to outputOptions.dir.

this.getModuleInfo(moduleId: string) => ModuleInfo

Returns additional information about the module in question in the form

{
  id: string, // the id of the module, for convenience
  isEntry: boolean, // is this a user- or plugin-defined entry point
  isExternal: boolean, // for external modules that are not included in the graph
  importedIds: string[], // the module ids imported by this module
  hasModuleSideEffects: boolean // are imports of this module included if nothing is imported from it
}

If the module id cannot be found, an error is thrown.

this.meta: {rollupVersion: string}

An Object containing potentially useful Rollup metadata. meta is the only context property accessible from the options hook.

this.moduleIds: IterableIterator<string>

An Iterator that gives access to all module ids in the current graph. It can be iterated via

for (const moduleId of this.moduleIds) { /* ... */ }

or converted into an Array via Array.from(this.moduleIds).

this.parse(code: string, acornOptions: AcornOptions) => ESTree.Program

Use Rollup's internal acorn instance to parse code to an AST.

this.resolve(source: string, importer: string, options?: {skipSelf: boolean}) => Promise<{id: string, external: boolean} | null>

Resolve imports to module ids (i.e. file names) using the same plugins that Rollup uses, and determine if an import should be external. If null is returned, the import could not be resolved by Rollup or any plugin but was not explicitly marked as external by the user.

If you pass skipSelf: true, then the resolveId hook of the plugin from which this.resolve is called will be skipped when resolving.

this.setAssetSource(assetReferenceId: string, source: string | Buffer) => void

Set the deferred source of an asset.

this.warn(warning: string | RollupWarning, position?: number )

Using this method will queue warnings for a build. These warnings will be printed by the CLI just like internally-generated warnings (except with the plugin name), or captured by custom onwarn handlers.

The warning argument can be a string or an object with (at minimum) a message property:

this.warn( 'hmm...' );
// is equivalent to
this.warn({ message: 'hmm...' });

Use the second form if you need to add additional properties to your warning object. Rollup will augment the warning object with a plugin property containing the plugin name, code (PLUGIN_WARNING) and id (the file being transformed) properties.

The position argument is a character index where the warning was raised. If present, Rollup will augment the warning object with pos, loc (a standard { file, line, column } object) and frame (a snippet of code showing the error).

Deprecated Context Functions

☢️ These context utility functions have been deprecated and may be removed in a future Rollup version.

  • this.isExternal(id: string, importer: string, isResolved: boolean): boolean - Use this.resolve - Determine if a given module ID is external when imported by importer. When isResolved is false, Rollup will try to resolve the id before testing if it is external.

  • this.resolveId(source: string, importer: string) => Promise<string | null> - Use this.resolve - Resolve imports to module ids (i.e. file names) using the same plugins that Rollup uses. Returns null if an id cannot be resolved.

Asset URLs

To reference an asset URL reference from within JS code, use the import.meta.ROLLUP_ASSET_URL_assetReferenceId replacement. This will generate code that depends on the output format and generates a URL that points to the emitted file in the target environment. Note that all formats except CommonJS and UMD assume that they run in a browser environment where URL and document are available.

The following example will detect imports of .svg files, emit the imported files as assets, and return their URLs to be used e.g. as the src attribute of an img tag:

// plugin
export default function svgResolverPlugin () {
  return ({
    resolveId(source, importer) {
      if (source.endsWith('.svg')) {
        return path.resolve(path.dirname(importer), source);
      }
    },
    load(id) {
      if (id.endsWith('.svg')) {
      	const assetReferenceId = this.emitAsset(
          path.basename(id),
          fs.readFileSync(id)
        );
        return `export default import.meta.ROLLUP_ASSET_URL_${assetReferenceId};`;
      }
    }
  });
}

// usage
import logo from '../images/logo.svg';
const image = document.createElement('img');
image.src = logo;
document.body.appendChild(image);

Chunk URLs

Similar to assets, emitted chunks can be referenced from within JS code via the import.meta.ROLLUP_CHUNK_URL_chunkReferenceId replacement.

The following example will detect imports prefixed with register-paint-worklet: and generate the necessary code and separate chunk to generate a CSS paint worklet. Note that this will only work in modern browsers and will only work if the output format is set to esm.

// plugin
const REGISTER_WORKLET = 'register-paint-worklet:';
export default function paintWorkletPlugin () {
  return ({
    load(id) {
      if (id.startsWith(REGISTER_WORKLET)) {
        return `CSS.paintWorklet.addModule(import.meta.ROLLUP_CHUNK_URL_${this.emitChunk(
          id.slice(REGISTER_WORKLET.length)
        )});`;
      }
    },
    resolveId(source, importer) {
      // We remove the prefix, resolve everything to absolute ids and add the prefix again
      // This makes sure that you can use relative imports to define worklets
      if (source.startsWith(REGISTER_WORKLET)) {
        return this.resolveId(source.slice(REGISTER_WORKLET.length), importer).then(
          id => REGISTER_WORKLET + id
        );
      }
      return null;
    }
  });
}

Usage:

// main.js
import 'register-paint-worklet:./worklet.js';
import { color, size } from './config.js';
document.body.innerHTML += `<h1 style="background-image: paint(vertical-lines);">color: ${color}, size: ${size}</h1>`;

// worklet.js
import { color, size } from './config.js';
registerPaint(
  'vertical-lines',
  class {
    paint(ctx, geom) {
      for (let x = 0; x < geom.width / size; x++) {
        ctx.beginPath();
        ctx.fillStyle = color;
        ctx.rect(x * size, 0, 2, geom.height);
        ctx.fill();
      }
    }
  }
);

// config.js
export const color = 'greenyellow';
export const size = 6;

If you build this code, both the main chunk and the worklet will share the code from config.js via a shared chunk. This enables us to make use of the browser cache to reduce transmitted data and speed up loading the worklet.

Transformers

Transformer plugins (i.e. those that return a transform function for e.g. transpiling non-JS files) should support options.include and options.exclude, both of which can be a minimatch pattern or an array of minimatch patterns. If options.include is omitted or of zero length, files should be included by default; otherwise they should only be included if the ID matches one of the patterns.

The transform hook, if returning an object, can also include an ast property. Only use this feature if you know what you're doing. Note that only the last AST in a chain of transforms will be used (and if there are transforms, any ASTs generated by the load hook will be discarded for the transformed modules.)

Example Transformer

(Use rollup-pluginutils for commonly needed functions, and to implement a transformer in the recommended manner.)

import { createFilter } from 'rollup-pluginutils';

export default function myPlugin ( options = {} ) {
  const filter = createFilter( options.include, options.exclude );

  return {
    transform ( code, id ) {
      if ( !filter( id ) ) return;

      // proceed with the transformation...
      return {
        code: generatedCode,
        map: generatedSourceMap
      };
    }
  };
}

Source Code Transformations

If a plugin transforms source code, it should generate a sourcemap automatically, unless there's a specific sourceMap: false option. Rollup only cares about the mappings property (everything else is handled automatically). If it doesn't make sense to generate a sourcemap, (e.g. rollup-plugin-string), return an empty sourcemap:

return {
  code: transformedCode,
  map: { mappings: '' }
};

If the transformation does not move code, you can preserve existing sourcemaps by returning null:

return {
  code: transformedCode,
  map: null
};

If you create a plugin that you think would be useful to others, please publish it to NPM and add submit it to https://github.com/rollup/awesome!

Frequently Asked Questions

Why are ES modules better than CommonJS Modules?

ES modules are an official standard and the clear path forward for JavaScript code structure, whereas CommonJS modules are an idiosyncratic legacy format that served as a stopgap solution before ES modules had been proposed. ES modules allow static analysis that helps with optimizations like tree-shaking, and provide advanced features like circular references and live bindings.

What Is "tree-shaking?"

Tree-shaking, also known as "live code inclusion," is the process of eliminating code that is not actually used in a given project. It is similar to dead code elimination but can be much more efficient.

How do I use Rollup in Node.js with CommonJS modules?

Rollup strives to implement the specification for ES modules, not necessarily the behaviors of Node.js, NPM, require(), and CommonJS. Consequently, loading of CommonJS modules and use of Node's module location resolution logic are both implemented as optional plugins, not included by default in the Rollup core. Just npm install the commonjs and node-resolve plugins and then enable them using a rollup.config.js file and you should be all set. If the modules import JSON files, you will also need the json plugin.

Why isn't node-resolve a built-in feature?

There are two primary reasons:

  1. Philosophically, it's because Rollup is essentially a polyfill of sorts for native module loaders in both Node and browsers. In a browser, import foo from 'foo' won't work, because browsers don't use Node's resolution algorithm.

  2. On a practical level, it's just much easier to develop software if these concerns are neatly separated with a good API. Rollup's core is quite large, and everything that stops it getting larger is a good thing. Meanwhile, it's easier to fix bugs and add features. By keeping Rollup lean, the potential for technical debt is small.

Please see this issue for a more verbose explanation.

Is Rollup meant for building libraries or applications?

Rollup is already used by many major JavaScript libraries, and can also be used to build the vast majority of applications. However if you want to use code-splitting or dynamic imports with older browsers, you will need an additional runtime to handle loading missing chunks. We recommend using the SystemJS Production Build as it integrates nicely with Rollup's system format output and is capable of properly handling all the ES module live bindings and re-export edge cases. Alternatively, an AMD loader can be used as well.

Who made the Rollup logo? It's lovely.

Julian Lloyd!

Integrating Rollup With Other Tools

With NPM Packages

At some point, it's very likely that your project will depend on packages installed from NPM into your node_modules folder. Unlike other bundlers such as Webpack and Browserify, Rollup doesn't know "out of the box" how to handle these dependencies - we need to add some configuration.

Let's add a simple dependency called the-answer, which exports the answer to the question of life, the universe and everything:

npm install the-answer
# or `npm i the-answer`

If we update our src/main.js file...

// src/main.js
import answer from 'the-answer';

export default function () {
  console.log('the answer is ' + answer);
}

...and run Rollup...

npm run build

...we'll see a warning like this:

(!) Unresolved dependencies
https://github.com/rollup/rollup/wiki/Troubleshooting#treating-module-as-external-dependency
the-answer (imported by main.js)

The resulting bundle.js will still work in Node.js, because the import declaration gets turned into a CommonJS require statement, but the-answer does not get included in the bundle. For that, we need a plugin.

rollup-plugin-node-resolve

The rollup-plugin-node-resolve plugin teaches Rollup how to find external modules. Install it...

npm install --save-dev rollup-plugin-node-resolve

...and add it to your config file:

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

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

This time, when you npm run build, no warning is emitted — the bundle contains the imported module.

rollup-plugin-commonjs

Some libraries expose ES modules that you can import as-is — the-answer is one such module. But at the moment, the majority of packages on NPM are exposed as CommonJS modules instead. Until that changes, we need to convert CommonJS to ES2015 before Rollup can process them.

The rollup-plugin-commonjs plugin does exactly that.

Note that rollup-plugin-commonjs should go before other plugins that transform your modules — this is to prevent other plugins from making changes that break the CommonJS detection.

Peer dependencies

Let's say that you're building a library that has a peer dependency, such as React or Lodash. If you set up externals as described above, your rollup will bundle all imports:

import answer from 'the-answer';
import _ from 'lodash';

You can finely tune which imports are bundled and which are treated as external. For this example, we'll treat lodash as external, but not the-answer.

Here is the config file:

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

export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  },
  plugins: [resolve({
    // pass custom options to the resolve plugin
    customResolveOptions: {
      moduleDirectory: 'node_modules'
    }
  })],
  // indicate which modules should be treated as external
  external: ['lodash']
};

Voila, lodash will now be treated as external, and not be bundled with your library.

The external key accepts either an array of module names, or a function which takes the module name and returns true if it should be treated as external. For example:

export default {
  // ...
  external: id => /lodash/.test(id)
}

You might use this form if you're using babel-plugin-lodash to cherry-pick lodash modules. In this case, Babel will convert your import statements to look like this:

import _merge from 'lodash/merge';

The array form of external does not handle wildcards, so this import will only be treated as external in the functional form.

Babel

Many developers use Babel in their projects in order to use the latest JavaScript features that aren't yet supported by browsers and Node.js.

The easiest way to use both Babel and Rollup is with rollup-plugin-babel. First, install the plugin:

npm i -D rollup-plugin-babel rollup-plugin-node-resolve

Add it to rollup.config.js:

// rollup.config.js
import resolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';

export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  },
  plugins: [
    resolve(),
    babel({
      exclude: 'node_modules/**' // only transpile our source code
    })
  ]
};

Before Babel will actually compile your code, it needs to be configured. Create a new file, src/.babelrc:

{
  "presets": [
    ["@babel/env", {"modules": false}]
  ]
}

There are a few unusual elements to this setup. First, we're setting "modules": false, otherwise Babel will convert our modules to CommonJS before Rollup gets a chance to do its thing, causing it to fail.

Secondly, we're putting our .babelrc file in src, rather than the project root. This allows us to have a different .babelrc for things like tests, if we need that later – it's generally a good idea to have separate configuration for separate tasks.

Now, before we run rollup, we need to install babel-core and the env preset:

npm i -D @babel/core @babel/preset-env

Running Rollup now will create a bundle - except we're not actually using any ES2015 features. Let's change that by editing src/main.js:

// src/main.js
import answer from 'the-answer';

export default () => {
  console.log(`the answer is ${answer}`);
}

Run Rollup with npm run build, and check the bundle:

'use strict';

var index = 42;

var main = (function () {
  console.log('the answer is ' + index);
});

module.exports = main;

Gulp

Rollup returns Promises which are understood by gulp so integration is relatively painless.

The syntax is very similar to the configuration file, but the properties are split across two different operations corresponding to the JavaScript API:

const gulp = require('gulp');
const rollup = require('rollup');
const rollupTypescript = require('rollup-plugin-typescript');

gulp.task('build', () => {
  return rollup.rollup({
    input: './src/main.ts',
    plugins: [
      rollupTypescript()
    ]
  }).then(bundle => {
    return bundle.write({
      file: './dist/library.js',
      format: 'umd',
      name: 'library',
      sourcemap: true
    });
  });
});

You may also use the async/await syntax:

const gulp = require('gulp');
const rollup = require('rollup');
const rollupTypescript = require('rollup-plugin-typescript');

gulp.task('build', async function () {
  const bundle = await rollup.rollup({
    input: './src/main.ts',
    plugins: [
      rollupTypescript()
    ]
  });

  await bundle.write({
    file: './dist/library.js',
    format: 'umd',
    name: 'library',
    sourcemap: true
  });
});

Troubleshooting

If you get stuck, please try discussing the issue on the Rollup Gitter or posting a question to https://stackoverflow.com/questions/tagged/rollupjs. If you've found a bug, or Rollup can't meet your needs, please try raising an issue. Lastly, you may try contacting @RollupJS on Twitter.

Avoiding eval

You probably already know that 'eval is evil', at least according to some people. But it's particularly harmful with Rollup, because of how it works – unlike other module bundlers, which wrap each module in a function, Rollup puts all your code in the same scope.

That's more efficient, but it means that the shared scope is 'polluted' whenever you use eval, whereas with a different bundler, modules that didn't use eval would not be polluted. A minifier can't mangle variable names in polluted code, because it can't guarantee that the code to be evaluated doesn't reference those variable names.

Furthermore, it poses a security risk in that a malicious module could access another module's private variables with eval('SUPER_SEKRIT').

Luckily, unless you really do intend for the evaluated code to have access to local variables (in which case you're probably doing something wrong!), you can achieve the same effect in one of two ways:

eval2 = eval

Simply 'copying' eval provides you with a function that does exactly the same thing, but which runs in the global scope rather than the local one:

var eval2 = eval;

(function () {
  var foo = 42;
  eval('console.log("with eval:",foo)');  // logs 'with eval: 42'
  eval2('console.log("with eval2:",foo)'); // throws ReferenceError
})();

new Function

Using the Function constructor generates a function from the supplied string. Again, it runs in the global scope. If you need to call the function repeatedly, this is much, much faster than using eval.

Tree-shaking Doesn't Seem to be Working

Sometimes, you'll end up with code in your bundle that doesn't seem like it should be there. For example, if you import a utility from lodash-es, you might expect that you'll get the bare minimum of code necessary for that utility to work.

But Rollup has to be conservative about what code it removes in order to guarantee that the end result will run correctly. If an imported module appears to have side-effects, either on bits of the module that you're using or on the global environment, Rollup plays it safe and includes those side-effects.

Because static analysis in a dynamic language like JavaScript is hard, there will occasionally be false positives. Lodash is a good example of a module that looks like it has lots of side-effects, even in places that it doesn't. You can often mitigate those false positives by importing submodules (e.g. import map from 'lodash-es/map' rather than import { map } from 'lodash-es').

Rollup's static analysis will improve over time, but it will never be perfect in all cases – that's just JavaScript.

Error: "[name] is not exported by [module]"

Occasionally you will see an error message like this:

'foo' is not exported by bar.js (imported by baz.js)

Import declarations must have corresponding export declarations in the imported module. For example, if you have import a from './a.js' in a module, and a.js doesn't have an export default declaration, or import {foo} from './b.js', and b.js doesn't export foo, Rollup cannot bundle the code.

This error frequently occurs with CommonJS modules converted by rollup-plugin-commonjs, which makes a reasonable attempt to generate named exports from the CommonJS code but won't always succeed, because the freewheeling nature of CommonJS is at odds with the rigorous approach we benefit from in JavaScript modules. It can be solved by using the namedExports option, which allows you to manually fill in the information gaps.

Error: "this is undefined"

In a JavaScript module, this is undefined at the top level (i.e., outside functions). Because of that, Rollup will rewrite any this references to undefined so that the resulting behaviour matches what will happen when modules are natively supported.

There are occasional valid reasons for this to mean something else. If you're getting errors in your bundle, you can use options.context and options.moduleContext to change this behaviour.

Warning: "Sourcemap is likely to be incorrect"

You'll see this warning if you generate a sourcemap with your bundle (sourceMap: true or sourceMap: 'inline') but you're using one or more plugins that transformed code without generating a sourcemap for the transformation.

Usually, a plugin will only omit the sourcemap if it (the plugin, not the bundle) was configured with sourceMap: false – so all you need to do is change that. If the plugin doesn't generate a sourcemap, consider raising an issue with the plugin author.

Warning: "Treating [module] as external dependency"

Rollup will only resolve relative module IDs by default. This means that an import statement like this...

import moment from 'moment';

...won't result in moment being included in your bundle – instead, it will be an external dependency that is required at runtime. If that's what you want, you can suppress this warning with the external option, which makes your intentions explicit:

// rollup.config.js
export default {
  entry: 'src/index.js',
  dest: 'bundle.js',
  format: 'cjs',
  external: [ 'moment' ] // <-- suppresses the warning
};

If you do want to include the module in your bundle, you need to tell Rollup how to find it. In most cases, this is a question of using rollup-plugin-node-resolve.

Some modules, like events or util, are built in to Node.js. If you want to include those (for example, so that your bundle runs in the browser), you may need to include rollup-plugin-node-builtins.

Big list of options

Core functionality

external

Type: string[] | (id: string, parentId: string, isResolved: boolean) => boolean
CLI: -e/--external <external-id,another-external-id,...>

Either a function that takes an id and returns true (external) or false (not external), or an Array of module IDs that should remain external to the bundle. The IDs should be either:

  1. the name of an external dependency, exactly the way it is written in the import statement. I.e. to mark import "dependency.js" as external, use "dependency.js" while to mark import "dependency" as external, use "dependency".
  2. a resolved ID (like an absolute path to a file).
// rollup.config.js
import path from 'path';

export default {
  ...,
  external: [
    'some-externally-required-library',
    path.resolve( __dirname, 'src/some-local-file-that-should-not-be-bundled.js' )
  ]
};

When given as a command line argument, it should be a comma-separated list of IDs:

rollup -i src/main.js ... -e foo,bar,baz

When providing a function, it is actually called with three parameters (id, parent, isResolved) that can give you more fine-grained control:

  • id is the id of the module in question
  • parent is the id of the module doing the import
  • isResolved signals whether the id has been resolved by e.g. plugins

When creating an iife or umd bundle, you will need to provide global variable names to replace your external imports via the output.globals option.

input

Type: string | string [] | { [entryName: string]: string }
CLI: -i/--input <filename>

The bundle's entry point(s) (e.g. your main.js or app.js or index.js). If you provide an array of entry points or an object mapping names to entry points, they will be bundled to separate output chunks. Unless the output.file option is used, generated chunk names will follow the output.entryFileNames option. When using the object form, the [name] portion of the file name will be the name of the object property while for the array form, it will be the file name of the entry point.

This will generate at least two entry chunks with the names entry-a.js and entry-b.js:

// rollup.config.js
export default {
  ...,
  input: {
    a: 'src/main-a.js',
    b: 'src/main-b.js'
  },
  output: {
    ...,
    entryFileNames: 'entry-[name].js'
  }
};

When using the command line interface, multiple inputs can be provided by using the option multiple times. When provided as the first options, it is equivalent to not prefix them with --input:

rollup --format esm --input src/entry1.js --input src/entry2.js
# is equivalent to
rollup src/entry1.js src/entry2.js --format esm

Chunks can be named by adding an = to the provided value:

rollup main=src/entry1.js other=src/entry2.js --format esm

File names containing spaces can be specified by using quotes:

rollup "main entry"="src/entry 1.js" "src/other entry.js" --format esm

output.dir

Type: string
CLI: -d/--dir <dirname>

The directory in which all generated chunks are placed. This option is required if more than one chunk is generated. Otherwise, the file option can be used instead.

output.file

Type: string
CLI: -o/--file <filename>

The file to write to. Will also be used to generate sourcemaps, if applicable. Can only be used if not more than one chunk is generated.

output.format

Type: string
CLI: -f/--format <formatspecifier>

Specifies the format of the generated bundle. One of the following:

  • amd – Asynchronous Module Definition, used with module loaders like RequireJS
  • cjs – CommonJS, suitable for Node and other bundlers
  • esm – Keep the bundle as an ES module file, suitable for other bundlers and inclusion as a <script type=module> tag in modern browsers
  • iife – A self-executing function, suitable for inclusion as a <script> tag. (If you want to create a bundle for your application, you probably want to use this.)
  • umd – Universal Module Definition, works as amd, cjs and iife all in one
  • system – Native format of the SystemJS loader

output.globals

Type: { [id: string]: string } | ((id: string) => string)
CLI: -g/--globals <external-id:variableName,another-external-id:anotherVariableName,...>

Specifies id: variableName pairs necessary for external imports in umd/iife bundles. For example, in a case like this...

import $ from 'jquery';

...we want to tell Rollup that jquery is external and the jquery module ID equates to the global $ variable:

// rollup.config.js
export default {
  ...,
  external: ['jquery'],
  output: {
    format: 'iife',
    name: 'MyBundle',
    globals: {
      jquery: '$'
    }
  }
};

/*
var MyBundle = (function ($) {
  // code goes here
}($));
*/

Alternatively, supply a function that will turn an external module ID into a global variable name.

When given as a command line argument, it should be a comma-separated list of id:variableName pairs:

rollup -i src/main.js ... -g jquery:$,underscore:_

To tell Rollup that a local file should be replaced by a global variable, use an absolute id:

// rollup.config.js
import path from 'path';
const externalId = path.resolve( __dirname, 'src/some-local-file-that-should-not-be-bundled.js' );

export default {
  ...,
  external: [externalId],
  output: {
    format: 'iife',
    name: 'MyBundle',
    globals: {
      [externalId]: 'globalVariable'
    }
  }
};

output.name

Type: string
CLI: -n/--name <variableName>

Necessary for iife/umd bundles that exports values in which case it is the global variable name representing your bundle. Other scripts on the same page can use this variable name to access the exports of your bundle.

// rollup.config.js
export default {
  ...,
  output: {
    file: 'bundle.js',
    format: 'iife',
    name: 'MyBundle'
  }
};

// var MyBundle = (function () {...

Namespaces are supported i.e. your name can contain dots. The resulting bundle will contain the setup necessary for the namespacing.

$ rollup -n "a.b.c"

/* ->
this.a = this.a || {};
this.a.b = this.a.b || {};
this.a.b.c = ...
*/

plugins

Type: Plugin | (Plugin | void)[]

See Using plugins for more information on how to use plugins and Plugins on how to write your own (try it out, it's not as difficult as it may sound and very much extends what you can do with Rollup!). For plugins imported from packages, remember to call the imported plugin function (i.e. commonjs(), not just commonjs). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins.

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

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

export default (async () => ({
  entry: 'main.js',
  plugins: [
    resolve(),
    commonjs(),
    isProduction && (await import('rollup-plugin-terser')).terser()
  ]
}))();

(This example also demonstrates how to use an async IIFE and dynamic imports to avoid unnecessary module loading, which can be surprisingly slow.)

Advanced functionality

cache

Type: RollupCache | false

The cache property of a previous bundle. Use it to speed up subsequent builds in watch mode — Rollup will only reanalyse the modules that have changed. Setting this option explicitly to false will prevent generating the cache property on the bundle and also deactivate caching for plugins.

const rollup = require('rollup');
let cache;

async function buildWithCache() {
  const bundle = await rollup.rollup({
    cache, // is ignored if falsy
    // ... other input options
  });
  cache = bundle.cache; // store the cache object of the previous build
  return bundle;
}

buildWithCache()
  .then(bundle => {
    // ... do something with the bundle
  })
  .then(() => buildWithCache()) // will use the cache of the previous build
  .then(bundle => {
    // ... do something with the bundle
  })

inlineDynamicImports

Type: boolean
CLI: --inlineDynamicImports/--no-inlineDynamicImports Default: false

This will inline dynamic imports instead of creating new chunks to create a single bundle. Only possible if a single input is provided.

manualChunks

Type: { [chunkAlias: string]: string[] } | ((id: string) => string | void)

Allows the creation of custom shared common chunks. When using the object form, each property represents a chunk that contains the listed modules and all their dependencies if they are part of the module graph unless they are already in another manual chunk. The name of the chunk will be determined by the property key.

Note that it is not necessary for the listed modules themselves to be be part of the module graph, which is useful if you are working with rollup-plugin-node-resolve and use deep imports from packages. For instance

manualChunks: {
  lodash: ['lodash']
}

will put all lodash modules into a manual chunk even if you are only using imports of the form import get from 'lodash/get'.

When using the function form, each resolved module id will be passed to the function. If a string is returned, the module and all its dependency will be added to the manual chunk with the given name. For instance this will create a vendor chunk containing all dependencies inside node_modules:

manualChunks(id) {
  if (id.includes('node_modules')) {
    return 'vendor';
  }
}

Be aware that manual chunks can change the behaviour of the application if side-effects are triggered before the corresponding modules are actually used.

onwarn

Type: (warning: RollupWarning, defaultHandler: (warning: string | RollupWarning) => void) => void;

A function that will intercept warning messages. If not supplied, warnings will be deduplicated and printed to the console.

The function receives two arguments: the warning object and the default handler. Warnings objects have, at a minimum, a code and a message property, allowing you to control how different kinds of warnings are handled. Other properties are added depending on the type of warning.

// rollup.config.js
export default {
  ...,
  onwarn (warning, warn) {
    // skip certain warnings
    if (warning.code === 'UNUSED_EXTERNAL_IMPORT') return;
  
    // throw on others
    if (warning.code === 'NON_EXISTENT_EXPORT') throw new Error(warning.message);
  
    // Use default for everything else
    warn(warning);
  }
};

Many warnings also have a loc property and a frame allowing you to locate the source of the warning:

// rollup.config.js
export default {
  ...,
  onwarn ({ loc, frame, message }) {
    if (loc) {
      console.warn(`${loc.file} (${loc.line}:${loc.column}) ${message}`);
      if (frame) console.warn(frame);
    } else {
      console.warn(message);
    }
  }
};

output.assetFileNames

Type: string
CLI: --assetFileNames <pattern>
Default: "assets/[name]-[hash][extname]"

The pattern to use for naming custom emitted assets to include in the build output. Pattern supports the following placeholders:

  • [extname]: The file extension of the asset including a leading dot, e.g. .css.
  • [ext]: The file extension without a leading dot, e.g. css.
  • [hash]: A hash based on the name and content of the asset.
  • [name]: The file name of the asset excluding any extension.

Forward slashes / can be used to place files in sub-directories. See also [output.chunkFileNames](guide/en#output-chunkfilenames), output.entryFileNames.

Type: string | (() => string | Promise<string>)
CLI: --banner/--footer <text>

A string to prepend/append to the bundle. You can also supply a function that returns a Promise that resolves to a string to generate it asynchronously (Note: banner and footer options will not break sourcemaps).

// rollup.config.js
export default {
  ...,
  output: {
    ...,
    banner: '/* my-library version ' + version + ' */',
    footer: '/* follow me on Twitter! @rich_harris */'
  }
};

See also output.intro/output.outro.

output.chunkFileNames

Type: string
CLI: --chunkFileNames <pattern>
Default: "[name]-[hash].js"

The pattern to use for naming shared chunks created when code-splitting. Pattern supports the following placeholders:

  • [format]: The rendering format defined in the output options, e.g. esm or cjs.
  • [hash]: A hash based on the content of the chunk and the content of all its dependencies.
  • [name]: The name of the chunk. This will be chunk unless the chunk was created via the manualChunks options.

Forward slashes / can be used to place files in sub-directories. See also output.assetFileNames, output.entryFileNames.

output.compact

Type: boolean
CLI: --compact/--no-compact Default: false

This will minify the wrapper code generated by rollup. Note that this does not affect code written by the user. This option is useful when bundling pre-minified code.

output.entryFileNames

Type: string
CLI: --entryFileNames <pattern>
Default: "[name].js"

The pattern to use for chunks created from entry points. Pattern supports the following placeholders:

  • [format]: The rendering format defined in the output options, e.g. esm or cjs.
  • [hash]: A hash based on the content of the entry point and the content of all its dependencies.
  • [name]: The file name (without extension) of the entry point.

Forward slashes / can be used to place files in sub-directories. See also output.assetFileNames, output.chunkFileNames.

output.extend

Type: boolean
CLI: --extend/--no-extend
Default: false

Whether or not to extend the global variable defined by the name option in umd or iife formats. When true, the global variable will be defined as (global.name = global.name || {}). When false, the global defined by name will be overwritten like (global.name = {}).

output.interop

Type: boolean
CLI: --interop/--no-interop
Default: true

Whether or not to add an 'interop block'. By default (interop: true), for safety's sake, Rollup will assign any external dependencies' default exports to a separate variable if it is necessary to distinguish between default and named exports. This generally only applies if your external dependencies were transpiled (for example with Babel) – if you are sure you do not need it, you can save a few bytes with interop: false.

output.intro/output.outro

Type: string | (() => string | Promise<string>)
CLI: --intro/--outro <text>

Similar to output.banner/output.footer, except that the code goes inside any format-specific wrapper.

export default {
  ...,
  output: {
    ...,
    intro: 'const ENVIRONMENT = "production";'
  }
};

output.paths

Type: { [id: string]: string } | ((id: string) => string)

Maps ids to paths. Where supplied, these paths will be used in the generated bundle instead of the module ID, allowing you to, for example, load dependencies from a CDN:

// app.js
import { selectAll } from 'd3';
selectAll('p').style('color', 'purple');
// ...

// rollup.config.js
export default {
  input: 'app.js',
  external: ['d3'],
  output: {
    file: 'bundle.js',
    format: 'amd',
    paths: {
      d3: 'https://d3js.org/d3.v4.min'
    }
  }
};

// bundle.js
define(['https://d3js.org/d3.v4.min'], function (d3) {

  d3.selectAll('p').style('color', 'purple');
  // ...

});

output.sourcemap

Type: boolean | 'inline'
CLI: -m/--sourcemap/--no-sourcemap
Default: false

If true, a separate sourcemap file will be created. If inline, the sourcemap will be appended to the resulting output file as a data URI.

output.sourcemapExcludeSources

Type: boolean
CLI: --sourcemapExcludeSources/--no-sourcemapExcludeSources
Default: false

If true, the actual code of the sources will not be added to the sourcemaps making them considerably smaller.

output.sourcemapFile

Type: string
CLI: --sourcemapFile <file-name-with-path>

The location of the generated bundle. If this is an absolute path, all the sources paths in the sourcemap will be relative to it. The map.file property is the basename of sourcemapFile, as the location of the sourcemap is assumed to be adjacent to the bundle.

sourcemapFile is not required if output is specified, in which case an output filename will be inferred by adding ".map" to the output filename for the bundle.

output.sourcemapPathTransform

Type: (sourcePath: string) => string

A transformation to apply to each path in a sourcemap. For instance the following will change all paths to be relative to the src directory.

import path from 'path';
export default ({
  input: 'src/main',
  output: [{
    file: 'bundle.js',
    sourcemapPathTransform: relativePath => {
      // will transform e.g. "src/main.js" -> "main.js"
      return path.relative('src', relativePath)
    },
    format: 'esm',
    sourcemap: true
  }]
});

preserveModules

Type: boolean
CLI: --preserveModules/--no-preserveModules
Default: false

Instead of creating as few chunks as possible, this mode will create separate chunks for all modules using the original module names as file names. Requires the output.dir option. Tree-shaking will still be applied, suppressing files that are not used by the provided entry points or do not have side-effects when executed. This mode can be used to transform a file structure to a different module format.

Danger zone

You probably don't need to use these options unless you know what you are doing!

acorn

Type: AcornOptions

Any options that should be passed through to Acorn's parse function, such as allowReserved: true. Cf. the Acorn documentation for more available options.

acornInjectPlugins

Type: AcornPluginFunction | AcornPluginFunction[]

A single plugin or an array of plugins to be injected into Acorn. For instance to use JSX syntax, you can specify

import jsx from 'acorn-jsx';

export default {
    // … other options …
    acornInjectPlugins: [
        jsx()
    ]
};

in your rollup configuration. Note that this is different from using Babel in that the generated output will still contain JSX while Babel will replace it with valid JavaScript.

context

Type: string
CLI: --context <contextVariable>
Default: undefined

By default, the context of a module – i.e., the value of this at the top level – is undefined. In rare cases you might need to change this to something else, like 'window'.

moduleContext

Type: ((id: string) => string) | { [id: string]: string }

Same as context, but per-module – can either be an object of id: context pairs, or an id => context function.

output.amd

Type: { id?: string, define?: string}

An object that can contain the following properties:

output.amd.id
Type: string
CLI: --amd.id <amdId>

An ID to use for AMD/UMD bundles:

// rollup.config.js
export default {
  ...,
  format: 'amd',
  amd: {
    id: 'my-bundle'
  }
};

// -> define('my-bundle', ['dependency'], ...

output.amd.define
Type: string
CLI: --amd.define <defineFunctionName>

A function name to use instead of define:

// rollup.config.js
export default {
  ...,
  format: 'amd',
  amd: {
    define: 'def'
  }
};

// -> def(['dependency'],...

output.esModule

Type: boolean
CLI: --esModule/--no-esModule Default: true

Whether or not to add a __esModule: true property when generating exports for non-ESM formats.

output.exports

Type: string
CLI: --exports <exportMode>
Default: 'auto'

What export mode to use. Defaults to auto, which guesses your intentions based on what the input module exports:

  • default – suitable if you are only exporting one thing using export default ...
  • named – suitable if you are exporting more than one thing
  • none – suitable if you are not exporting anything (e.g. you are building an app, not a library)

The difference between default and named affects how other people can consume your bundle. If you use default, a CommonJS user could do this, for example:

const yourLib = require( 'your-lib' );

With named, a user would do this instead:

const yourMethod = require( 'your-lib' ).yourMethod;

The wrinkle is that if you use named exports but also have a default export, a user would have to do something like this to use the default export:

const yourMethod = require( 'your-lib' ).yourMethod;
const yourLib = require( 'your-lib' ).default;

output.freeze

Type: boolean
CLI: --freeze/--no-freeze
Default: true

Whether to Object.freeze() namespace import objects (i.e. import * as namespaceImportObject from...) that are accessed dynamically.

output.indent

Type: boolean | string
CLI: --indent/--no-indent
Default: true

The indent string to use, for formats that require code to be indented (amd, iife, umd, system). Can also be false (no indent), or true (the default – auto-indent)

// rollup.config.js
export default {
  ...,
  output: {
    ...,
    indent: false
  }
};

output.namespaceToStringTag

Type: boolean
CLI: --namespaceToStringTag/--no-namespaceToStringTag
Default: false

Whether to add spec compliant .toString() tags to namespace objects. If this option is set,

import * as namespace from './file.js';
console.log(String(namespace));

will always log [object Module];

output.noConflict

Type: boolean
CLI: --noConflict/--no-noConflict
Default: false

This will generate an additional noConflict export to UMD bundles. When called in an IIFE scenario, this method will return the bundle exports while restoring the corresponding global variable to its previous value.

output.preferConst

Type: boolean
CLI: --preferConst/--no-preferConst
Default: false

Generate const declarations for exports rather than var declarations.

output.strict

Type: boolean
CLI: --strict/--no-strict
Default: true

Whether to include the 'use strict' pragma at the top of generated non-ESM bundles. Strictly-speaking, ES modules are always in strict mode, so you shouldn't disable this without good reason.

output.dynamicImportFunction

Type: string
CLI: --dynamicImportFunction <name>
Default: import

This will rename the dynamic import function to the chosen name when outputting ESM bundles. This is useful for generating code that uses a dynamic import polyfill such as this one.

Type: boolean
CLI: --preserveSymlinks
Default: false

When set to false, symbolic links are followed when resolving a file. When set to true, instead of being followed, symbolic links are treated as if the file is where the link is. To illustrate, consider the following situation:

// /main.js
import {x} from './linked.js';
console.log(x);

// /linked.js
// this is a symbolic link to /nested/file.js

// /nested/file.js
export {x} from './dep.js';

// /dep.js
export const x = 'next to linked';

// /nested/dep.js
export const x = 'next to original';

If preserveSymlinks is false, then the bundle created from /main.js will log "next to original" as it will use the location of the symbolically linked file to resolve its dependencies. If preserveSymlinks is true, however, it will log "next to linked" as the symbolic link will not be resolved.

shimMissingExports

Type: boolean
CLI: --shimMissingExports/--no-shimMissingExports
Default: false

If this option is provided, bundling will not fail if bindings are imported from a file that does not define these bindings. Instead, new variables will be created for these bindings with the value undefined.

treeshake

Type: boolean | { annotations?: boolean, moduleSideEffects?: ModuleSideEffectsOption, propertyReadSideEffects?: boolean }
CLI: --treeshake/--no-treeshake
Default: true

Whether or not to apply tree-shaking and to fine-tune the tree-shaking process. Setting this option to false will produce bigger bundles but may improve build performance. If you discover a bug caused by the tree-shaking algorithm, please file an issue! Setting this option to an object implies tree-shaking is enabled and grants the following additional options:

treeshake.annotations
Type: boolean
CLI: --treeshake.annotations/--no-treeshake.annotations
Default: true

If false, ignore hints from pure annotations, i.e. comments containing @__PURE__ or #__PURE__, when determining side-effects of function calls and constructor invocations. These annotations need to immediately precede the call invocation to take effect. The following code will be completely removed unless this option is set to false, in which case it will remain unchanged.

/*@__PURE__*/console.log('side-effect');

class Impure {
  constructor() {
    console.log('side-effect')
  }
}

/*@__PURE__*/new Impure();

treeshake.moduleSideEffects
Type: boolean | "no-external" | string[] | (id: string, external: boolean) => boolean
CLI: --treeshake.moduleSideEffects/--no-treeshake.moduleSideEffects
Default: true

If false, assume modules and external dependencies from which nothing is imported do not have other side-effects like mutating global variables or logging without checking. For external dependencies, this will suppress empty imports:

// input file
import {unused} from 'external-a';
import 'external-b';
console.log(42);
// output with treeshake.moduleSideEffects === true
import 'external-a';
import 'external-b';
console.log(42);
// output with treeshake.moduleSideEffects === false
console.log(42);

For non-external modules, false will not include any statements from a module unless at least one import from this module is included:

// input file a.js
import {unused} from './b.js';
console.log(42);

// input file b.js
console.log('side-effect');
// output with treeshake.moduleSideEffects === true
console.log('side-effect');

console.log(42);
// output with treeshake.moduleSideEffects === false
console.log(42);

You can also supply a list of modules with side-effects or a function to determine it for each module individually. The value "no-external" will only remove external imports if possible and is equivalent to the function (id, external) => !external;

treeshake.propertyReadSideEffects Type: boolean
CLI: --treeshake.propertyReadSideEffects/--no-treeshake.propertyReadSideEffects
Default: true

If false, assume reading a property of an object never has side-effects. Depending on your code, disabling this option can significantly reduce bundle size but can potentially break functionality if you rely on getters or errors from illegal property access.

// Will be removed if treeshake.propertyReadSideEffects === false
const foo = {
  get bar() {
    console.log('effect');
    return 'bar';
  }
}
const result = foo.bar;
const illegalAccess = foo.quux.tooDeep;

Experimental options

These options reflect new features that have not yet been fully finalized. Availability, behaviour and usage may therefore be subject to change between minor versions.

chunkGroupingSize

Type: number
CLI: --chunkGroupingSize <size>
Default: 5000

The total source length allowed to be loaded unnecessarily when using experimentalOptimizeChunks.

experimentalCacheExpiry

Type: number
CLI: --experimentalCacheExpiry <numberOfRuns>
Default: 10

Determines after how many runs cached assets that are no longer used by plugins should be removed.

experimentalOptimizeChunks

Type: boolean
CLI: --experimentalOptimizeChunks/--no-experimentalOptimizeChunks
Default: false

Experimental feature to optimize chunk groupings. When a large number of chunks are generated, this allows smaller chunks to group together as long as they are within the chunkGroupingSize limit. It results in unnecessary code being loaded in some cases in order to have a smaller number of chunks overall. Disabled by default as it may cause unwanted side effects when loading unexpected code.

experimentalTopLevelAwait

Type: boolean
CLI: --experimentalTopLevelAwait/--no-experimentalTopLevelAwait
Default: false

Whether to support top-level await statements. The generated code will follow Variant A of the specification.

perf

Type: boolean
CLI: --perf/--no-perf
Default: false

Whether to collect performance timings. When used from the command line or a configuration file, detailed measurements about the current bundling process will be displayed. When used from the JavaScript API, the returned bundle object will contain an aditional getTimings() function that can be called at any time to retrieve all accumulated measurements.

getTimings() returns an object of the following form:

{
  "# BUILD": [ 698.020877, 33979632, 45328080 ],
  "## parse modules": [ 537.509342, 16295024, 27660296 ],
  "load modules": [ 33.253778999999994, 2277104, 38204152 ],
  ...
}

For each key, the first number represents the elapsed time while the second represents the change in memory consumption and the third represents the total memory consumption after this step. The order of these steps is the order used by Object.keys. Top level keys start with # and contain the timings of nested steps, i.e. in the example above, the 698ms of the # BUILD step include the 538ms of the ## parse modules step.

Watch options

These options only take effect when running Rollup with the --watch flag, or using rollup.watch.

watch.chokidar

Type: boolean | ChokidarOptions
CLI: --watch.chokidar/--no-watch.chokidar
Default: false

A Boolean indicating that chokidar should be used instead of the built-in fs.watch, or an Object of options that are passed through to chokidar.

You must install chokidar separately if you wish to use it.

watch.clearScreen

Type: boolean
CLI: --watch.clearScreen/--no-watch.clearScreen
Default: true

Whether to clear the screen when a rebuild is triggered.

watch.exclude

Type: string
CLI: --watch.exclude <excludedPattern>

Prevent files from being watched:

// rollup.config.js
export default {
  ...,
  watch: {
    exclude: 'node_modules/**'
  }
};

watch.include

Type: string
CLI: --watch.include <includedPattern>

Limit the file-watching to certain files:

// rollup.config.js
export default {
  ...,
  watch: {
    include: 'src/**'
  }
};

Deprecated options

☢️ These options have been deprecated and may be removed in a future Rollup version.

treeshake.pureExternalModules

Type: boolean | string[] | (id: string) => boolean | null
CLI: --treeshake.pureExternalModules/--no-treeshake.pureExternalModules
Default: false

If true, assume external dependencies from which nothing is imported do not have other side-effects like mutating global variables or logging.

// input file
import {unused} from 'external-a';
import 'external-b';
console.log(42);
// output with treeshake.pureExternalModules === false
import 'external-a';
import 'external-b';
console.log(42);
// output with treeshake.pureExternalModules === true
console.log(42);

You can also supply a list of external ids to be considered pure or a function that is called whenever an external import could be removed.