Nx: builder: how to write custom builder within nx / provide schematics

Created on 17 Dec 2019  路  8Comments  路  Source: nrwl/nx

Current Behaviour

So I was trying to build custom builder by following angular-devkit docs.

In the end, I was able to run it, but it didn't work.

Error
image

The process required "a lot" of overhead from developer perspective:

  • need to manually create all the boilerplate
  • need to compile builder on your own
  • need to create npm package and use yarn link and friends

Expected Behaviour/Feature Request

  1. provide docs how to author custom builder within nx workspace

  2. provide tooling

  3. provide have schematic for booting custom builders (we have nx g @nrwl/workspace:workspace-schematic, so something like nx g @nrwl/workspace:workspace-builder)
  4. allow custom workspace builder to be used as targets without all that manual churn that is needed at the moment

thx a lot !

misc feature

Most helpful comment

Hello,
this is probably more an issue on the Angular side, as they just don't have official support for TS schematics (and builders) to run directly yet. See https://github.com/angular/angular-cli/issues/13858.

I had the same pain and I want to share how we approach it currently for our project where we have various builders and schematics which we use on a regular basis locally and on the CI. In the beginning we searched for a "elegant" solution, then quickly decided for the pragmatic way to get things done. We use that solution every day since then.

  1. Create the builder as a library package as I don't want to use the nx tools/ folder for our shared packages.
  2. Create an entry for the builder in your angular.json/workspace.json so you can build it anytime (yarn nx build @builders/builder-a)
  3. Ensure that you build it whenever you install your workspace. That way you always have a working artifact sitting in your workspace you can point to. This works locally for developers but also on the CI/CD. In your package.json we have a part to ensure the builders are compiled. We use npm-run-all for the wildcard support.
"postinstall": "run-s postinstall:*",
"postinstall:builder-a": "yarn nx build @builders/builder-a",
"postinstall:builder-b": "yarn nx build @builders/builder-b",
"postinstall:builder-c": "yarn nx build @builders/builder-c",

The builder artifacts will be written to build/libs/builders/builder-a and so on.

  1. You can now start using it. Refer to the artifact via "builder": "./build/libs/builders/builder-a in your target configuration in angular.json, wherever you want to use the builder

  2. You are currently developing the builder? We have a yarn nx develop @builders/builder-a target which will output the latest artifacts into build/libs/builders/builder-a whenever we change code (through a custom nodemon watch task). Works flawless for schematics & builders for us, especially if you use jest for a test driven approach, as you can run the schematics within jest without even building it as jest compiles the typescript.

As said, this is a limitation by Angular. Maybe we can extend the Nx Documentation to guide people properly or craft a schematic to support the creation of the various parts. I'm sure there is some smart person who can provide a solution to run the builders directly with ts-node some day, but until then the outlined solution is a good start that works without any problems for us. I hope this helps a few folks 馃檹

All 8 comments

Hi, thought this could be interesting here:
https://github.com/just-jeb/angular-builders

Best,
Michael

Hi, sorry about this.

This was mislabeled as stale. We are testing ways to mark _not reproducible_ issues as stale so that we can focus on actionable items but our initial experiment was too broad and unintentionally labeled this issue as stale.

btw I wish it could be easier to debug, I attempted to add the trace in https://github.com/angular/angular-cli/pull/17341 although it was rejected.

You can debug it, you just need to follow the code a bit because it does not run directly but through a forked child process.

Each time you run nx it will use @nrwl/cli to execute the code with some pre processing to the command line input.

For example, running:

nx build my-app --buildLibsFromSource

Will actually run the following in a child process:

./node_modules/@nrwl/cli/lib/run-cli.js run my-app:build --buildLibsFromSource=true

So you can easily go into debug mode:

node --inspect-brk ./node_modules/@nrwl/cli/lib/run-cli.js run my-app:build --buildLibsFromSource=true

If you're using VSCode, just turn on auto attach and your debugger will automatically popup on the first instruction

I created a video on debugging Nx with VSCode. Also, in VSCode you can set the breakpoint, then open the JavaScript Debugger Terminal & then execute the command to debug.

image

That should even follow child processes properly

The Nx docs provide a bit of documentation here to create custom builders within a workspace.
Is there a simple way to avoid having to compile the builder manually before using it? I would like to be able to to use all my custom builders at any time without the requirement to run any kind of script upfront.

A schematic for a workspace builder would be really nice.

Hello,
this is probably more an issue on the Angular side, as they just don't have official support for TS schematics (and builders) to run directly yet. See https://github.com/angular/angular-cli/issues/13858.

I had the same pain and I want to share how we approach it currently for our project where we have various builders and schematics which we use on a regular basis locally and on the CI. In the beginning we searched for a "elegant" solution, then quickly decided for the pragmatic way to get things done. We use that solution every day since then.

  1. Create the builder as a library package as I don't want to use the nx tools/ folder for our shared packages.
  2. Create an entry for the builder in your angular.json/workspace.json so you can build it anytime (yarn nx build @builders/builder-a)
  3. Ensure that you build it whenever you install your workspace. That way you always have a working artifact sitting in your workspace you can point to. This works locally for developers but also on the CI/CD. In your package.json we have a part to ensure the builders are compiled. We use npm-run-all for the wildcard support.
"postinstall": "run-s postinstall:*",
"postinstall:builder-a": "yarn nx build @builders/builder-a",
"postinstall:builder-b": "yarn nx build @builders/builder-b",
"postinstall:builder-c": "yarn nx build @builders/builder-c",

The builder artifacts will be written to build/libs/builders/builder-a and so on.

  1. You can now start using it. Refer to the artifact via "builder": "./build/libs/builders/builder-a in your target configuration in angular.json, wherever you want to use the builder

  2. You are currently developing the builder? We have a yarn nx develop @builders/builder-a target which will output the latest artifacts into build/libs/builders/builder-a whenever we change code (through a custom nodemon watch task). Works flawless for schematics & builders for us, especially if you use jest for a test driven approach, as you can run the schematics within jest without even building it as jest compiles the typescript.

As said, this is a limitation by Angular. Maybe we can extend the Nx Documentation to guide people properly or craft a schematic to support the creation of the various parts. I'm sure there is some smart person who can provide a solution to run the builders directly with ts-node some day, but until then the outlined solution is a good start that works without any problems for us. I hope this helps a few folks 馃檹

Thank you so much for sharing. I think this gets the job done for now 馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danieldanielecki picture danieldanielecki  路  3Comments

about-code picture about-code  路  3Comments

markphip picture markphip  路  3Comments

zpydee picture zpydee  路  3Comments

jon301 picture jon301  路  3Comments