Open-source project
privatenumber/esbuild-loader avatar
privatenumber/esbuild-loader

esbuild-loader: replacing babel-loader and ts-loader inside an existing Webpack config

💠 Speed up your Webpack with esbuild ⚡️

3,601 stars102 forksTypeScriptMIT

At a glance

What is it?
esbuild-loader swaps Webpack's slowest loaders for esbuild's Go-based transforms while leaving the rest of the build alone. It is a targeted speed fix, not a bundler migration, and it does not type check.
Who is it for?
Adopt esbuild-loader if you have a working Webpack build and the transpile and minify stages dominate your build time; the install is one dev dependency and the config change is a rule swap. Do not adopt it if your build depends on Babel plugins, emitDecoratorMetadata, or type-aware transforms, because esbuild supports only a subset of tsconfig options and does not type check.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The build-time problem esbuild-loader targets

Most Webpack configurations spend their wall-clock time in two places: transpiling every module through babel-loader or ts-loader, and minifying the resulting bundle with Terser. Both are JavaScript programs doing per-file work, and both sit on the critical path of every build and every rebuild during watch mode. esbuild-loader exists to replace those two stages with esbuild, a JavaScript bundler written in Go, while leaving Webpack's module graph, plugin ecosystem and code-splitting behaviour untouched. The README frames the project exactly that way: it offers faster alternatives for transpilation (babel-loader, ts-loader) and for minification (Terser). The audience is therefore narrow and specific. It is for teams with a large existing Webpack build who cannot or will not migrate to a different bundler, but who are tired of waiting on the transform stage. If you are starting a project from scratch, nothing here argues for choosing Webpack first.

How the loader sits inside Webpack's module pipeline

esbuild-loader is a Webpack loader, not a plugin and not a bundler. Webpack still walks the dependency graph, resolves imports and emits chunks; the loader only receives the source of a matched file and returns transformed code. Because it is a loader, it composes with everything else in your rules array, which is why the README's setup instructions are a diff rather than a new config file: you delete the babel-loader and ts-loader rules and add one rule matching /\.[jt]sx?$/. The loader picks a syntax mode from the file extension, so .js is treated as JS with no JSX allowed, .jsx as JSX, .ts as TS with no TSX allowed, and .tsx as TSX. That automatic mapping is convenient but it is also the first place people get surprised, which is why the loader option exists to override it. On the TypeScript side, the loader looks for tsconfig.json automatically, and get-tsconfig is used behind the scenes to load it and resolve the extends property. The tsconfigRaw option accepts a raw object instead, but the README notes it will not resolve extends. The package declares webpack ^4.40.0 || ^5.0.0 as a peer dependency, so both major versions are in scope.

Installing esbuild-loader and getting a first build to pass

The README gives a single install command, and the package ships as a dev dependency. Run it at the root of the project that already has Webpack configured.

bash
npm i -D esbuild-loader

The next step is editing webpack.config.js. The README presents this as a diff: remove the existing babel-loader and ts-loader rules, then add one rule for esbuild-loader. The target option controls which JavaScript version the output is compiled to, and the README's example uses es2015.

js
module.exports = {
    module: {
        rules: [
            {
                test: /\.[jt]sx?$/,
                loader: 'esbuild-loader',
                options: {
                    target: 'es2015'
                }
            }
        ]
    }
}

After the rule is in place, the loader decides how to parse each file from its extension. If you need JSX inside plain .js files, the README shows the loader option set to 'jsx' on a .js rule. If your tsconfig lives under a non-standard name, the tsconfig option takes a path, for example './tsconfig.custom.json'. The README does not document a rollback procedure, so keep the removed loader rules in version control before you delete them.

The TypeScript caveats are the real cost of the swap

esbuild does not type check your code. The README states this plainly and links to the esbuild FAQ, which says type checking will not be supported and that you should run tsc separately. That single fact changes the shape of a TypeScript project's CI: you still need tsc --noEmit somewhere, and if you were relying on ts-loader to fail the build on a type error, that failure now moves to a different step that someone has to wire up. The README suggests IDEs such as VSCode or WebStorm as one alternative for type checking, which is a development-time answer rather than a CI answer. The second constraint is narrower but sharper: esbuild supports only a subset of tsconfig options, and the README points at the TransformOptions interface for the list. Features that require type interpretation, including emitDecoratorMetadata and declaration emit, are not supported. The README also recommends enabling isolatedModules to avoid mis-compilation when re-exporting types, and esModuleInterop to keep TypeScript's type system compatible with ESM imports. Those are not optional niceties; they are the conditions under which the transform is safe.

target, tsconfig paths and what the loader cannot do for Webpack

The target option defaults to esnext, which means no transpilation happens at all. That default is easy to misread. If you drop esbuild-loader in and set nothing, you get the fastest possible transform and output that assumes a modern engine. Setting target to es2015, as the README's example does, brings back the transpilation work and, as the README warns, can bloat your output code the same way Babel does. So the speed you gain is partly a function of how old a target you need. The loader's scope is also strictly transform-only. tsconfig.json paths are not resolved by esbuild-loader, because it cannot aid Webpack with resolving paths; the README directs you to tsconfig-paths-webpack-plugin for that. This is a clean division of responsibility, but it means a migration from ts-loader is not purely a rule swap if your project uses path aliases. You will be adding a plugin as well.

esbuild-loader versus swc-loader and versus dropping Webpack

Two comparisons matter. The first is swc-loader, which occupies the same slot: a fast Rust-based transform replacing babel-loader inside Webpack. The practical difference is the surrounding ecosystem rather than the loader API. esbuild-loader is a thin wrapper over esbuild, so its supported syntax and its tsconfig subset track esbuild's own TransformOptions, and the caveats you inherit are esbuild's caveats. Choosing between them is largely a question of which transform's limitations you can live with. The second comparison is the one the README's own tip gestures at: esbuild is a bundler in its own right, and projects sometimes skip the loader entirely and let esbuild do the bundling. That is a different project with a different plugin ecosystem and a different set of unsupported Webpack features. esbuild-loader's whole value proposition is that it does not ask you to make that decision. It keeps Webpack's graph and swaps the slow part. If Webpack's plugin ecosystem is not something you depend on, the loader is the wrong tool and a direct esbuild build is the shorter path.

Maintenance, licence and the upgrade surface

The repository is not archived and the last push was on 2026-09-21. Recent releases are v4.5.0 on 2026-06-15, v4.4.3 on 2026-04-02 and v4.4.2 on 2025-12-29. The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained; that is a statement about the licence text, not legal advice, and your organisation's own review process decides what it means for you. The upgrade surface is small and worth understanding before you adopt. The package has four runtime dependencies: esbuild, get-tsconfig, loader-utils and webpack-sources. Because esbuild-loader is a thin wrapper, a new esbuild release can change which syntax and which tsconfig options are supported, and that is the change most likely to reach you through a minor version bump. The peer dependency range covers webpack 4 and 5, so a Webpack major upgrade does not by itself force a loader upgrade. The README does not document a rollback path, so if a new esbuild changes transform output in a way you dislike, your fallback is pinning the version rather than a documented downgrade procedure.

Editorial conclusion

Adopt esbuild-loader if you have a working Webpack build and the transpile and minify stages dominate your build time; the install is one dev dependency and the config change is a rule swap. Do not adopt it if your build depends on Babel plugins, emitDecoratorMetadata, or type-aware transforms, because esbuild supports only a subset of tsconfig options and does not type check. Before you commit, verify two things: that your tsconfig has isolatedModules and esModuleInterop enabled, and that the target value you set matches the oldest engine you actually ship to.

Frequently asked questions

What is esbuild-loader and what does it replace?

esbuild-loader is a Webpack loader that uses esbuild to transform JavaScript and TypeScript. The README positions it as a faster alternative to babel-loader and ts-loader for transpilation, and to Terser for minification.

Does esbuild-loader type check my TypeScript?

No. The README states that esbuild does not type check your code, and that according to the esbuild FAQ it will not be supported. The README suggests running tsc separately or relying on an IDE such as VSCode or WebStorm.

How do I install esbuild-loader?

The README gives one command, npm i -D esbuild-loader, followed by adding a rule for esbuild-loader to webpack.config.js and removing the babel-loader or ts-loader rules you were using before.

What does the esbuild-loader target option do?

It sets the JavaScript version to compile to. The README notes the default is esnext, which means no transpilations are performed, and shows target: 'es2015' for engines that only support ES2015.

Can esbuild-loader resolve tsconfig paths?

No. The README says esbuild-loader only transforms code and cannot aid Webpack with resolving paths, and it directs you to tsconfig-paths-webpack-plugin for tsconfig.json paths support.

Official sources

  1. Issues
  2. License: MIT
  3. privatenumber/esbuild-loader on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/privatenumber-esbuild-loader.svg)](https://hysenlabs.com/projects/privatenumber-esbuild-loader)