Javascript module bundler: rollup.js (Essential to learn)

Biswasindhu Mandal
13 min readDec 8, 2023

--

source: self

Here we will learn how to use rollup.js in UI application

📚What is rollup.js?

  • Rollup.js is a module bundler for Javascript applications.
  • It allows developers to bundle their code into a single or multiple file/s. Making it easier to manage dependencies and improve performance.
  • It’s commonly used on front-end development for building applications, libries and plugins.

📚How to create a web project with RollupJs📚

1. Create a basic environment:

  • Create Project Directory
    mkdir rollupjs && cd rollupjs
  • install package.json
    npm init -y

2. Add rollup dependencies into the project

  • Difference between dependencies & dev-dependencies in Node.js:
    - Dependencies are the packages that your project needs to run properly in production.
    - Dev-dependencies are the packages that are needed for development and building the project, but not required for it to run in production.
  • install Rollup as a global command line tool:
    npm install --global rollup
  • install dependencies: rollup
    npm i rollup --save-dev
    So, in your package.json it’s added like:
"dependencies": {
"rollup": "^4.6.1"
},
  • change script in package.json to build the project
"scripts": {
// need some specific format describe later
"build": "rollup"
},

3. Create project structure for rollupjs

  • Application basic structure:
rollupjs

├───build
│ ├───index.html
│ └───bundle.js (auto create after build)

├───node_modules

├───src
| └───index.js
|
├───package-lock.json
└───package.json
  • Create two directories: build & src
  • Createindex.html within build repo.
<!DOCTYPE html>
<html lang="eng">
<head>
<title>rollup</title>
</head>
<body>
<div style="text-align:center" id="main"></div>
<script src="bundle.js"></script>
</body>
</html>
  • Create index.js under src repo.
function mainContaint() {
var el = document.createElement("h1");
el.textContent = "This is First Rollup Project";
return el;
}

document.getElementById("main").appendChild(mainContaint());
  • Now run the project:
    npm run build
    - After run above script, it will open rollup --help page. Where clearly declear some specific format to build the code as follows:
  • So, to build the project required some format as input_source_path, output_dir_path, build_format.
    - Rollup support build format amd, cjs, system, es, iife or umd.
    -
    Here input file path: src/index.js
    - Output directory: build/bundle.js
    - Now modify package.json build script as follows:
  "scripts": {
// "rollup --format=<format> --file=<output_dir> -- <input_dir>
"build": "rollup --format=cjs --file=build/bundle.js -- src/index.js"
},

------- OR -------
"scripts": {
// "rollup <input_dir> --file <output_dir> --format <format>
"build": "rollup ./src/index.js --file ./build/bundle.js --format cjs"
},
  • So, RollupJs build the default script src/index.js & store build files under build folder name as: bundle.js
  • Now I explain how to add modules.
rollupjs

├───build
│ ├───index.html
│ └───bundle.js (auto create after build)

├───node_modules

├───src
│ ├───index.js
| └───module.js (add a new file)
|
├───package-lock.json
└───package.json
  • Now create another file under src repo as module.js.We are trying to import something into index.js and let's check what will happen…
  • Add this code within module.js file
export function module() {
var el = document.createElement("h2");
el.textContent = "This is Rollup Module Page";
return el;
}
  • Now import module.js into index.js file and update index.js as follows:
import { module } from "./module";

function mainBody() {
var el = document.createElement("h1");
el.textContent = "This is First Rollup Project";
return el;
}
function main() {
var d = document.getElementById("main");
d.appendChild(mainBody());
d.appendChild(module());
}
(function () {
main();
})();
  • Run the project: npm run build
  • Now you understand how to build your project using RollupJs.
  • If you are using visual code then you may run your project with “live-server”. Otherwise, you directly open build/index.html file locally and after build refresh the browser.
  • So, you will add multiple files in this way and create UI according to that.

4. Describe different type of Module Loaders

Module loader is a mechanism or software concept that facilitates the loading, resolution and execution of modular code in programming environent.
In the context of web development and JavaScript, module loader are essential for managing modular code organization and handling dependencies between different parts of an application.

  • AMD (Asynchronous Module Definition): This format allows modules to be define asynchronously. It’s commonly used in browsers for managing dependencies and loading modules.
  • CJS (Common JS): Generally used in serverside, like Node.js. Defines a synchronous approach to loading modules and allows modules to include their dependencies directly.
  • ES/ESM (ESMAScript): This module introduced the ES6 features like import, export statements.
  • IIFE (Immediately Invoken Function Expression): A Javascript design pattern whire function is defined and eecuted immediately after its creation. Help to create private scope for variable to avoid pooluting the global scope.
  • SYSTEM/SYSTEMJS: It introduce it’s own module format called “System.register”, which includeds metadata from module dependencies and allow for lazy loading. That can work with various format including CommonJS, AMD & ES6.
  • UMC (Universal Module Definition): This pattern allow a javascript library to work in various module system, including AMD, CommonJS and as a global variable. A versatile approach that enables developers to use a library in different environents.

📚RollUp configuration & Basic Plugins📚

1. Setup Basic Rollup Configuratin file:

Now package.json script as follows:

"scripts": {
"build": "rollup ./src/index.js --file ./build/bundle.js --format cjs"
},
  • Let’s create a rollup configuration file: rollup.config.js
  • Update package.json script config in rollup.config.js as follows:
// rollup.config.js
module.exports = [{
input: './src/index.js',
output: {
file: './build/bundle.js',
format: 'cjs'
}
}];
  • Now, update package.json script as follows
"scripts": {
"build": "rollup --config"
},
-------- OR --------
"scripts": {
"build": "rollup --config rollup.config.js"
},
  • After build the code, output file (build/bundle.js) show as:

2. Setup Rollup in watch mode

Rollup has a watch mode that allows it to watch any changes in our source files and automatically rebuild the project when changes are detected.
To use the watch mode, you can use the -w or --watch flag when running the Rollup command.
So, need to upgrade package.json script as follows:

"scripts": {
"build": "rollup --config --watch"
},
-------- OR --------
"scripts": {
"build": "rollup --config rollup.config.js --watch"
},
-------- OR --------
"scripts": {
"build": "rollup -c rollup.config.js -w"
},

3. Setup Rollup Plugin for Live Server

Still now we are using either vs-code live-server or run it locally.
In this block, we will learn how to create a rollup plugin to serve the bundle.

  • Install Rollup Plugin for Live Server:
    Live server — rollup-plugin-server: npm install --save-dev rollup-plugin-serve
    Automatic reload — rollup-plugin-livereload: npm install — save-dev rollup-plugin-livereload
  • So, package.json added the both devDependencies as follows:
// pacakge.json
... ... ...
"devDependencies": {
"rollup": "^4.6.1",
"rollup-plugin-livereload": "^2.0.5",
"rollup-plugin-serve": "^3.0.0"
}
... ... ...
  • Let configure rollup-plugin-serve & rollup-plugin-livereload plugins in rollup.config.js as follows:
// rollup.config.js
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';

export default [{
input: 'src/index.js',
output: {
file: 'build/bundle.js',
format: 'es'
},
plugins: [
serve({
// Launch in browser (default: false)
open: true,
// Page to navigate to when opening the browser.
openPage: '/index.html',
// Folder to serve files from
contentBase: 'build',
// Options used in setting up server
host: 'localhost',
port: 8008,
}),
// Automatic page refresh after any changes
livereload('build')
]
}];
  • Now build the code throghpacakge.jsonnpm run build
  • Now live server will work and show as follows:

4. Setup Rollup Plugin to Copy HTML file

Still now we are using index.html under the build directory.
Lets create a different directory for index.html, public. Also add the module.js under src and update index.js accordingly.
So, project structure as follows:

rollupjs

├───build
│ ├───index.html (buildFile: HTMLPlugin)
│ └───bundle.js (buildFile: auto create after build)

├───public (new directory for `index.html`)
│ └───index.html

├───src
│ ├───index.js
| └───module.js
|
├───package-lock.json
├───package.json
|
└───rollup.config.js

Clarly required some HtmlPlugin in rollup.config.js and after build two files will create under build directory; index.html & bundle.js.

  • Install Rollup Plugin to copy HTML file:
    rollup-plugin-copy : npm install — save-dev rollup-plugin-copy
  • Configure plugin in rollup.config.js :
// rollup.config.js
... ... ...
import copy from 'rollup-plugin-copy';

export default [{
... ... ...
plugins: [
copy({
targets: [{
// Copy HTML files from src to build
src: 'public/index.html',
dest: 'build'
}],
}),
... ... ...
... ... ...
]
}];
  • Now build the code: npm run build

📌 Check details about Rollup Configuratin Files:👉 link

📚RollUp configuration: CSS & Style Loader📚

Now we will add images and css files in this project.
So, we need to add css plugins.

  • Add Rollup css plugin — rollup-plugin-css-only : npm install --save-dev rollup-plugin-css-only
  • Lets update our project structure & then we will configure the css plugin in rollup config.
rollupjs

├───build (build repo)

├───public
│ └───index.html

├───src
│ ├───images (contains all type of images)
│ │
│ ├───module
│ │ ├───module.css
│ │ └───module.js
│ │
│ ├───index.css
| └───index.js
|
├───package-lock.json
├───package.json
|
└───rollup.config.js

Need to remember:
— — Need to create css file with same .js file name.
— — If you create some module and every module have separate css, then also create css with same module name and both *.js & *.css will in same directory.
— — If you create a single css along the project, then it should be index.css and it will exist same directory, where index.html is exist.
— — For image file/s created a separate directory, images.

  • Now update module.js, module.css, index.js & index.css as follows:
// index.css
body {
background-color: aqua;
background-image: url('./images/bg.avif');
}
.cl1 {
color: red;
font-size: 100px;
}
===========================================================
// index.js
import { module } from "./module/module";
import './index.css';
function mainBody() {
var el = document.createElement("h1");
el.textContent = "This is First Rollup Project";
return el;
}
function main() {
var d = document.getElementById("main");
d.appendChild(mainBody());
d.appendChild(module());
}
(function () {
main();
})();
// module.css
.cl2 {
color: pink;
font-size: 60px;
}
#my_logo {
content: url('./images/logo.png');
width: 200px;
height: 200px;
padding: 20px;
background-color: white;
}
===========================================================
// module.js
import './module.css';
function addImage() {
var x = document.createElement("img");
x.id = "my_logo";
var el = document.createElement("div");
el.appendChild(x);
return el;
}
export function module() {
var el = document.createElement("h2");
el.className = "cl2";
el.id = "id2";
el.textContent = "This is Module Page";
el.appendChild(addImage());
return el;
}
  • What we will do in css plugin config ?
    — — bundle all css across project to a single css file and it should be store in build dirctory.
    — — copy all image files (src/images/*) to build directory.
  • So, css plugin configuration in rollup.config.js as follows:
// rollup.config.js
... ... ...
import css from 'rollup-plugin-css-only'

export default [{
input: 'src/index.js',
output: {
file: 'build/bundle.js',
format: 'cjs'
},
plugins: [
css({
// all `*.css` files in src directory
input: ['src/*.css', 'src/*/*.css'],
// Optional: filename to write all styles to
output: 'bundle.css'
}),
copy({
targets: [{
// Copy HTML files from public to build
src: ['public/*'],
dest: 'build'
}, {
// Copy images from src to build
src: ['src/images/*'],
dest: 'build/images'
}],
}),
serve({
/* existing code */
});
livereload('build')
]
}];
  • Now build the code through pacakge.json: npm run build

📚Important Rollup Plugins📚

  1. Module Resolution:
    Plugins like @rollup/plugin-node-resolve help resolve module paths, especially for dependencies installed in the node_modules directory. This is essential for Rollup to locate and bundle external modules.
  2. CommonJS to ES Module Conversion:
    Many third-party packages are written in CommonJS format. The @rollup/plugin-commonjs plugin converts CommonJS modules to ES modules, making them compatible with Rollup's module system.
  3. Code Transformation:
    Plugins like rollup-plugin-babel, rollup-plugin-typescript, or @rollup/plugin-terser enable the transformation of code written in different languages (e.g., ES6/ESNext, TypeScript) and perform tasks like transpilation and minification.
  4. CSS and Stylesheet Handling:
    Plugins like rollup-plugin-postcss allow Rollup to process and bundle CSS files, and optionally extract them into separate files. This is essential for managing styles in modern web development.
  5. HTML and Asset Management:
    While Rollup primarily focuses on JavaScript, plugins like rollup-plugin-html or rollup-plugin-copy assist in handling HTML files and other assets, ensuring a comprehensive build process.
  6. Live Development Server:
    Plugins such as rollup-plugin-serve and rollup-plugin-livereload provide features for local development, allowing you to serve your application, automatically reload pages, and debug more efficiently during development.
  7. Tree Shaking:
    Rollup is known for its tree-shaking capabilities, eliminating dead code to generate smaller bundles. Plugins like rollup-plugin-node-builtins and rollup-plugin-node-globals help with tree shaking by providing necessary polyfills.
  8. Dynamic Import Handling:
    Plugins like @rollup/plugin-dynamic-import-vars and @rollup/plugin-dynamic-import assist in handling dynamic imports, a feature introduced in ECMAScript modules.
  9. Customization and Extensibility:
    Rollup plugins provide a way to extend Rollup’s behavior according to project-specific requirements. This customization is essential for handling diverse project structures, external dependencies, and specific build optimizations.
  10. Optimizations and Minification:
    Plugins like @rollup/plugin-terser or rollup-plugin-uglify help minify and optimize the final bundled JavaScript code, reducing its size for production deployment.

📌 Check different type of rollup plugins details: 👉 link

📚Rollup Configuration Mode: dev or prod📚

1. What are dev & prod mod ?

Production Mode: Primarily intended for use during the development and testing phases of a software project.
Development Mode: Designed for the final deployment of an application in a live or production environment, where performance and efficiency are critical.

✅Rollup devServer (rollup-plugin-serve & rollup-plugin-livereload) & watch mode (-w) not required for production mode.
✅Production mode used JavaScript minifier and mangler (@rollup/plugin-terser) that can help reduce the size of your JavaScript files.
✅Production mode will use Javascript Obfuscator (rollup-obfuscator) to difficult to understand or reverse engineer our existing code.

🇳🇧✍️I will change rollup.config.js buildle files as follows:
js bundle file: bundle.jssript.js
css bundle file name: bundle.cssstyle.css
Please update rollup.config.js & *.html files accordingly

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

There are two way to create dev & prod mode rollup.js build.
1️⃣ Through Pacakge.json we set dev & prod mode build.
2️⃣ We will set two diffent rollup.config for dev & prod mode and set up accordingly.

2. Config Rollup dev & prod build mode through package.json

  • Update package.json script for prod & dev build as follows :
"scripts": {
"build:prod": "NODE_ENV=production rollup -c rollup.config.js",
"build:dev": "rollup -c rollup.config.js -w"
},
  • We will create two different directory under build directory, name as prod & dev for production & development build respictively.
    Also use JavaScript minifier (@rollup/plugin-terser plugin) for prduction build and not used rollup-server for production build.
  • Now, update rollup.config.js as follows for prod & dev mode:
// rollup.config.js
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import copy from 'rollup-plugin-copy';
import css from 'rollup-plugin-css-only';
// Used for production build
import terser from '@rollup/plugin-terser';

const isProductionBuild = process.env.NODE_ENV === 'production';
console.log('is Rollup Production Build: ', isProductionBuild ? "Yes" : "No");

export default [{
input: 'src/index.js',
output: {
file: `build/${isProductionBuild ? 'prod' : 'dev'}/script.js`,
format: 'cjs'
},
plugins: [
css({
// all `*.css` files in src directory
input: ['src/*.css', 'src/*/*.css'],
// Optional: filename to write all styles to
output: 'style.css'
}),
copy({
targets: [{
// Copy HTML files from public to build
src: ['public/*'],
dest: `build/${isProductionBuild ? 'prod' : 'dev'}`
}, {
// Copy images from src to build
src: ['src/images/*'],
dest: `build/${isProductionBuild ? 'prod' : 'dev'}/images`
}],
}),
!isProductionBuild && serve({
// Launch in browser (default: false)
open: true,
// Page to navigate to when opening the browser.
openPage: '/index.html',
// Folder to serve files from
contentBase: `build/${isProductionBuild ? 'prod' : 'dev'}`,
// Options used in setting up server
host: 'localhost',
port: 8008,
}),
// Automatic page reload after any changes
!isProductionBuild && livereload(`build/${isProductionBuild ? 'prod' : 'dev'}`),
// JavaScript minifier
isProductionBuild && terser({
maxWorkers: 4,
compress: {
drop_console: true,
}
}),
]
}];

3. Config Rollup dev & prod mode build with different file

  • Create two files rollup.config.dev.js & rollup.config.prod.js and copy exising code of rollup.config.js to both file.
  • We will create two different directory under build directory, name as prod & dev for production & development build respictively.
  • Create dev & prod build script in package.json and use watch mode only for dev build.
    So, changes as follows:
// package.json
"scripts": {
"build:prod": "rollup -c rollup.config.prod.js",
"build:dev": "rollup -c rollup.config.dev.js -w",
}
  • 💥💥💥Create Rollup Devlopment Config💥💥💥
    Now update rollup dev config according to build/dev directory.
    So, rollup.config.dev.js changes as follows:
// rollup.config.dev.js
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import copy from 'rollup-plugin-copy';
import css from 'rollup-plugin-css-only';

export default [{
input: 'src/index.js',
output: {
file: 'build/dev/script.js',
format: 'cjs'
},
plugins: [
css({
// all `*.css` files in src directory
input: ['src/*.css', 'src/*/*.css'],
// Optional: filename to write all styles to
output: 'style.css'
}),
copy({
targets: [{
// Copy HTML files from public to build
src: ['public/*'],
dest: 'build/dev'
}, {
// Copy images from src to build
src: ['src/images/*'],
dest: 'build/dev/images'
}],
}),
serve({
// Launch in browser (default: false)
open: true,
// Page to navigate to when opening the browser.
openPage: '/index.html',
// Folder to serve files from
contentBase: 'build/dev',
// Options used in setting up server
host: 'localhost',
port: 8008,
}),
// Automatic page reload after any changes
livereload('build/dev')
]
}];
  • 💥💥💥Create Rollup Production Config💥💥💥
    Now update rollup prod config according to build/dev directory.
    — Remove Rollup Plugin Live Server (rollup-plugin-serve & rollup-plugin-livereload) config.
    — Add JavaScript minifier plugin(@rollup/plugin-terser) for prduction build, for Reduced File Size, Improved Page Load Performance, Caching Efficiency, Tree Shaking.
    — Add JavaScript obfuscator plugin(rollup-obfuscator/ javascript-obfuscator) for prduction build, which Code Protection, Security Through Obscurity, String and Code Encryption, Reduced Risk of Code Tampering, Compliance with Licensing Agreements etc.
    So, rollup.config.dev.js changes as follows:
// rollup.config.prod.js
import copy from 'rollup-plugin-copy';
import css from 'rollup-plugin-css-only'

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

export default [{
input: 'src/index.js',
output: {
file: 'build/prod/script.js',
format: 'cjs',
name: 'production'
},
logLevel: 'none',
plugins: [
css({
// all `*.css` files in src directory
input: ['src/*.css', 'src/*/*.css'],
// Optional: filename to write all styles to
output: 'style.css'
}),
copy({
targets: [{
// Copy HTML files from public to build
src: ['public/*'],
dest: 'build/prod'
}, {
// Copy images from src to build
src: ['src/images/*'],
dest: 'build/prod/images'
}],
}),
terser({ // JavaScript minifier
// maximum number of worker processes for parallelizing the minification process
maxWorkers: 4,
compress: {
// Remove console.log statements in production build
drop_console: true,
}
}),
obfuscator({
// what files will obfuscate or what not
include: ['src/**/*.js', 'public/*.html'],
exclude: ['node_modules/**'],
// Obfuscator Rules
compact: false,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
numbersToExpressions: true,
simplify: true,
stringArrayShuffle: true,
splitStrings: true,
stringArrayThreshold: 1
})
]
}];
  • How to build dev & prod build:
    — — Production build: npm run build:prod : will create a obfuscate minifire library
    — — Development Build: npm run build:dev : will create a common js library for devepment testing.
  • More details check rollup documentation
  • check sample code👉 Rollupjs_sample-code

--

--

Biswasindhu Mandal

I am a Software Engineer, living in Kolkata, India. I love to work as a Javascript, Node.js Full Stack developer and OTT Frontend Developer.