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.
The 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 runschematics blank --name=my-schematic
cd my-schematic
You should end up with something like the above. Great.. what do these files mean?
collection.json
- This will be the list of all the available schematics you are offering. You should only see one at this point namedmy-schematic
. To use an example the Angular CLI has a number of schematics such ascomponent
,directive
, andservice
. Those would all go in the file specifically under theschematics
node. Thefactory
field points to a javascript function that the schematic will use. Here it is pointing to the functionmySchematic
inindex.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)index.ts
- This is the meat and potatoes of your schematic. All your instructions will go in here as you will see shortly.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.
I won’t go too in depth about this interface but know that NodeDependencyType
is 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: addPackageJsonDependency
is 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
- 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! - Angular Air episode about schematics on youtube.
- Angular Schematics source code. Check it out here.
- Nrwl Schematics source code. Check it out here.