CLI tool
just-jeb/angular-builders avatar
just-jeb/angular-builders

angular-builders: custom webpack, esbuild and Jest for the Angular CLI

Angular build facade extensions (Jest and custom webpack configuration)

1,164 stars208 forksTypeScriptMIT

At a glance

What is it?
angular-builders collects the community maintained builders for the Angular build facade into one monorepo, with a package for custom webpack, a package for custom esbuild, a Jest builder so ng test runs Jest, a Bazel wrapper and a teaching example. The rule that governs everything else is that the major version of a builder must match the major version of Angular.
Who is it for?
angular-builders is the right choice for an Angular team that needs to modify the bundler configuration or swap the test runner without forking the CLI, and the schematics remove most of the upgrade pain. It is the wrong choice if you are on an Angular major older than the ones with published packages, or if you need a builder that is not one of these five.
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 received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

Editorial analysis

One repository, five packages

The stated purpose of the repository is to consolidate all the community builders for the Angular build facade, and the effect of that consolidation is that the pieces live together rather than scattered across separate repositories.

The packages directory holds five of them. The custom esbuild builders allow customizing the ESBuild configuration, and the custom webpack builders do the same for Webpack. The Jest builder allows running ng test with Jest, which is the one that most directly replaces part of the CLI's own behaviour. The Bazel builder is an ng wrapper for a Bazel build. The timestamp builder is described as an example builder taken from a Medium article on how the CLI's build layer works, and it exists to be read rather than used.

Each one is published under the same scope on npm, with a next tag alongside the stable version, so you can install a prerelease of the next major without changing the package name.

The examples directory mirrors the packages, with a folder for each of the five, and the root of the repository holds the shared Jest configuration files for the different roles: a common config, a unit test config, an end to end config and a custom environment file. That layout is a clue to how the packages relate to one another, since the Jest builder and the example workspace share the same config files.

The consolidation is what makes the versioning story work. When the builders are in one repository, they can be released together, and a team using two of them does not have to coordinate two upgrade cycles.

The major version rule is the first thing to get right

The alignment rule is stated three times in the readme, which tells you how often it is the source of trouble.

Builders and Angular major versions must match. The example given is that Angular 19 requires the packages at version 19.x, and Angular 20 requires version 20.x, and the readme names a mismatched version as the most common source of issues. The latest version of all the builders requires Angular CLI 22.

This is the same versioning scheme the Angular framework itself uses, where the major version of a library tracks the framework major, and it has a direct consequence for how you upgrade. Because builder majors track Angular majors, a project moving up several versions upgrades Angular first, and the builder is brought in line afterwards.

The reason the rule exists is worth spelling out, because it is not arbitrary policy. The Angular build facade is the layer between the CLI and the tool that actually does the work, and the builder implementations reach into the CLI's own internals to change how the build runs. When the CLI changes its internals between majors, a builder written for the previous major has to change with it. The major version is the signal that says whether the builder has been adapted.

The practical consequence is that you cannot install the newest builder into an older application, and you should not try. If your project is on an Angular major that predates the current one, you need the matching major of the builder, and the repository keeps those older lines on separate branches.

Schematics handle the setup and the upgrade

Three of the packages ship Angular schematics, and the readme explains exactly what that buys you.

The custom esbuild, custom webpack and jest packages have schematics, so both the initial setup and the move between majors are automated:

sh
ng add @angular-builders/<package>
ng update @angular-builders/<package>

The add command sets the builder up in your workspace. The update command moves an existing project to a new major, and the readme explains the mechanism: it applies every migration between the version you have installed and the one you are moving to, so the builder's own migrations all run in one pass rather than one at a time.

There is a version floor on that, and it is worth knowing. Updating from version 17 or later is supported, so a project that is far behind has to make the jump manually before it can use the automated path. The readme also says that each package README documents what its schematics change for you and, importantly, which changes they can only warn about. That distinction is the honest bit: some migrations are code changes a schematic can apply, and others are decisions a human has to make, and the package documentation says which is which.

The Bazel and timestamp packages have no schematics, so those two are still configured by hand. That is not an oversight but a consequence of being outside the normal builder flow.

A separate migration guide is linked for the details, and the versioning notes are repeated per branch, which is how a reader on an old major gets the rules that applied at the time.

What each builder is actually for

The two customisation packages solve the same problem against different bundlers, and the reason to use them is that the CLI does not expose every option of either tool.

The custom webpack builders let you extend the Webpack configuration that the Angular CLI generates, and the custom esbuild builders do the same for the ESBuild configuration the CLI uses when a project is on the esbuild application builder. The mechanism is the Architect layer: a builder is a class the CLI invokes with a set of options, and by wrapping or replacing the default builder you can supply your own configuration. The repository links an article that teaches the layer by building a builder from scratch, and it says plainly that the article explains the mechanism while the setup instructions live in the package readmes.

The Jest builder is the one with the clearest effect on a team's day to day work. It lets ng test run Jest, which means the familiar command still works, and the repository's own shared Jest configuration files, split into a common config, a unit test config and an end to end config, show the shape of a setup that is expected to be more involved than the CLI's built in runner.

The Bazel builder is an ng wrapper for a Bazel build, so you can drive Bazel through the CLI's own commands, and the timestamp builder is the smallest of the set, an example that exists so you can read a complete builder implementation.

The topic list shows the range the project has covered, with entries for Angular 15 through 18, for the dev server, for the Ivy compilation pipeline, and for unit testing.

One branch per major, kept for the long term

The repository keeps a branch for every supported major version, and the list is long enough to be a signal about the project's commitment.

There are branches named for versions 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8 and 7, each with its own patch suffix. The readme lists them under a heading for previous versions, so the current major lives on the default branch and everything older is on its own line.

That is a maintenance commitment with a cost, and the repository is honest enough to name the cost. There is a MAINTENANCE.md file at the root, separate from the readme, which suggests the policy of who maintains which branch and for how long is written down somewhere rather than assumed.

The alternative would be to drop old branches and tell people to upgrade, which is simpler but pushes the cost onto every user of an older Angular. The fact that the branches still exist, going back to version 7, is the clearest evidence of how the project is run.

The other thing worth noticing is that the tagged release history in the repository metadata looks old, with the newest listed tag at 7.2.0 from 2019, while the readme describes builders that require Angular CLI 22. The gap between those two facts is a documentation artefact rather than a project state, but it does mean you should read the branch list and the package readmes rather than the tag list to work out what is current.

The monorepo tooling behind the packages

The root package.json describes a Yarn workspaces monorepo managed with Lerna and Turborepo, and the scripts tell you how a release is put together.

The workspaces cover the packages directory and several of the example workspaces, so the examples are part of the same dependency graph as the packages and are built and tested with them. The build script filters to the packages that changed against the origin master branch, which is the standard incremental approach, with a separate script to build everything.

The release path is conventional commits, with a commitlint configuration and a conventional config in the dev dependencies, and the publish script runs a conventional graduate publish through Lerna. Formatting is Prettier, there is a Husky directory with a prepare script that installs the hooks, and there is a Renovate configuration for dependency updates.

Two details are worth flagging for anyone running this locally. The Node engine requirement is explicit, listing version 20.19 or 22.12 or anything from 24 upwards, which is a stricter floor than many projects state and will fail loudly on an older Node. And the repository uses Yarn with a Yarn release configuration and a lock file, so the toolchain assumes Yarn rather than npm or pnpm for the workspace scripts.

The test tooling is Vitest with coverage, and there are local test scripts under a scripts directory, alongside a merge helper for the schematic sources, which is what lets one schematic definition be shared between packages.

Editorial conclusion

angular-builders is the right choice for an Angular team that needs to modify the bundler configuration or swap the test runner without forking the CLI, and the schematics remove most of the upgrade pain. It is the wrong choice if you are on an Angular major older than the ones with published packages, or if you need a builder that is not one of these five. Before you adopt it, confirm that the builder major you would install matches your Angular major exactly, and read the package README for the builder you want, since each one documents which changes its schematics can make and which they can only warn about.

Frequently asked questions

How do I install an angular-builders package?

Use ng add @angular-builders/<package> to set the builder up in your workspace. The custom esbuild, custom webpack and jest packages ship schematics that automate the setup, while the bazel and timestamp packages have no schematics and are configured by hand.

Which version of angular-builders should I use with my Angular version?

The major versions must match. Angular 19 requires @angular-builders packages at 19.x and Angular 20 requires 20.x, and the readme names a mismatched version as the most common source of issues. The latest version of all the builders requires Angular CLI 22.

How do I upgrade a builder to a new Angular major?

Run ng update @angular-builders/<package>, which applies every migration between the version you have installed and the one you are moving to, so the builder's own migrations all run in one pass. Updating from version 17 or later is supported, and each package README documents which changes its schematics can apply and which they can only warn about.

What is the timestamp builder in angular-builders for?

It is an example builder taken from a Medium article on the Angular CLI build layer, and it exists to be read as a complete builder implementation. The Bazel builder, by contrast, is a working ng wrapper for a Bazel build.

Official sources

  1. Issues
  2. just-jeb/angular-builders on GitHub
  3. License: MIT
  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/just-jeb-angular-builders.svg)](https://hysenlabs.com/projects/just-jeb-angular-builders)

Was this useful?