Best Practices for building Angular Schematics
Tips and tricks to help make building schematics easier
Angular Schematics are one of the coolest things to come out of Angular in the past while. With a little bit of work, you can build extensions that can be run on their own or via the Angular CLI that can install and set up libraries in your project, generate code, or make configuration changes easily and in a standardized way. They can save you a lot of time in addition to help enforcing coding standards your organization may have.
Here are some best practices that can help save you some time and headaches as you build some awesome schematics.
Use a sandbox project to test your schematics’ functionality as you develop
Testing the functionality of your schematics to make sure they behave the way you expect can be tricky. It usually involves having to link your project to another Angular application and then going back and resetting things after you run your schematics before you try again. This can be cumbersome and much more time than I would like. What if I told you it didn’t have to be that way?
Kevin Schuchard has a great post where he recommends bundling your schematics project with its own Angular app, which he calls a sandbox, and wire it up with scripts for quick testing and resetting of the project between runs. This helps you move quickly but, even better, helps others to be productive when working on your schematics later on. I highly suggest you go read the article, but here’s a quick and dirty setup of a sandbox for your schematics.
- Generate an Angular workspace with
ng new sandbox --skipGitwithin your schematics root directory.
- Update these two scripts to the sandbox’s
3. Update the scripts in the root
package.json with the following. For this example, we'll say that we want to test our ng-add schematic.
Go ahead and setup/commit everything to your git repository at the root of the project (there shouldn’t be a secondary repository in the sandbox). These scripts will allow us to link our schematics via
npm link to the sandbox and execute them easily with
npm test then clean up the sandbox back to it's original state with
npm run clean.
To use your schematic first run
npm run link:schematic to link your schematics to the sandbox. Next run
npm run build followed by
npm test. The schematic will run and then run the tests for the sandbox as well to ensure that you won’t break the app. Now you can easily diff your changes in the sandbox project and see how your schematic performed. When you are ready to try again run
npm run clean to reset the sandbox back to its original state.
Type your schemas
Schemas are great. They allow you to define what options your schematic is expecting and use dialogs to gather information from the user instead of forcing the user to remember various flags for your schematic. After I create a
schema.json file for my schematics I find it helpful to create an interface that represents that schematic's options.
For example, given this schematic’s
You would create a
schema.model.ts file like so:
This way you can use this as the type of the options you pass into the rule factory and you get all the great type checking benefits of Typescript when working with your rule factories.
Organize your project by schematic
This may seem like a no-brainer, even the example project generated by the Schematics CLI when you run
schematics schematic organizes files like this (note: see Brian Love’s tutorial if you need a refresher regarding the Schematics CLI). It really is the best way to organize your schematics and adhering to this will save you a lot of headache down the road. For example, if my project had three different schematics (let's call them schematic-a, schematic-b, and schematic-c) you should organize your project like so:
This is similar to how the Angular style guide recommends organizing your projects into modules by feature.
Create helper schematics
The great thing about schematics is that they can call other schematics! This means you can split up your functionality among multiple schematics and make them more modular. For example, if I had a schematic that installed some libraries then modified something in the file tree I would create one schematic to handle the installation of the dependencies, one to deal with the file system interactions, and a third to serve as the main schematic that chains the previous two.
Here is what the primary schematic would look like:
collection.json you can mark those other two schematics as private so they aren't accessible outside of the schematic:
files property of
package.json to only publish what you want
As your project grows and becomes more complex you might have more files and directories added to it. This can be great and ease our lives as developers but a lot of that other stuff we use for developing our schematics should not be packaged with the schematics when we publish to npm for others to use (our fancy new sandbox for example). Those files will never be used by end users and can bloat the footprint of our schematics package.
Luckily there's a way to keep our publish process small and simple without needing to change a lot to the project. Simply add the directories you want published to a
files array in your
package.json and let npm take care of the rest! For example, if I only wanted to publish my
src directory when I released my schematics package I would first create a
.npmignore that ensures that none of your *.ts except for definition files will be packaged:
Then update the root
package.json like so:
Adding this additional field will tell npm to only package those files that are not ignored within the
src directory. Hooray, smaller package sizes!
Schematics are very exciting and very powerful. There are a lot of techniques that can help to make the building of schematics a lot less difficult. Now you have a few more tools in your schematics toolbox to make sure you can build maintainable and highly performing schematics for your projects. Go forth and see what you can create!