Schematics is one of Angular’s strongest tools, for quickly generating boilerplates and maintaining code standards. Unfortunately, it can be hard to create and use schematics. In this article, I will demonstrate my way of developing and using schematics while mainly focus on how to integrate and debug it as part of our application’s project and quickly gain some of schematics strong benefits.

Before we start, for those who want to learn more deeply about schematics I recommend you to read Effective automated scaffolding with Angular Schematics by Natalia Venditto

Table of content:

How to create & debug a schematics command.

How to install & use our schematics.

Expand and benefit from external schematics.

How to test our schematics.

Create Our First Schematics Command

Before we start, in order to create a schematics project, we should install the schematics CLI:

npm install -g @angular-devkit/schematics-cli

Now, we can use the CLI and simply generate new schematics for our project:

schematics blank my-project-schematics

This command created a blank schematics project under the folder “my-project-schematics”.

Now we are good to go to create our first schematics.

Let’s start with creating a simple and plain schematics “hello world” generation command. We do that by defining the command’s definition in a file called collection.json

As you might notice, our definition contains two reference entries: the factory file which will be used as an entry point for our schematics command, and the schema file which defines our command details and properties, and used by IDEs for details and auto-completion.

Let’s begin with defining our schema:

Now the factory file:

So far so good, we now have our first generate command! So let’s try and run our command.

For that, add the following command to the scripts in the main `package.json` file:

"schematics:watch": "cd ./my-project-schematics/ && npm link && cd .. && npm link my-project-schematics && npm run build --prefix ./my-project-schematics -- --watch"

This command creates a symlink to our project’s node_modules folder then sets the build step to run in watch mode so that it will automatically rebuild as we make changes.

Now we are ready and should be able to generate our hello command. Let’s run ng generate my-project-schematics:hello Itay

Tip: we can set our schematics as the default schematics in the angular.json ,so we won’t have to specify the schematics name every time we use it.

After we tested our new generated command is working, let’s continue to develop it so it generates an hello.md file.

To do so, under our command folder, we add files/hello.md file:

Hello From <%= name %>!

And now in index.ts we can process this file and complete our command.

Now, if we run again ng generate my-project-schematics:hello Itay we should have the hello.md file generated.

Install and Use Our Schematics

We achieved our first command! We will now learn how to install it in our project so that every team member will be able to use it.

First, we need to add another script to the package.json :

"schematics:install": "npm run build --prefix ./my-project-schematics && npm i ./my-project-schematics"

Now, in order to make sure that everyone who installs our project will also get our schematics, we can use npm’s postinstall hook and run our install script.

Under scripts section we add:

"postinstall": "npm run schematics:install"

Now each time someone installs our dependencies, our script will run and automatically install our schematics.

Use External Schematics

So far, we have created a basic schematics example. Now let’s extend it and see how we can quickly gain some more of its benefits.

In this example, we will use the schematics from NgRx combined with Angular’s schematics in order to create a complete feature command.

First, install @ngrx/schematics & @schematics/angular to our schematics project:

npm i @ngrx/schematics @schematics/angular --save

So now, we are all set to start writing our feature command.

We will use another great feature of schematics that allows us to extend another schematics project - externalSchematic .

As before, add the feature command’s definition in the collection.json :

Now in ./feature/index file, we can combine Angular’s and NgRx’s external commands to create our complete feature command.

Now, after running the command ng generate feature my-feature we should expect the following files to be generated:

Tip: you can add an extend property to the collection.json file which will add our schematics other schematics commands: “extends”: [“@ngrx/schematics”] .

So now, every time we want to use commands from external schematics we won’t need to specify the schematics name.

Bonus Testing With Jest

As you might notice the schematics project had been already generated with a testing infrastructure and Jasmine as a testing tool.

Personally, I would recommend you to use Jest in this case mostly because of jest’s snapshots which allow us to easily write and update our tests while gaining the ability to instantly see schematic’s result.

Before you use Jest, and to learn more about it, I highly recommend for you to read “Integrate Jest into an Angular application and library” blog, written by Tim Deschryver.

Now, in order to test our feature, we will first need to create a setup which will generate a workspace in each test and give us the infrastructure we need for our feature. We create a utils/workspace.ts file.

And now to our feature test:

For the setup, we will use SchematicTestRunner from @angular-devkit/schematics/testing which will allow us to mock a schematics command, and also our createWorkspace that will create the tree object we need for our command infrastructure.

Finally, for the test, we will run our command using the SchematicTestRunner and then we will use the result to simply read the content of our command, and expect it will match our snapshot.

Summary

We learned how to develop a schematics project and install it within our project. we used one of schematic’s cool features (external schematics) and used it to reduce our boilerplates by creating a feature command.

Finally, we learned a quick and efficient way to test our schematics, using jest and set up a workspace for our tests.