Multi-language Monorepo with Bazel
In this post
This post will discuss how to keep a mono repo with projects written in multiple languages using Bazel as the common build tool for all four. The languages are:
- Go
- Typescript
- Javascript
- PostCSS
I chose these three languages because they are what I’m most familiar with. I also chose to make a distinction between Javascript and Typescript since they require different toolchains and are written differently.
I chose Bazel because it allows developers to use a single tool across a variety of languages.
Bazel has specific characteristics that I find appealing:
- Reproducibility
- Bazel produces pure functional builds where your output files are strictly dependent on your inputs. This gives two important characteristics to your builds.
- Your builds are hermetic, which means only the inputs that you explicitly mention are readable by your build steps.
- Your builds are reproducible. If you’re using a constant set of inputs, Bazel will produce the same build each time.
- Scalability
- Bazel’s invention arose from one of Google’s internal build tools, Blaze. Within Google itself, Bazel handles builds for projects containing more than 100K source files
- While it advocates the monorepo pattern, it handles microservices architecture just as easily. Dropbox used Bazel to scale their CI/CD pipelines to mitigate the number of tests executed on their commits. Uber also adopted Bazel to scale their Go monorepo. They leveraged Bazel’s hermetic builds to support incremental build generation that supports their distributed infrastructure.
- Declarative programming
- Writing build configurations for projects should be as simple as possible. Bazel is built using Starlark, a high-level language derived from Python. Thus it gives developers a more convenient way to write build configurations and properties that are easily readable. Additionally, the abstraction in Bazel saves developers from dealing with complicated stuff like compilers and linkers.
Parallelism and caching: Build tools at scale have to be high performant. Bazel speeds up your builds using a caching mechanism. It intelligently compares your subsequent builds with your previous cached builds and only builds those files which the developers updated. This ensures that Bazel only spends your CPU resources on building those pieces of your project that need to be re-built. Bazel also allows you to generate concurrent builds in a parallel fashion to save time across your distributed codebase. You can generate parallel builds on both a single machine as well as across multiple machines remotely.
Building a project with Bazel
Backend in Go
https://medium.com/@simontoth/golang-with-bazel-2b5310d4ce48
https://bazel-contrib.github.io/SIG-rules-authors/go-tutorial.html
Cross-compiling Go to WASM
Front-end in Javascript
https://github.com/aspect-build/rules_js
https://github.com/aspect-build/rules_ts
https://github.com/aspect-build/rules_rollup
https://github.com/aspect-build/rules_terser
https://github.com/aspect-build/rules_jest
Styling: PostCSS
https://github.com/bazelbuild/rules_postcss
Extending Bazel
https://github.com/bazelbuild/starlark/
