Rollup.js Guide
An interactive tutorial for the next-generation JavaScript module bundler.
1. Project Setup & Basic Configuration
This section walks you through the initial steps of creating a new project, installing Rollup, and creating your first bundle. We'll set up the basic file structure and configuration needed to get started.
Step 1: Initialize the Project
Create a directory and initialize a new Node.js project.
mkdir rollup-project
cd rollup-project
npm init -y
Step 2: Install Rollup
Install Rollup as a development dependency.
npm install --save-dev rollup
Step 3: Create Source Files
Create a `src` directory with these two files:
src/logger.js
// A simple utility function
export const logMessage = (message) => {
console.log(`[INFO] ${message}`);
};
src/main.js
import { logMessage } from './logger.js';
const heading = document.createElement('h1');
heading.textContent = 'Hello, Rollup!';
document.body.appendChild(heading);
logMessage('Application has started.');
Step 4: Create a Basic Rollup Configuration
Create a `rollup.config.js` file in the root of your project.
rollup.config.js
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'iife' // Immediately Invoked Function Expression
}
};
2. Using Plugins for Common Tasks
Rollup's core functionality is extended through a rich ecosystem of plugins. Here, we'll add some of the most common plugins to handle modules from `node_modules` and transpile modern JavaScript for broader compatibility.
Step 1: Install Plugins
Install plugins for resolving Node modules and transpiling with Babel.
npm install --save-dev @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-babel @babel/core @babel/preset-env
Step 2: Update Rollup Configuration
Import and add the plugins to your `rollup.config.js`. This is the complete file at this stage.
rollup.config.js
import { babel } from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: true,
},
plugins: [
resolve(),
commonjs(),
babel({ babelHelpers: 'bundled' })
]
};
3. Development vs. Production Configurations
Different environments require different build outputs. For development, we want fast rebuilds, a local server, and source maps. For production, we want a minified, optimized bundle. This section shows how to manage both from a single configuration file.
Step 1: Install Dev/Prod Plugins
Install plugins for serving content, live reloading, and minification.
npm install --save-dev rollup-plugin-serve rollup-plugin-livereload @rollup/plugin-terser
Step 2: Update `package.json` Scripts
Add `dev` and `build` scripts to your `package.json`.
package.json
{
...
"scripts": {
"build": "NODE_ENV=production rollup -c",
"dev": "rollup -c -w"
},
...
}
Step 3: Update Rollup Configuration
Use an environment variable to conditionally apply plugins. This is the complete file at this stage.
rollup.config.js
import { babel } from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import terser from '@rollup/plugin-terser';
const isProduction = process.env.NODE_ENV === 'production';
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: !isProduction,
},
plugins: [
resolve(),
commonjs(),
babel({ babelHelpers: 'bundled', exclude: 'node_modules/**' }),
!isProduction && serve({
contentBase: ['dist'],
port: 3000,
}),
!isProduction && livereload('dist'),
isProduction && terser()
]
};
4. Handling CSS and Images
Modern web development involves more than just JavaScript. Learn how to use Rollup plugins to import, process, and bundle assets like CSS files and images directly within your project.
Step 1: Install Asset Plugins
Install plugins for handling CSS and image files.
npm install --save-dev rollup-plugin-postcss @rollup/plugin-image
Step 2: Update Rollup Configuration
Add the asset plugins to your configuration. This is the complete file at this stage.
rollup.config.js
import { babel } from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import terser from '@rollup/plugin-terser';
import postcss from 'rollup-plugin-postcss';
import image from '@rollup/plugin-image';
const isProduction = process.env.NODE_ENV === 'production';
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: !isProduction,
},
plugins: [
resolve(),
commonjs(),
babel({ babelHelpers: 'bundled', exclude: 'node_modules/**' }),
image(),
postcss({
extract: 'bundle.css',
minimize: isProduction,
}),
!isProduction && serve({ contentBase: ['dist'], port: 3000 }),
!isProduction && livereload('dist'),
isProduction && terser(),
]
};
5. Using Rollup with TypeScript
Integrate the power of static typing into your Rollup workflow. This section covers setting up the TypeScript compiler and the official Rollup plugin to build type-safe applications.
Step 1: Install Dependencies
Install TypeScript and the Rollup TypeScript plugin.
npm install --save-dev typescript @rollup/plugin-typescript
Step 2: Configure TypeScript
Create a `tsconfig.json` file to configure the TypeScript compiler.
tsconfig.json
{
"compilerOptions": {
"target": "es2020",
"module": "esnext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"sourceMap": true
},
"include": ["src/**/*"]
}
Step 3: Update Rollup Configuration
Add the TypeScript plugin and update the input file. This is the complete file at this stage.
rollup.config.js
import { babel } from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import terser from '@rollup/plugin-terser';
import postcss from 'rollup-plugin-postcss';
import image from '@rollup/plugin-image';
import typescript from '@rollup/plugin-typescript';
const isProduction = process.env.NODE_ENV === 'production';
export default {
input: 'src/main.ts',
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: !isProduction,
},
plugins: [
resolve(),
commonjs(),
typescript({ sourceMap: !isProduction }),
babel({ babelHelpers: 'bundled', exclude: 'node_modules/**' }),
image(),
postcss({
extract: 'bundle.css',
minimize: isProduction,
}),
!isProduction && serve({ contentBase: ['dist'], port: 3000 }),
!isProduction && livereload('dist'),
isProduction && terser(),
]
};
6. Code Splitting with Dynamic Imports
Improve your application's initial load time by splitting code into smaller chunks that are loaded on demand. Rollup has first-class support for the dynamic `import()` syntax, making code splitting easy and efficient.
Step 1: Use a Dynamic Import in Your Code
Use `import()` to load a module dynamically, for example on a button click.
src/main.ts
// ...
button.onclick = () => {
import('./dynamic-module.js')
.then(module => {
module.showDynamicMessage();
});
};
// ...
Step 2: Update Rollup Configuration
To enable code splitting, your configuration needs several changes. The `output.format` must be changed to `es`, and `output.file` must be replaced with `output.dir`. The following is the complete and final `rollup.config.js` incorporating all plugins and features from the entire tutorial.
rollup.config.js
import { babel } from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import terser from '@rollup/plugin-terser';
import postcss from 'rollup-plugin-postcss';
import image from '@rollup/plugin-image';
import typescript from '@rollup/plugin-typescript';
const isProduction = process.env.NODE_ENV === 'production';
export default {
input: 'src/main.ts',
output: {
dir: 'dist',
format: 'es',
sourcemap: !isProduction,
},
plugins: [
resolve(),
commonjs(),
typescript({ sourceMap: !isProduction }),
babel({ babelHelpers: 'bundled', exclude: 'node_modules/**' }),
image(),
postcss({
extract: 'bundle.css',
minimize: isProduction,
}),
// For development
!isProduction && serve({
contentBase: ['dist'],
port: 3000,
}),
!isProduction && livereload('dist'),
// For production
isProduction && terser(),
],
};
7. Understanding Output Formats: `iife` vs. `es`
The output format determines how your bundled code is structured. Choosing the right one is crucial for compatibility and functionality. This section explains the two most common formats for web development in more detail.
`iife` (Immediately Invoked Function Expression)
This format is ideal for simple, single-file browser scripts. It wraps your entire bundle in a function that is executed immediately, creating a private scope. This prevents your code from adding variables to the global `window` object, which avoids conflicts with other scripts on the page.
Use when: You have a single entry point and don't need code splitting. It's great for compatibility with older browsers and simple script setups.
Example Output (dist/bundle.js)
(function () {
'use strict';
// All your bundled code is contained here...
})();
`es` (ES Modules)
This is the modern format for web applications. It outputs standard JavaScript modules that modern browsers can understand. Its primary advantage is that it's required for code splitting. When Rollup finds a dynamic `import()`, it creates a separate "chunk" file that the main bundle can load on demand.
Use when: You are building a modern application and want to use code splitting for better performance. Remember to load your script in HTML with <script type="module">.
Example Output (Multiple Files)
// dist/main.js
import { showDynamicMessage } from './chunk-abc.js';
// ... your main entry code ...
// dist/chunk-abc.js
const showDynamicMessage = () => { /*...*/ };
export { showDynamicMessage };
8. Conclusion & Next Steps
Congratulations on completing this guide! You now have a solid foundation for using Rollup.js to build efficient, modern JavaScript applications. You've learned how to set up a project, use essential plugins, manage different build environments, handle assets, and implement advanced features like TypeScript and code splitting.
From here, you can explore more advanced topics to further enhance your build process:
- Explore the Official Rollup Documentation for in-depth information.
- Discover more plugins in the Awesome Rollup list.
- Learn about advanced options like tree-shaking, creating multiple outputs, and building for Node.js.
- Integrate Rollup with other tools like Storybook or testing frameworks.