How to build code generated by create-react-app with esbuild
I'm JS developer with 13 years of professional experience. I'm always happy to teach my craft.
esbuild is js bundler that is getting more and more traction because of it impressive build speed. create-react-app (CRA) is well-established script to generate a new react application. In this article, we will take a look on what tweaks are needed to CRA output to pass build with esbuild.
Alternatives
There are some react app generators that use esbuild out of the box:
and those can be a good idea if you are starting a new project, but for already existing apps they probably will not be of much help.
Generting new application
To simplify our example, let's generate new application with CRA:
$ npx create-react-app esbuild-cra
Creating a new React app in /home/marcin/workspace/github/tmp/esbuild-cra.
Installing packages. This might take a couple of minutes.
...
We suggest that you begin by typing:
cd esbuild-cra
npm start
Happy hacking!
The next step is to install esbuild:
$ npm install --save-dev esbuild
added 1 package, and audited 1962 packages in 4s
146 packages are looking for funding
run `npm fund` for details
...
Adding test HTML
For testing the esbuild we will create a dist folder, and put there manually created index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<title>React App</title>
<link href="main.css" rel="stylesheet" />
</head>
<body>
<div id="root"></div>
<script src="main.js"></script>
</body>
</html>
I created it based on html output of npm run script, and replace all dynamically created file references with static one that we will build in a moment.
Build script
To build the application, I'll leave the original npm scripts as they were & add temporarily esbuild script for testing. I recommend doing the same if you decide to migrate your app - it will allow for a smooth testing before replacing original builds. Plus you will want to replace dev script too - something that is not covered in this article, and you will need to figure it out on your onw.
To package.json, I add:
"scripts": {
....
"esbuild": "esbuild src/index.js --bundle --outfile=dist/main.js --loader:.html=text --loader:.js=jsx --loader:.svg=dataurl"
}
The build script parts means as follow:
src/index.js- the entry point of our build. From there all our files are found--bundle- the files are all bundled into one, output file--outfile=dist/main.js- the location where the output files should be saved--loader:.html=text- a loader that will read all HTML files are strings equal to the file content--loader:.js=jsx- the JSX load for JS files - as CRA uses this extension for JSX files--loader:.svg=dataurl- loader that includes SVG files as data url links (data:image/svg;base64....)
With this script in place we already can successfully run npm run esbuild:
$ npm run esbuild
> esbuild-cra@0.1.0 esbuild
> esbuild src/index.js --bundle --outfile=dist/main.js --loader:.html=text --loader:.js=jsx --loader:.svg=dataurl
dist/main.js 902.9kb
dist/main.css 1019b
⚡ Done in 61ms
Add explicit import
If you open the test page as it is now, you will see a white screen and the following error in console:
Uncaught ReferenceError: React is not defined
App http://localhost/github/tmp/esbuild-cra/dist/main.js:20611
renderWithHooks http://localhost/github/tmp/esbuild-cra/dist/main.js:12714
mountIndeterminateComponent http://localhost/github/tmp/esbuild-cra/dist/main.js:14834
...
luckily it's easy to fix, we just need to import React in all places that are referencing it. In our case, just add to src/App.js this line as the first line:
import React from "react";
Links
Summary
In this article, we have seen how to build esbuild an app generated with create-react-app. If you are interested in other articles on this topic, let me know in the comments.
You can see the application in action here, and the repository here





