Rollup & React
According to Tooling.Report maintained by GoogleChromeLabs , Rollup.js performs better than other bundlers.
bundlers
In this blog post, we will see how to bundle a React.js app with rollup.js.
Let’s start
Make sure that you have installed a node.js version in your machine. Nvm makes things easier and allows us to have multiple versions of node.js in our machine.
Let’s install the latest stable nodejs version:
nvm install stable
Now using node v15.3.0 (npm v7.0.14)
Cool! We’re ready to go.
Setup your project:
mkdir react-rollup-app
cd react-rollup-app
npm init
The above command will create the initial package.json. We’re going to enhance this file later.
package.json
{
"name": "react-rollup-app",
"version": "1.0.0",
"description": "A react app bundled with rollup.js",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "John Dusaitis",
"license": "MIT"
}
We’re going to enhance this file later.
Create the html file which will host your React.js app.
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Your React app bundled with Rollup.js</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
Open it with your browser:
loads the page
That’s a good start, but soon or later you’ll need a web server to load other static files such as javascript and css files.
How rollup.js works?
It’s pretty simple:
-
It takes an input file with your code
-
It performs some actions to your code based on the provided plugins you gave
-
It produces one or more output files
Give me a dead simple example
OK, fair! Let’s change the body background colour of our page.
src/index.js
document.body.style.backgroundColor = "yellow";
Install rollup and some plugins for development
Rollup.js comes with a variety of plugins and one of them can play as web server to host all your static files. We will also need another one which reloads the page after each edit of our javascript files.
Install rollup and the above 2 plugins:
npm i rollup rollup-plugin-serve rollup-plugin-livereload –save-dev
Create the rollup configuration file:
rollup.config.dev.js
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
export default {
input: 'src/index.js',
plugins: [
serve({
open: true,
verbose: true,
contentBase: ['', 'dist'],
historyApiFallback: true,
host: 'localhost',
port: 3000
}),
livereload({ watch: 'dist' })
],
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: true
}
};
In our case the output file dist/bunlde.js will be used by our index.html to run the javascript code.
Include it to your index.html file:
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Your React app bundled with Rollup.js</title>
</head>
<body>
<div id="app"></div>
<script src="/dist/bundle.js"></script>
</body>
</html>
Add the build:dev script to package.json
package.json
{
...
"scripts": {
"build:dev": "rollup -c rollup.config.dev.js -w"
}
...
}
and run the command npm run build:dev.
This command, will load our yellow page to localhost:3000.
Loads the page to localhost:3000
So far, so good. Now it’s time to run some React code.
Setup your React code
Install the react and react-dom libs:
npm i react react-dom
Create your first React component:
src/App.jsx
import React, { useState } from 'react';
const App = () => {
const [counter, setCounter] = useState(0)
return (
<div>
<h4>A react page bundled with Rollup.js</h4>
<br />
<h1>Counter: {counter}</h1>
<br />
<button onClick={()=>{setCounter(counter+1)}}>+ Increase</button>
<br />
<button onClick={()=>{setCounter(counter-1)}}>- Decrease</button>
</div>
);
};
export default App;
Edit the src/index.js to run the react code.
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
const root = document.querySelector('#app');
ReactDOM.render(<App />, root);
Run the build script again:
npm run build:dev
error #1
Hmmm, error No #1. <App />Unexpected token..
This happens because JSX is not valid JavaScript and must be transpiled to valid JavaScript. Babel is one of the most popular JavaScript tranpilers out there.
Babel also allow us to write modern JavaScript. It converts ES6/ES7 to older versions such as ES5 which are compatible with old browsers.
Install babel and the related react-preset.
npm i babel @babel/preset-react @rollup/plugin-babel --save-dev
Edit the rollup.config.dev.js
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import babel from '@rollup/plugin-babel';
export default {
input: 'src/index.js',
plugins: [
babel({
presets: ['@babel/preset-react']
}),
serve({
open: true,
verbose: true,
contentBase: ['', 'dist'],
historyApiFallback: true,
host: 'localhost',
port: 3000
}),
livereload({ watch: 'dist' })
],
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: true
}
};
Run again the build script:
npm run build:dev
error #2
Error No #2. (!) Unresolved dependencies . The packages react and react-dom cannot be found.
To overcome this issue, we need another rollup plugin. The @rollup/plugin-node-resolve.
npm i @rollup/plugin-node-resolve --save-dev
add it to rollup.config.dev.js:
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import babel from '@rollup/plugin-babel';
import { nodeResolve } from '@rollup/plugin-node-resolve';
export default {
input: 'src/index.js',
plugins: [
nodeResolve({
extensions: ['.js', '.jsx']
}),
babel({
presets: ['@babel/preset-react']
}),
serve({
open: true,
verbose: true,
contentBase: ['', 'dist'],
historyApiFallback: true,
host: 'localhost',
port: 3000
}),
livereload({ watch: 'dist' })
],
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: true
}
};
Run again the build script:
npm run build:dev
error #3
Error No #3, name exports, this time. Let’s fix it.
For this we need the @rollup/plugin-commonjs plugin which converts CommonJS modules to ES6.
npm i @rollup/plugin-commonjs --save-dev
add it to rollup.config.dev.js:
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import babel from '@rollup/plugin-babel';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default {
input: 'src/index.js',
plugins: [
nodeResolve({
extensions: ['.js', '.jsx']
}),
babel({
presets: ['@babel/preset-react']
}),
commonjs({
include: ['node_modules/**']
}),
serve({
open: true,
verbose: true,
contentBase: ['', 'dist'],
historyApiFallback: true,
host: 'localhost',
port: 3000
}),
livereload({ watch: 'dist' })
],
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: true
}
};
Let’s run the build script again:
npm run build:dev
created the bundle.js successfully
The build was successful. But, there’s a last error in the page.
error #4
Error No #4, Uncaught ReferenceError: process is not defined. In order to fix this issue, we need a last plugin. The @rollup/plugin-replace which replaces strings in files while bundling.
npm i @rollup/plugin-replace --save-dev
Include it to the rollup config file:
rollup.config.dev.js
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import babel from '@rollup/plugin-babel';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import replace from '@rollup/plugin-replace';
export default {
input: 'src/index.js',
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify('development')
}),
nodeResolve({
extensions: ['.js', '.jsx']
}),
babel({
presets: ['@babel/preset-react']
}),
commonjs({
include: ['node_modules/**']
}),
serve({
open: true,
verbose: true,
contentBase: ['', 'dist'],
historyApiFallback: true,
host: 'localhost',
port: 3000
}),
livereload({ watch: 'dist' })
],
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: true
}
};
Let’s run the build script again:
npm run build:dev
the react app ran successfully
? Congrats! You have your first React & Rollup.js app is up and running. ?
Find the full source code at my github repo.
And the live working example at https://dusaitis.co/react-rollup-app/index.html
Thanks for reading.
John Dusaitis
P.S. Original blog post: https://dusaitis.com/bundle-your-react-app-with-rollup-js