DEV Community

Cover image for How To Setup Rollup Config
Milos Protic
Milos Protic

Posted on • Updated on

How To Setup Rollup Config

Originally posted on my blog.

Front-End development has become extremely interesting and fun to do with the beginning of the ECMAScript and NPM era. There is a lot of packages and tools out there that we can use in our projects that can make our life easier. One of these tools is rollup.js.

Let's start the article with a short introduction and find out what rollup actually is and what it does for us and our application.

The official statement:

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.

Let's break down the statement above.

Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger

Developing an application is a lot easier if we split it into logically independent smaller pieces. That way we reduce the overall complexity of our code during development thus making it more approachable and maintainable. It is easier and faster for someone to join the team if he/she can focus on the smaller part instead of analyzing the entire application logic and trying to isolate a specific code block. This can dramatically increase the possibility of errors after injecting a new piece of code in the middle of it which is something we do not want.

Rollup helps us solve the use case described above. It takes our small pieces and bundles them all together into a single code base. To do this, we can use the command line or a specific configuration file called rollup.config.js.

In this article, I will cover a configuration file approach.

It uses the new standardized format for code modules included in the ES6

This is very neat. What this does is that enables us to write the import/export statements within our JavaScript files. We can import data, constants, functions, entire logic blocks...and all this we can write in the next generation of JavaScript and let rollup (and its plugins) worry about creating the browser readable output. It's possible to specify the output format, which we will see later in this post.

Just to summarize and answer the WHAT and WHY questions. Rollup is a JavaScript bundler (also can minify the output with a plugin) and we need it if we want to use the new syntactic sugar like import and export from the ECMAScript specification.

Note that the code below assumes that Node.js and NPM package manager had already been installed and that your application had been initialized with npm init command.

Installing Rollup

To install rollup and save it as development dependency we should run the following command:

npm install rollup --save-dev
Enter fullscreen mode Exit fullscreen mode

The command above will install the rollup node package and update the package.json file located in our application root folder.

"devDependencies": {
    "rollup": "^1.10.0" // the version might be different in your case depending on the time reading this
}
Enter fullscreen mode Exit fullscreen mode

Next, create a new file called rollup.config.js in the application root folder. Inside, add the following.

export default {
    input: './src/main.js',
    output: {
        file: './build/bundle.min.js',
        format: 'iife',
        name: 'bundle'
    }
}
Enter fullscreen mode Exit fullscreen mode

Let’s see what each of these configuration options does for us:

  1. input - This is a required setup and it represents the file we want rollup to process. It should be the main entry point of the application where we import everything else required by it

  2. output - It's an object like configuration where we set up the result of our processing. Minimum of the configuration is to include the:

    2.1 file - This is the location where our bundle will be created. It represents the file to write to. Usually under the build or dist folder. The folder and the file will be generated automatically by rollup

    2.2 format - Rollup supports several output formats. In our example, we will use an immediately-invoked function expression (iife)

    2.3 name - Global variable name representing the created bundle

Other formats can be found here, section output.format

Test the configuration

Now when we have our setup, we can test if everything works.

First, create a source folder, src. This folder will contain our application source files. Inside of it, create the application entry point, a file called main.js and the index.html page.

Next, let's create a test module. In the src folder, create a subfolder modules and a file within called MyModule.js. Inside, add the following:

const sayHello = (message) => {
    alert(message);
}

export default sayHello;
Enter fullscreen mode Exit fullscreen mode

In the main.js file add the import statement and use the imported function:

import sayHello from './modules/MyModule';

sayHello('Hello from Rollup');
Enter fullscreen mode Exit fullscreen mode

Open the package.json file and add the following script under the script setting:

"scripts": {
    "build": "rollup -c"
}
Enter fullscreen mode Exit fullscreen mode

and run the following command:

npm run build
Enter fullscreen mode Exit fullscreen mode

This will create a new folder called build in our project that contains the generated bundle.min.js file. We can see that the bundle was created properly by adding it as a reference to our index.html page and opening it in the browser.

<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8">
    <head>
        <title>Rollup Example</title>
    </head>

    <body>
    </body>

    <script src="../build/bundle.min.js"></script>
</html>
Enter fullscreen mode Exit fullscreen mode

If everything was done properly, an alert should popup immediately after opening the page.

At this point, only modern browsers will work without errors. To get this working with browsers that don’t support ECMAScript features, we need to include a couple of plugins.

Next Generation of JavaScript

Installing babel

In order to properly parse our module and make it compatible with older browsers, we should include babel to compile the output. If you are not familiar with it, babel is a JavaScript compiler and makes the next-gen JavaScript code cross-browser compatible by compiling it to the older version of it.

In order to continue with the example, we need to install the required packages:

npm install @babel/core @babel/preset-env rollup-plugin-babel --save-dev
Enter fullscreen mode Exit fullscreen mode

The command above will update our dev dependencies like so:

// the versions might be different in your case depending on the time reading this
"devDependencies": {
    "@babel/core": "^7.4.3",
    "@babel/preset-env": "^7.4.3",
    "rollup": "^1.10.0",
    "rollup-plugin-babel": "^4.3.2"
 }
Enter fullscreen mode Exit fullscreen mode

Next, we need to create a babel configuration file .babelrc in the application folder with the following content:

{
  "presets": [
      "@babel/env"
  ]
}
Enter fullscreen mode Exit fullscreen mode

After these actions, babel is configured and ready for usage. Considering that this article is about rollup, visit the official babel site for more information.

Updating rollup.config.js

The above changes alone will do nothing because we did not tell rollup that it needs to use the newly installed packages. We do this by updating the rollup.config.js file as shown below:

import babel from 'rollup-plugin-babel';

export default {
    input: './src/main.js',
    output: {
        file: './build/bundle.min.js',
        format: 'iife',
        name: 'bundle'
    },
    plugins: [
        babel({
            exclude: 'node_modules/**'
        })
    ]
}
Enter fullscreen mode Exit fullscreen mode

We left the input and output configurations like they were before, added an import statement to include the rollup-plugin-babel and introduced the plugins config option. Plugins are used to customize rollup behavior. In this case, we want it to compile our ECMAScript into its predecessor.

Also, we've excluded the node_modules folder to avoid third-party scripts and libraries being compiled. Now, we are ready to run our build command again:

npm run build
Enter fullscreen mode Exit fullscreen mode

The expected result is that our bundle now should have different content which is cross-browser compatible.

The bundle.min.js without babel:

(function () {
    'use strict';

    const sayHello = (message) => {
        alert(message);
    };

    sayHello('Hello from Rollup');

}());
Enter fullscreen mode Exit fullscreen mode

and with babel:

(function () {
    'use strict';

    var sayHello = function sayHello(message) {
      alert(message);
    };

    sayHello('Hello from Rollup');

}());

Enter fullscreen mode Exit fullscreen mode

Clearly, we can see the difference. Reserved word const is no longer present and it has been converted to var. Also, our arrow function has been converted to a cross-browser compatible version.

After opening index.html page in the browser, the result should be the same and a popup message should again be displayed.

Handling non-ES modules

So far our project was working without any node module dependency and the only module imported was the test one we've created. However, in the real world, this is rarely the case and our app would require a non-ES module.

Supporting the CommonJS modules is not provided out of the box by rollup, therefore we need a couple more plugins. In order to make our project to work with the node modules dependencies, we need to install the following packages:

npm install rollup-plugin-node-resolve rollup-plugin-commonjs --save-dev
Enter fullscreen mode Exit fullscreen mode

The rollup-plugin-node-resolve plugin allows us to load the third-party modules and the rollup-plugin-commonjs plugin converts them into the ES6 version.

Our package.json file should look like this:

// the versions might be different in your case depending on the time reading this
"devDependencies": {
    "@babel/core": "^7.4.3",
    "@babel/preset-env": "^7.4.3",
    "rollup": "^1.10.0",
    "rollup-plugin-babel": "^4.3.2",
    "rollup-plugin-commonjs": "^9.3.4",
    "rollup-plugin-node-resolve": "^4.2.3"
}
Enter fullscreen mode Exit fullscreen mode

Updating rollup.config.js - part 2

Again, rollup needs to know that it needs to use the new plugins. We configure them the same way we did for the rollup-plugin-babel plugin:

import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';

export default {
    input: './src/main.js',
    output: {
        file: './build/bundle.min.js',
        format: 'iife',
        name: 'bundle'
    },
    plugins: [
        babel({
            exclude: 'node_modules/**'
        }),
        resolve(),
        commonjs()
    ]
}
Enter fullscreen mode Exit fullscreen mode

Installing the Third-Party Library

Now we are ready to install and use our first third-party dependency. lodash for example. To install it, run the following command:

npm install lodash --save-dev
Enter fullscreen mode Exit fullscreen mode

Our package.json file should look like this:

"devDependencies": {
    "@babel/core": "^7.4.3",
    "@babel/preset-env": "^7.4.3",
    "lodash": "^4.17.11",
    "rollup": "^1.10.0",
    "rollup-plugin-babel": "^4.3.2",
    "rollup-plugin-commonjs": "^9.3.4",
    "rollup-plugin-node-resolve": "^4.2.3"
}
Enter fullscreen mode Exit fullscreen mode

Updating rollup.config.js - part 3

In order to use it, we again need to tweak the rollup.config.js file a little bit. We need to tell the rollup that we are using an external library with a global variable _. This is required since we are going to import it in our main.js file. Update the config like so:

import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';

export default {
    input: './src/main.js',
    output: {
        file: './build/bundle.min.js',
        format: 'iife',
        name: 'bundle',
        globals: {
            'lodash': '_',
        }
    },
    plugins: [
        babel({
            exclude: 'node_modules/**'
        }),
        resolve(),
        commonjs()
    ]
}
Enter fullscreen mode Exit fullscreen mode

By adding the globals configuration we made sure that rollup knows what to do with the external import.

Next, we should test to see if everything is working fine by trying to use the lodash library. For example, let's use the _concat function.

Update the main.js file like so:

import sayHello from './modules/MyModule';
import _ from 'lodash';

const arr = _.concat([1, 2, 3], 4, [5]);
sayHello('Hello from Rollup and lodash: ' + arr);
Enter fullscreen mode Exit fullscreen mode

and run the build command:

npm run build
Enter fullscreen mode Exit fullscreen mode

The created bundle.min.js should contain both modules. The test module we've created and the externally imported lodash module.

If we run the index.html page at this point we should see an alert with a different message. It should print the Hello from Rollup and lodash: 1,2,3,4,5 without problems.

Compressing the Output

It is not uncommon that production environments require a minified version of the final bundle. This is needed for various reasons like reduced size, loading speed, network delivery...etc. In order to do minify it, we need to install another plugin called rollup-plugin-uglify:

npm install rollup-plugin-uglify --save-dev

Enter fullscreen mode Exit fullscreen mode

Next, tell the rollup that it needs to use it by updating the rollup.config.js for the 4th time in this example:

import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import { uglify } from 'rollup-plugin-uglify';

export default {
    input: './src/main.js',
    output: {
        file: './build/bundle.min.js',
        format: 'iife',
        name: 'bundle',
        globals: {
            'lodash': '_',
        }
    },
    plugins: [
        babel({
            exclude: 'node_modules/**'
        }),
        resolve(),
        commonjs(),
        uglify()
    ]
}

Enter fullscreen mode Exit fullscreen mode

and run the build command:

npm run build
Enter fullscreen mode Exit fullscreen mode

Now, if we take a look at our bundle.min.js file the code should be a lot less readable :) If you compare the file before and after minification there should be an obvious size difference.

Comming Up

In the next rollup article, I will cover importing of the CSS and HTML files.

Thank you for reading and see you in the next post.

Top comments (17)

Collapse
 
antialias profile image
Thomas Hallock

lodash exports as CommonJS (via UMD), so there's no need to configure rollup to grab it off window... unless you're demonstrating how this can be done, and if that's the case, it might be helpful to point out that's why you did what you did and that normally (i.e. most modern packages) you'd just npm / yarn install your package and not have to muck with your bundler config at all.

Also, no need to install all of lodash and blow up your bundle size with all its functions if you're just going to use a couple of functions from it; e.g. lodash.concat and all the other lodash functions are published individually.

But then again, why use _.concat at all when your browser can already concat arrays pretty well without a library?

Collapse
 
djibe profile image
djibe

Hi,
note that commonjs must be invoked before babel.

"When using @rollup/plugin-babel with @rollup/plugin-commonjs in the same Rollup configuration, it's important to note that @rollup/plugin-commonjs must be placed before this plugin in the plugins array for the two to work together properly."
github.com/rollup/plugins/tree/mas...

Collapse
 
wrongnerfs profile image
Hello

I'm confused, I don't see how to include the global css file (from .scss). I have a "main.scss" file that imports a bunch of helper scss files (colors, typogrpahy) etc.. and I want to bundle "main.scss" and have it in my main page so all my components get the "base" styles. I went to the other link (rollup cheatsheet) but I am not seeing you include a global.css file anywhere.. I"m confused as to where the solution is for installing a global css file.

Collapse
 
antialias profile image
Thomas Hallock • Edited

I'm confused why you think the post is supposed to teach you how to configure rollup to bundle your css files... and why were you working with css files as late as October of 2020? en.wikipedia.org/wiki/CSS-in-JS

Collapse
 
1111byte profile image
UDI

Good :)

Collapse
 
proticm profile image
Milos Protic

Thanks 😊

Collapse
 
wzhkobe2408 profile image
Wzh • Edited

hope to see the next article, and can you include multi input configure and css/less/sass html files import

Collapse
 
proticm profile image
Milos Protic

Hi, I didn't post it on dev.to, but I've created a rollup cheat sheet that includes the CSS handling. You can check it out here. It's a shortened version of this post and, as an addition, it includes the CSS configuration.

Regarding the HTML, you can see the plugin in action on this repo.

Collapse
 
proticm profile image
Milos Protic

Sure, will include css/sass/html combination.

Collapse
 
spjesusdiaz profile image
Jesus

A year later, but still very useful article. Thanks a lot

Collapse
 
proticm profile image
Milos Protic

No problem :)

Collapse
 
slikts profile image
Reinis Ivanovs

Your IIFE output config doesn't work since the IIFE format also requires the name option to be set.

Collapse
 
proticm profile image
Milos Protic • Edited

Yes, I didn't update the article, but it's updated here though.

I will update this one too. Thanks for pointing out. In earlier versions, the name wasn't required.

EDIT: The name has been added to the output object

Collapse
 
maciekgrzybek profile image
Maciek Grzybek

Nice one mate, awesome article :)

Collapse
 
proticm profile image
Milos Protic

Thanks! Glad you find it useful

Collapse
 
davodaslanifakor profile image
Davod Aslani Fakor

how run development mode by rollup?

Collapse
 
js_bits_bill profile image
JS Bits Bill

Awesome write up. Exactly what I was looking for!