Speed up your create-react-app build times by 80% with esbuild
let's give our good ol' CRA a little chance, shall we?
A short view back to the past
create-react-app
in 2017 (its v1 release) was this cool kid in around the block. We finally had a go-to way to start a react project that you couldn't go wrong with.
But as happens with everything on the web, people realized these client-side apps did not give out the performance they thought they would. Hence, came frameworks like Next.js. People/Organizations who could afford to move their react projects to these frameworks did that. While others stuck with CRA, with the hopes that things would get better.
Then came a time when people started experimenting with low-level languages (like Rust, Go for example) to replace JavaScript for our build tools and Hence things like Vite and esbuild were born.
We started seeing these massive differences in build times. Fact that Vite looked so similar but "Faster", everyone thought of just moving to Vite from CRA. But again there were these external packages at time that did not have an esmodule support and again people with am CRA app was stuck.
But then people like Hiroki came to save the day! They looked at the default CRA webpack config and said, "What if we replace the parts of this config, which are really slow with the equivalent APIs of esbuild
?" and they did exactly that by building esbuild-loader
I did something similar to what we are going to do next at my previous workplace and let's just say the improvements were pretty wild ๐
Enough of the history lesson, give me the code already
We are going to use something like Craco, So that we don't even have to eject
our CRA app.
Imagine using Craco, similar to sneaking up into the webpack config of CRA, changing the default webpack config just a little bit, without touching anything else ๐
Make sure your
react-scripts
package is updated to at least version 5.0.0 inside yourpackage.json
Install
@craco/craco
andcraco-esbuild
as dev dependenciesWe are using
craco-esbuild
here as it makesesbuild-loader
a craco plugin, which makes the whole process a LOT smoother.
npm install --save-dev craco-esbuild @craco/craco
- Create a
craco.config.js
file in the root directory and insert this code snippet
const CracoEsbuildPlugin = require("craco-esbuild");
const webpack = require("webpack");
module.exports = {
plugins: [
{
plugin: CracoEsbuildPlugin,
options: {
esbuildMinimizerOptions: {
target: "es2015",
css: true, // OptimizeCssAssetsWebpackPlugin being replaced by esbuild.
},
},
},
],
webpack: {
plugins: {
add: [
new webpack.DefinePlugin({
process: { env: {}, browser: {} },
}),
],
},
configure: {
resolve: {
fallback: {
fs: false,
tls: false,
net: false,
path: false,
zlib: false,
http: false,
https: false,
stream: false,
crypto: false,
buffer: false,
},
},
},
},
};
The first part of the config is just us adding a craco plugin called CracoEsbuildPlugin
that taps into our webpack config and replaces babel-loader
, terser
and OptimizeCssAssetsWebpackPlugin
. All of these plugins are being used under the hood of create-react-app
when running the dev server and during the build process. We are replacing all of these with esbuild, that's part of the reason why we see these crazy improvements in the build times.
---------------
configure: {
resolve: {
fallback: {
fs: false,
...............................
Here we are telling webpack to not include polyfills for these node.js modules. Not setting them false
explicitly, gave out some pretty bad compatibility errors with external libraries. You can read more about this part of the config here.
- Replace
react-scripts
build command withcraco
inpackage.json
+ "build": "craco build",
- "build": "react-scripts build",
+ "start": "craco start",
- "start": "react-scripts start",
That's it! Benchmark Time!
aaaand we are done! You know what they say, optimizing without any benchmarking isn't optimizing :)
Would LOVE to see the improvements if ya'll get any! There's a whole github discussion about the gains people make with esbuild.
If you made it this far, thank you for reading!
Do you think something's not right with the blog? is some part confusing you?
Please Reach out to me on Twitter, I am Tanvesh Sarve (@Sarve___tanvesh) / Twitter