Alameda Dev.
Published in

Alameda Dev.

Build React JS application with ESbuild and node.

Recently we made a change in one of the projects for our client, we were tasked with changing the build loader of a ReactJS application from webpack to esbuild.

As we love to try new things in React, this was a great opportunity to test a new tool that is gaining popularity in the ecosystem. Fortunately we had the help of Kevin Burke https://www.linkedin.com/in/ekrub/ to guide us and solve this daunting task, he made the initial setup with ‘Make’; but out of curiosity we wanted to test doing it with node.

Based on Kevin’s work, we have adapted the code to work with Node. And here we will show you how to change the loader from Webpack to esbuild with node doing these easy steps.

With the change from Webpack to esbuild we could shave 24 seconds of the app build 😆
We now have faster deployments and this is great!!

Esbuild build: Done in 481ms
Webpack build: Done in 25.06s.

Basic setup

  1. Create a ‘build’ folder at the root of your project
cd your_project
mkdir build

2. Create an ‘index.html’ file in the ‘build’ folder

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<link rel="icon" href="favicon.png"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<meta name="theme-color" content="#000000"/>
<link rel="manifest" href="/manifest.json"/>
<title>My App</title>
<link href="/static/css/index.css" rel="stylesheet">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/static/js/index.js"></script>
</body>
</html>

3. Add ‘esbuild’ package to you node_packages

yarn add esbuild  // or
npm install esbuild --save

4. Add ‘regenerator-runtime’ to your app. (This is needed for making fetch calls, don't add this if you don't need it).

yarn add regenerator-runtime // or
npm install regenerator-runtime —save

In your ‘src/index.jsx’, add at the top:

...
import "regenerator-runtime/runtime";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>
)
...

5. Create a ‘build.js’ file on the root of your project

const { build } = require('esbuild');
const fs = require('fs-extra');
const generateBuild = async () => {
await fs.rmdirSync('./build/static', { recursive: true });
await build({
entryPoints: ['./src/index.jsx'],
outdir: './build/static/js',
minify: true,
bundle: true,
sourcemap: true,
target: ['chrome58', 'firefox57', 'edge16'],
loader: { ".svg": "dataurl", ".png": "dataurl" },
define: {
'process.env.NODE_ENV': "'production'",
...your env variables...,
}
}).catch(() => process.exit(1));
await fs.move('./build/static/js/index.css', './build/static/css/index.css', (err) => {
if (err) return console.error(err);
console.log("success!");
return null;
}
);
};
generateBuild();

6. Add ‘fs-extra’ package to your packages.

yarn add fs-extra // or
npm install fs-extra —save

7. Run your build

node build.js

The generated files should be in the ‘build’ folder now.

8. You should change your build scripts to use this build command.

"scripts": {
...
"esbuild": "node ./build.js"
...
},

Extra Steps:

To use esbuild in development mode and watch for the changes in files, we are going to make some more configurations.

As we are serving the build from a different folder and with different configurations we need to start the server on this new folder and using new configurations.

The react-script starts the app by default in the current folder and looks by default for the ‘src/index.jsx’ file unfortunately we can’t change this default behavior without ejecting. So we are going to use a separate server (servor) to start from our new build folder.

In the terminal run

npx servor ./build/ index.html --reload

It will ask for install the ‘servor’ package. Accept and install the package.

Then it will run with the options passed, and serve from the ‘build’ folder.

Now that we have the server running we need a way to watch for file changes and refresh the page. Chokidar package is great for this.

Let's install ‘chokidar’ package

yarn add chokidar // or
npm install chokidar --save

Modify the ‘build.js’ script to add chokidar watcher.

const { build } = require('esbuild');
const chokidar = require('chokidar');
const fs = require('fs-extra');
const generateBuild = async () => {
await fs.rmdirSync('./build/static', { recursive: true });
await build({
entryPoints: ['./src/index.jsx'],
outdir: './build/static/js',
minify: true,
bundle: true,
sourcemap: true,
target: ['chrome58', 'firefox57', 'edge16'],
loader: { ".svg": "dataurl", ".png": "dataurl" },
define: {
'process.env.NODE_ENV': "'production'",
...your env variables...,
}
}).catch(() => process.exit(1));
await fs.move('./build/static/js/index.css', './build/static/css/index.css', (err) => {
if (err) return console.error(err);
console.log("success!");
return null;
}
);
};
chokidar.watch('.', {ignored:/build|node_modules|.git/}).on('all', (event, path) => {
console.log(event, path);
generateBuild();
});

Don’t forget

In one terminal you should have the server running

npx servor ./build/ index.html --reload

And In another terminal you should have the build script running

node build.js

Also, change your ‘env.’ variables accordingly.

Notice you can have one ‘build.js’ file and one ‘watch.js’ file for different configurations if you need.

And that’s all. Enjoy your extra time!

Big thanks to Kevin for helping us decipher this.

You can find the code for this tutorial is in our GitLab account https://gitlab.com/alamedadev/react-js-build-using-esbuild

Hello We are Alameda Dev.!

We would love to help you, offer you a first conversation to talk about your ideas and help you focus on them.

Alameda Dev. Is a 100% remote team. Specialized in developing mobile applications, websites and advanced software in the React ecosystem.

You can read other interesting posts about technology: https://medium.com/alameda-dev

You can also enter the web: www.alamedadev.com

Follow us on:

Twitter: @AlamedaDev

--

--

--

We are a small agency 100% Remote. Specialized in Design and Development of Mobile Apps, Web and advanced software with React Ecosystem.

Recommended from Medium

Which type of loop is fastest in JavaScript?

React Custom Hooks #2: useFontSize

useFontSize hook usage

Ternary Operator

Realtime Face Recognition

Building an interactive order form using Getform and Appizy

How to Create a Headless WordPress Site with ReactJs

Let’s Build DnD Column Reordering in an HTML Table w/ React Hooks

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alameda Dev.

Alameda Dev.

¡Hola! We are a team 100% Remote. Specialized Development of Mobile Apps, Web and advanced software with React and ReactNative. www.alamedadev.com

More from Medium

Easy Custom API Hook — React

THE REACT WITH REDUX

Private Routes With React Js — React -Router V6

Understanding React Hooks