I just moved the ts-api-guardian library into the Angular repository. For this post, it’s not important what the library does (though TypeScript library projects should definitely check it out), but I realized it’s a nice demonstration of how Bazel solves the problem of publishing more than one package from a repo, similar to what Lerna does.
https://github.com/angular/angular/tree/master/tools/ts-api-guardian is the new home for this package, and it is used in two different ways:
- within the monorepo, it’s just another Bazel package with some targets and an index.bzl file that defines a Bazel rule for using it.
- it has an
npm_packagerule which means it can be published to npm.
I’ll quickly illustrate both of these.
Within the monorepo
Since ts-api-guardian is built with Bazel, and so is Angular, it’s easy for us to use the library directly at head, with no release step. Just make any change under
tools/ts-api-guardian and re-run the
//tools/public_api_guard:core_api_test. The new behavior of the library is already live, and governs how the public API of
@angular/core should look to users.
This has another benefit. The last change I reviewed to
ts-api-guardian turned out to be breaking for users — I manually published and integrated it with Angular before merging the PR and discovered it would drastically change the enforcement of Angular’s public API. If I hadn’t taken that extra step, we would have only discovered that problem after releasing the library. However the next time someone proposes a change, it will naturally run Angular’s public API tests in the PR review as an extra validation that the library works for a downstream consumer.
Note that if
bazel test //tools/public_api_guard:all fails, each failing test prints a handy command like
bazel run //tools/public_api_guard:core_api_test.accept which accepts the new golden file into the project. (The
.accept variant is provided by the
Perhaps there are some users of
ts-api-guardian who use Bazel, and aren’t in the Angular monorepo — they can add a dependency to their
WORKSPACE file to build it from head and consume it the same way Angular does. But this is probably uncommon today.
The common use case is to publish the library to npm. This is made easy because of the
npm_package rule at
//tools/ts-api-guardian. Building this target produces the directory that would be published to npm. But it can be one step easier, because another variant of this target is provided with the
.publish suffix. That means we can just
bazel run //tools/ts-api-guardian:ts-api-guardian.publish to do the whole thing.
Even better, you can do all of this without installing
npm on your machine, because Bazel is a multi-language build tool and understands the runtimes needed for all the languages it supports.
I hope that’s useful for someone!