r/webdev - Bundle your React app with Rollup.js

Rollup & React

According to Tooling.Report maintained by GoogleChromeLabs , Rollup.js performs better than other bundlers.

r/webdev - Bundle your React app with Rollup.js

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:

r/webdev - Bundle your React app with Rollup.js

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:

  1. It takes an input file with your code

  2. It performs some actions to your code based on the provided plugins you gave

  3. 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.

r/webdev - Bundle your React app with Rollup.js

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

r/webdev - Bundle your React app with Rollup.js

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

r/webdev - Bundle your React app with Rollup.js

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

r/webdev - Bundle your React app with Rollup.js

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

r/webdev - Bundle your React app with Rollup.js

created the bundle.js successfully

The build was successful. But, there’s a last error in the page.

r/webdev - Bundle your React app with Rollup.js

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

r/webdev - Bundle your React app with Rollup.js

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



Source link

Write A Comment