Angular Schematics — Going a bit more in depth

Hello all! If you ended up here chances are you probably ran through the scarce amount of blogs that talk about schematics. It is also probably true that you may have found them very helpful(as did I) BUT maybe they are “out of date” at this point in time or maybe it is just a tad bit basic and you need maybe some other examples. I’m here to reiterate on those “basics” on how I accomplished them today(which is mostly the same) and add a couple more complex examples that I encountered while stumbling/struggling through schematics. I’ll also share the materials that helped me learn schematics better at the bottom of this post. Think of this post as a hub to get all your schematics knowledge.

First off.. I have yet to really find any documentation ANYWHERE.. and to be honest those few blog posts I mentioned earlier were my saving grace to just getting me somewhat familiar of what the basics are. If I wanted to go beyond those blog posts I had to go through the source code of schematics of Angular and Nrwl. Lets be honest though, I am far from knowing everything about schematics and I am here to just share what I have tried and succeeded with so if there are better ways of doing things please share with me in the comments below!

Let’s get started

Before we can take advantage of creating our first schematics we’ll need the schematics cli

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

Great, now this will allow us to scaffold our first schematic. Lets look at what option we have here.

Option 1

schematics schematic --name=my-schematic

Option 2

schematics blank --name=my-schematic

Most places will tell you to just do Option 2 but theres a whole other option that actually has comments that kind of help explain whats going on.

If you’re interested in where the code for these two options are check the link below.

For this article we will be sticking to Option 2 but I wanted to make you aware of Option 1 because it’s probably as close to documentation as you will get at the moment and it has examples of more complex scenarios.

Okay lets dive into what has been created after running Option 2

# reminder of commands to run
schematics blank --name=my-schematic
cd my-schematic

You should end up with something like the above. Great.. what do these files mean?

  1. collection.json- This will be the list of all the available schematics you are offering. You should only see one at this point named my-schematic. To use an example the Angular CLI has a number of schematics such as component, directive, and service. Those would all go in the file specifically under the schematics node. The factory field points to a javascript function that the schematic will use. Here it is pointing to the function mySchematic in index.ts.
    Note: The $schema key points to the JSON Schema defining this format. It is used by IDEs to do auto completion, tools for validation, and is entirely optional. (taken from this post)
  2. index.ts- This is the meat and potatoes of your schematic. All your instructions will go in here as you will see shortly.
  3. index_spec.ts — This is where your unit tests will go for your schematic. We will not be covering that in the article.

Notes: As of this post the latest cli will put these in your package.json. Make sure you versions match these or are later because you will find that you will not have access to certain utilities I use in the post

"@angular-devkit/core": "^0.8.5",
"@angular-devkit/schematics": "^0.8.6",
"@schematics/angular": "^7.0.2",

Before we go any further I would recommend you just read this blog post since it explains terminology far better than I can. Head on back once you’re done! You can view the blog by clicking here.

Okay I am hoping you read that blog post because I am just going to truck forward into some examples I have yet to see examples of online.

Scenario 1 — modify package json dependencies

You’re on a team with many devs and its often that many of you have to spin up a brand new Angular application. However, 99% of the time you need the exact same dependencies and you find yourself referencing old projects and copying and pasting package.json. Or really.. you’re a lone wolf and you have your go to packages you use for most of your work. Sound familiar?

Lets automate that boring step of copying pasting dependencies with schematics and ensure that you and your team hit the ground running.

Check out the gists below.

Okay.. what the hell is this you’re thinking right? Lets dive in.

Line 24: mySchematic is the function that drives this whole operation. Remember its being referenced in collections.json?

Now, if you didn’t read the blog I just told you to you will have no idea what chain is or does. Scroll up and read it if you don’t.

In our chain we will call a method named addDependencies that returns a Rule that will modify our Tree. As you can guess from the name of the function the purpose of this method is to add dependencies to package.json.

Line 12: you will see the code loop over dependencies. If you look at the second gist dependencies is nothing more than a simple object where key is the package name and the value is the version number. You can go about this in many different ways but I am settled on this one.

Line 13: We must create a nodeDependency that contains all the information about the dependency we want to add/update in our package.json. This is what the interface looks like.

code is from the Angular CLI repo

I won’t go too in depth about this interface but know that NodeDependencyTypeis an enum that determines what kind of dependency your package is (e.g: Dev, Peer, etc).

To make our lives a bit easier I created a factory function that takes a package and version and will create that object for us.

Line 14: addPackageJsonDependencyis the magic method that does the work for us. It will take our Tree and the dependency we just created via the factory function and find it for us in thepackage.json and add or update it. It is important to know that if you want to update a dependency you must set the overwrite property to true.

Line 18: alas, if you want to kick off dependency installation automatically include this line.

And thats how you can update dependencies in an existing project with schematics!

Try it now!!

# if you dont have angular cli, install it
npm i -g @angular/cli
ng new schematics-test --minimal
cd schematics-test
# run `npm run build` in your schematic project before linking
npm link ../path/to/my-schematic
schematics my-schematic:myschematic

You should now see the following in your pending changes.

Scenario 2 — Override default app component files or just add new files in general

Now.. you’re on this same team with a million or so devs and you all more than likely using Visual Studio Code and you want to include some default settings or whatever. I really can’t think of a better example but you get the point.

Check out the gists below:

Alright lets dig in.

Line 3: apply allows to you two apply multiple Rules to a source. In this case the source is our vscode config files and our Rule is to just move it to a certain directory. I also take into consideration if the file already exists then we should prompt the user that it has been overridden.

Line 18: I get a little shaky here but in the source code of the CLI and Nrwl I see them use branchAndMerge every time apply is used. However, this still works if I were to just do return mergeWith(templateSource); so if anyone can shed some light on this that would be awesome. At this point in time I will just go with this is best practice since the best in the industry are doing it this way as well! So what does branchAndMerge mean exactly? This says we want to branch from the current Tree and the tree is our current directory structure… and then we want to merge them with the files we just created. In this case those files would be the vscode configurations. Cool?

… and that is it! You just added some config files for you coworkers to enjoy! If you wanted to override the default app.component.* files the syntax would look essentially the same. Just make sure you point to those files via url and move them to the appropriate directory. Why would you want to overwrite these files? Maybe your apps share a common template(header/footer) and you need to include these every time you spin up a new project.

If there is any scenarios you would like me to write about let me know and I’ll see if I can whip up a new post on it. This is all trial and error for me :)

Materials that saved my life

  1. This blog goes into how to use options and templateSource which will piggyback off of Scenario 2. It will also mention a number of other things I didn’t go over in this post but I didn’t want to repeat what has already been explained. Check it out here. He also wrote one on unit testing schematics here. Great stuff!
  2. Angular Air episode about schematics on youtube.
  3. Angular Schematics source code. Check it out here.
  4. Nrwl Schematics source code. Check it out here.