How to speed up webpack with esbuild-loader
I'm JS developer with 13 years of professional experience. I'm always happy to teach my craft.
Search for a command to run...
I'm JS developer with 13 years of professional experience. I'm always happy to teach my craft.
No comments yet. Be the first to comment.
In this series, I'll share tips about optimizing your webpack configuration.
Webpack has the feature of accepting an array of configuration objects instead of one object. Unfortunately, it comes with a performance penalty - in this article, I'll look at how serious the slow-down can get. Code I'll have 10 files in the benchma...
I’ve been working in programming for the last 16 years. Let’s see what changes I see in our industry that are enabled by generative AI. Rapid prototyping The last few months, I’ve been working on a set of WordPress plugins, related to event organizat...
Writing unit tests takes time and effort. Nonetheless, many teams insist on writing them anyway—that’s because of the benefits they bring to a project. Those benefits are mainly the following: fast feedback—unit tests speed up each iteration of twea...

Pure functions are the perfect case for unit testing. For a given input, we always expect the same output—there is no internal state involved. Let’s take a look at a few examples and some simple tests that check if the methods work as expected. Jasmi...

Let’s say you have a job interview in a few days. How should you prepare for it so that you can make an informed decision about joining the company, as well as make sure that your interests are taken care of? Prepare your questions An interview is a ...

Creating example projects is a common way of showing your skills to potential employers. Let’s take a look at what’s important to keep in mind when building personal projects with an eye toward impressing prospective employers. Simplicity Building ap...

If you are a webpack user and have heard about esbuild speed, you may start questioning your js-bundler choices. Luckily, you don't have to drop your hand-crafted webpack config just now. Thanks to esbuild-loader, you can get part of the speed improvement without doing a whole migration.
For checking the esbuild-loader with a non-trivial amount of code, I created a repository. My code is minimal, src/index.js:
import { PDFDocument } from "pdf-lib";
const pdfButton = document.getElementById("pdf-button");
pdfButton.addEventListener("click", async () => {
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([350, 400]);
page.moveTo(110, 200);
page.drawText("Hello World!");
const pdfDataUri = await pdfDoc.saveAsBase64({ dataUri: true });
document.getElementById("pdf").src = pdfDataUri;
});
index.html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>esbuild-loader pdf-lib</title>
<link rel="shortcut icon" href="#" />
</head>
<body>
<button id="pdf-button">Generate pdf</button>
<br />
<iframe id="pdf" style="width: 350px; height: 600px"></iframe>
<script type="text/javascript" src="dist/main.js"></script>
</body>
</html>
and it does mainly 2 things:
pdf-lib - pure js pdf library, so our build has something to spend time onThis code is meant to be built with the default webpack configuration. If you checkout the webpack branch, the build will go more or less like this:
$ npm run build
> esbuild-loader-pdf-lib@1.0.0 build
> webpack --mode=production
asset main.js 413 KiB [compared for emit] [minimized] [big] (name: main) 1 related asset
orphan modules 936 KiB [orphan] 156 modules
runtime modules 663 bytes 3 modules
cacheable modules 1.12 MiB
modules by path ./node_modules/pako/lib/zlib/*.js 183 KiB 11 modules
modules by path ./node_modules/pako/lib/utils/*.js 7.56 KiB
./node_modules/pako/lib/utils/common.js 2.39 KiB [built] [code generated]
./node_modules/pako/lib/utils/strings.js 5.17 KiB [built] [code generated]
modules by path ./node_modules/pako/lib/*.js 22.9 KiB
./node_modules/pako/lib/deflate.js 10.8 KiB [built] [code generated]
./node_modules/pako/lib/inflate.js 12.1 KiB [built] [code generated]
./src/index.js + 155 modules 937 KiB [built] [code generated]
./node_modules/pako/index.js 347 bytes [built] [code generated]
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
main.js (413 KiB)
WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
main (413 KiB)
main.js
WARNING in webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
webpack 5.45.1 compiled with 3 warnings in 5983 ms
Key numbers to remember:
esbuild-loader provides 2 ways of using esbuild in webpack:
babel-loader or ts-loaderESBuildMinifyPlugin that we can use to replace the default terser pluginI haven't seen any improvements in my example repo by using the loader in my example repo - it even got a bit slower. Luckily, the minification improvements are interesting enough to recommend you to give it a try. You need webpack.config.js with:
const { ESBuildMinifyPlugin } = require("esbuild-loader");
module.exports = {
mode: "production",
optimization: {
minimizer: [
new ESBuildMinifyPlugin({
target: "es2015", // Syntax to compile to (see options below for possible values)
}),
],
},
};
install esbuild-loader with:
$ npm install --save-dev esbuild-loader
and your build will look like this:
$ npm run build
> esbuild-loader-pdf-lib@1.0.0 build
> webpack --mode=production
asset main.js 426 KiB [compared for emit] [minimized] [big] (name: main)
orphan modules 936 KiB [orphan] 156 modules
runtime modules 663 bytes 3 modules
cacheable modules 1.12 MiB
modules by path ./node_modules/pako/lib/zlib/*.js 183 KiB 11 modules
modules by path ./node_modules/pako/lib/utils/*.js 7.56 KiB
./node_modules/pako/lib/utils/common.js 2.39 KiB [built] [code generated]
./node_modules/pako/lib/utils/strings.js 5.17 KiB [built] [code generated]
modules by path ./node_modules/pako/lib/*.js 22.9 KiB
./node_modules/pako/lib/deflate.js 10.8 KiB [built] [code generated]
./node_modules/pako/lib/inflate.js 12.1 KiB [built] [code generated]
./src/index.js + 155 modules 937 KiB [built] [code generated]
./node_modules/pako/index.js 347 bytes [built] [code generated]
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
main.js (426 KiB)
WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
main (426 KiB)
main.js
WARNING in webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
webpack 5.45.1 compiled with 3 warnings in 1658 ms
Key values:
So we got our build time about 3 times lower, with a 3% increase in build size.
If you are interested in speeding up your build time but have no time for replacing the whole bundler & the setup, ESBuildMinifyPlugin from esbuild-loader can be a good way to achieve that.