topic: JavaScript by Milos Protic relates to: Web Development, Advice, Rollup, Config on April, 18 2019
How To Setup Rollup Config
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
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
}
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'
}
}
Let’s see what each of these configuration options does for us:
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 itoutput
- It's an object like configuration where we set up the result of our processing. Minimum of the configuration is to include the:file
- This is the location where our bundle will be created. It represents the file to write to. Usually under thebuild
ordist
folder. The folder and the file will be generated automatically by rollupformat
- Rollup supports several output formats. In our example, we will use an immediately-invoked function expression (iife)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;
In the main.js
file add the import statement and use the imported function:
import sayHello from './modules/MyModule';
sayHello('Hello from Rollup');
Open the package.json
file and add the following script under the script setting:
"scripts": {
"build": "rollup -c"
}
and run the following command:
npm run build
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>
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
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"
}
Next, we need to create a babel configuration file .babelrc
in the application folder with the following content:
{
"presets": [
"@babel/env"
]
}
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/**'
})
]
}
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
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');
}());
and with babel:
(function () {
'use strict';
var sayHello = function sayHello(message) {
alert(message);
};
sayHello('Hello from Rollup');
}());
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
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"
}
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()
]
}
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
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"
}
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()
]
}
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);
and run the build
command:
npm run build
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
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()
]
}
and run the build command:
npm run build
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.
Subscribe to get the latest posts delivered right to your inbox