Check out real world test implementation as a part of the @angular-extensions/model library which comes with built in schematics with full test coverage!

10. Build and publish custom schematics

Until now we have been building our schematics project using npm run build:watch which we added in the beginning.

Let’s stop that process and run npm rum build command instead Also let’s have a look into package.json file and change the name of the package to @schematics/hello and version to 1.0.0 . Besides that, we have to remove *.ts line from .npmignore file because it would exclude our template from the final package Now we could run npm publish but let’s run npm pack instead which will give us schematics-hello-1.0.0.tgz file which we can copy to some Angular CLI workspace project. Then, in the target Angular CLI workspace we can run npm i --no-save schematics-hello-1.0.0-tgz which will install our package into that project. The last step is to run schematics by referencing package name instead of the path to local schematics project. We can run ng g @schematics/hello:hello Tomas .

✔️ Notice that we don’ have to use --debug=false flag!

Boom that’s it, we have our first working custom Angular Schematics npm package!

11. Implement schematics as a part of library project

Previously we have been focusing on creating schematics as a stand alone npm package. This can be a great approach for a big collection of schematics dedicated for some project similarly to how @schematics/angular is the default standalone collection of Angular CLI.

On the other hand, it can also make sense to have inline smaller collection of schematics as a part of a library itself where it provides stuff specific to that library.

In that case we have to integrate the build of schematics next to the library itself. The exact implementation depends on whether we are implementing our lib as a part of Angular CLI workspace or a custom setup.

It the end it boils down to having separate tsconfig.schematics.json which compiles only the schematics project and a way to copy every other schematics asset to the schematics dist folder.

Assets can be copied using a library like cpx as a part of schematics build in npm scripts, for example something like this "schematics:build:copy": "cpx schematics/**/{collection.json,schema.json,files/**} dist/schematics" .

Real-life example of this setup can be seen in this package.json file and tsconfig.schematics.json file.

12. Add ng-add support

The ng-add is this cool thing that enables us to run ng add @angular/material instead of doing npm i @angular/material and then performing additional hundred manual setup steps (I am joking 😂, partially… 😬).

It’s extremely cool because it enables us (or consumers of our library) to get started in the matter of seconds instead of spending tens of minutes following some kind of documentation to be able to setup the library properly.

⚠️ As always, it depends… Some libs require little to none configuration to get started so they would not benefit much by implementing ng-add support…

Let’s say we have a library with some nontrivial setup. For example we may have implemented websocket based library for our organization and setup includes selection of connected services. Such a setup can be automated using ng-add .

The ng-add is a schematic that is implemented in a same way as any other schematic so all the steps we disused above are still valid! More so, ng-add schematics usually live side by side other supported schematics in the collection.

The only difference between ng-add and other schematics is that they get executed by calling ng add @my-org/schematics instead of ng g @my-org/schematics:ng-add .

The Angular CLI will npm install the mentioned package and execute the ng-add package automatically!

13. Add ng-update support

The ng-update enable us to automate work needed to upgrade to a next version of our library.

Let’s say we have an upcoming major version of our library with a breaking change to API of one of the main services. For example, the service API was 5 arguments but we want to change it to an options object.

Such a “mechanical” change should be possible to automate using some search and replace (or some more advanced AST manipulation).

🔧 I haven’t implemented any ng-update schematics yet so the following content is based solely on the reverse engineering of the @angular/material library…

First of all, the ng-update uses a special dedicated ng-update property in the package.json which references new migration.json file.

Add ng-update property to the package.json

The migration.json file then contains all the migration schematics per version…

Example of migration.json file content

Then the content of the index.ts file would follow in line of standard schematics implementation…

Check out real life example of ng-update implementation of @angular/material library.

We’re finally done, this shit was crazy! 🤪

I hope you enjoyed this epic ride and will now be able to implement and use tailor made Angular Schematics to make you and your team even more productive!

This is by far the longest and most complicated article I have ever written so your 👏👏👏 would be very appreciated to help it spread to a wider audience 🙏.

Also, don’t hesitate to ping me if you have any questions using the article responses or Twitter DMs @tomastrajan.