It may look like the follow…
1. Choose one of NPM or Yarn
2. Choose one of Webpack or Rollup
3. Choose plugins that work with #2
4. Choose additional dependencies and patterns for iterative development
5. Choose Lerna to manage many packages
The adventure was fun and exciting through steps 1, 2, and some of 3, but then it took a dark turn. The choice became, write a new plugin or go back to 2(maybe?)!
The problem can be summarized as the following…
Yarn, NPM, Rollup, Webpack, et al fail to track dependencies and force sloppy chaining of plugins and scripts to accomplish something that should be much more transparent.
I want to know exactly how each plugin or script transforms the input. The pattern of passing the source into a bag of plugins was not going to work for me. And frankly, I don’t care to know how Rollup internals work or the best way to run scripts in my package.json in parallel.
A Deterministic, Cached Adventure
name = "app",
srcs = [":index.js"],
entry_point = "index.js",
config_file = "//:rollup.config.js",
format = "iife",
name = "transpiled",
args = [
data = [
outs = ["transpiled.js"],
That may seem much more verbose and there is definitely a different kind of magic.
In my opinion it is worth it because the next step is…
a custom string replacement or
an addition of a license header
a branch of this chain of transformations
a million different possibilities.
Whatever the case might be, Bazel knows what to build and only builds what is necessary. I can call
bazel build :app.js or
bazel build :transpiled.js. It doesn’t care how I get from step A to B so long as it is deterministic.
- Want to replace some strings with sed? Write a simple genrule.
- Want to use another node cli tool? rules_nodejs has wrapped it into a Bazel binary and rule automatically.
- Want to change just one transformation? Bazel will have cached all of the dependencies already.
For example, I wrote a simple macro calling prettier that I can use anywhere in my project and with this I can call
bazel build :pretty.html.
src = ":index.html",
out = "pretty.html",
This book is still a difficult read and partially because of the below:
- Bazel is very strict about it’s sandbox for good reason.
- Bazel expects a new output for every rule.
- Many node tools work over directories and edit in place.
- rules_nodejs does not document all of its functionality well.