Automate your team’s boilerplates by building your own schematics
Create and integrate your own project’s schematics, and gain its strong benefits quickly and effortlessly.
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.
Special thanks to Tim Deschryver & Noa Barki for the review 🙏🙏
All code samples used in this piece are available in this repository.