As productive as mother Earth! (Original š· by MarkusĀ Spiske)
Angular Schematics is a workflow tool for the modern webāāāofficial introduction article
There are many articles on how to build your own Angular schematics but in this one weāre going to focus on using available schematics to the fullest! šŖ
Most of the time we will be using
@schematics/angular
which are provided in Angular CLI out of the box.
angular.json
file so that we donāt need to specify all the flags all the timeprovidedIn: 'root'
vs --module
flag (scoping to lazy-loaded modules)ng add
to add libraries like Angular Material (or others)BONUS: Useful commands
BONUS+: Amazing code completion capabilities!
FUN FACT: In the beginning all I had in mind was 6 distinct useful tips and see how it ended up. We have 7 main points and 2 bonuses š¤¦ But schematics just have so many cool features that there was no other way š
Most of the schematics commands in Angular CLI come with the shortcut version. For example, instead of ng generate service service-name
we can simply write ng g s service-name
.
Less letters = lower probability of typos,Ā yaayš!
Also, schematics used to be documented in the GitHub Wiki of the Angular CLI repository but this was improved. Official schematics documentation is now available as a part of angular.io together with the rest of the docs which is very convenient! Check them out to see all the available commands and their shortcut versions!
Angular CLI comes with great support for multiple apps and libraries in a single workspace. This feature can be easily missed because by default Angular CLI will generate new project with a default application directly in the project root in theĀ ./src/
folder.
Standard workspace generated using ng newĀ app-name
CLI will create new projects
folder when we decide to add more libraries later during the development process. This will lead to a inconsistent code structure where original app doesnāt follow paths and conventions compared to the ones added later.
This can be prevented by creating our new workspace with ng new --createApplication=false
flag.
What we get is an empty workspace. Then we can continue with the ng generate application our-first-app
(or library our-first-library
).
That way, all the code in the workspace will be located in the predictable location inside of projects
folder! Great! ššš
Minimal workspace generated by the Angular CLI with ng new cli-testāāāā createApplication=false
As mentioned above, Angular CLI currently supports multiple apps and libraries in the single workspace (by default inside of the projects/
folder.
The libraries and apps can be added by running ng generate library library-name
and ng generate application app-name
respectively.
You can go with the multiple independent npm packages or monorepo, thatās up to your subjective preferences. Both have their distinctive advantages and disadvantages.
The Angular CLI will generate libraries which will get their own package.json
file in the dist
folder after they were built by ng-packager
. Such a library can be easily published to npm independently from the rest of the projects in the workspace. This supports multiple npm packages scenario out of the box
On the other hand, tools like @nrwl/nx
help us to implement similar structure in a monorepo fashion. Choose what works best for your use-case!
Using schematics in a workspace with single app is very straight forward. Every call to ng generate
will generate desired entity in the specified path inside of the one and only app. What would happen with multiple apps and libraries in a single workspace?
The angular.json
file contains the defaultProject
property which specifies which project will be implicitly assumed when executing any Angular CLI command. This is valid also for the things like ng build
or ng test
.
Example of a top level structure of angular.json file with one app and one libĀ project
We can also specify --project <my-project-name>
flag as a part of these commands to make it run in a desired app or libraryā¦ The command will then look like this: ng g c path/some-component --project some-app
PRO TIP: It might be worth it to change
defaultProject
property inangular.json
file when working mostly on a single app (or lib) to prevent unnecessary typing or create additional npm script inpackage.json
which will do that for us. For example,"ng-my-lib": "ng run --project my-lib"
which we can then use like thisnpm run ng-my-lib -- test
Ā . Note the--
npm pipe to pass in a sub-command.
Angular CLI comes with default set of schematics implemented in the @schematics/angular
npm package which gives us ability to generate apps or components.
The schematics itself are actually framework independent
Many people, organizations and open source libraries already implemented and provided their own schematics in the npm registry for our use.
A good example of this could be NgRx state management library which ships its own schematics in the @ngrx/schematics
npm package. So how can we use this additional 3rd party schematics?
This one is the most straight forward solution. Once we installed additional schematics package in our workspace we can simply call them using ng g <schematics-package-name>:<schematics-name> [...options]
. Or to imagine it from a more practical angleāāāng g @ngrx/schematics:action feature-name/entity-name --spec=true
Ā ā¦
Comparison between using ng g versus schematics
Schematics can be executed even without the help of Angular CLI. In that case we can just run schematics @ngrx/schematics:action feature-name/entity-name
.
How to make schematics
command available in our environment will be discussed in the BONUS section š
Follow me on Twitter to get notified about the newest Angular blog posts and interesting frontendĀ stuff!š¤
angular.json
file so that we donāt need to specify all the flags all theĀ timeMany of the schematics which we use to generate entities like components or services support vast amount of additional configuration flags.
For example, with components we can set flag for --inlineStyle
and --inlineTemplate
so that we have whole implementation inside of the component typescript file.
A single project usually contains many components so we would need to repeat these flags manually and quite often if we wanted to preserve unified code styleā¦
Luckily, Angular CLI has support for defining default values of the schematics options!
Example of how to define workspace and project specific schematics defaults
The default values are defined inside of the schematics
object and they are defined per individual schematic. Every schematic is defined by the package name and the respective schematic.
In the example above weāre providing defaults for the component
schematics from the package @schematics/angular
.
This approach is great because it is flexible enough to allow us to specify defaults for multiple schematics packages like popular 3rd party
@nrwl/schematics
,@ngrx/schematics
packages or even our own custom built@some-org/schematics
.
The schematics
object can be defined as a top level property and in that case defaults will be applied for the ng g
call WITHOUT--project
flag. Project specific schematics
defaults can be configured too and will be activated only when using ng g
together with the --project some-project
flag.
Some schematics collections (like ngrx
) enable us to call original Angular CLI schematics (like component
or service
) next to all the new schematics they are bringing to the table.
In that case we can set such a collection as a default Angular CLI schematics collection using ng config cli.defaultCollection <schematics-package>
Ā . The defaultCollection
property will be added into angular.json
file.
Setting default schematics collection in angular.json file will enable us to call provided schematics without the need to specify their package name in every ng gĀ call
Setting default collection enables us to execute schematics from that collection without the need to specify the schematics package name in the call. That way we can call ng g action feature/action-name
instead of ng g @ngrx/schematics:action feature/action-name
which is great!
providedIn: 'root'
vs --module
flag (scoping to lazy-loaded modules)Service generation has changed and the services generated by Angular CLI 6+ use new providedIn: 'root'
syntax by default.
Service generated using ng generate service some/path/feature
Such a service doesnāt have to be specified in providers: []
array of any @NgModule
which is nice convenience. Even better, library services provided in the root will be tree-shaken automatically if they were not explicitly imported by the consumer app!
This is great improvement compared to previous dependency injection style using providers: []
array when all the provided services would always end up in the bundle regardless of whether they were used at all!
Providing service using the old style
_providers: []_
has still its place when we want to get unique instance of the service per created component or when we want to scope service to lazy loaded module.
Before it was possible to ng generate service some-feature
and specify --moduleĀ ../some.module
flag but this is no longer supported in Angular CLI 7+.
In case we want to scope our service to some component or module we have to remove the content of the @Injectable()
decorator. Then we can import the service to the desired module and add it manually to the providers: [ ]
array.
Adjusting service dependency injection registration to scope it to the lazy loadedĀ module
ng addā
to add libraries like Angular Material (orĀ others)Until now, we have been mostly talking about the execution of various schematics which were already available in our workspace. The schematics themselves usually created couple of new files and maybe added some import statement here and there to wire stuff upā¦
But what about libraries that need more extensive setupĀ work?
Schematics cover our back yet again! The helps comes in the form of ng add
command and the corresponding (special) ng-add
schematics implemented in the particular schematics package!
The most common example probably would be Angular Material, a great component library used in many Angular projects. Angular Material setup process is a bit more complicatedā¦.
@angular/material
npm packageSuch a nontrivial setup process is best handled using ng add
.
The selection capability is called āpromptsā and is a new feature of Angular CLIĀ 7+
Without ng add
we would have to install the package manually and then spend couple of minutes reading the docs to figure out how to set everything up!
PRO TIP: It still might be worth it to add
ng-add
schematics to your open source library even if it doesnāt do much more thannpm install
the package. That way people can add it using the usual workflow! Check out example how to implement this minimalng-add
schematics in the @angular-extensions/model library.
Schematics are independent from the Angular CLI and can be executed outside of the workspace. All we have to do is to install npm i -g @angular-devkit/schematics-cli
which will give as schematics
command which we can run in our terminal of choice.
Another possibility would be to us npx. Unfortunately, in our case the package name and the command name are not the same so the execution would be quite cumbersomeā¦ npx -p [@angular](http://twitter.com/angular "Twitter profile for @angular")-devkit/schematics schematics <command>
and therefore I recommend to use global npm installation instead.
schematics --list-schematics schematics-package-name:
This command lists all available schematics from the specified package. The package has to be installed and available in the node_modules/
folder of the folder from where the command was executed. (Please note that the package name ends withĀ :
character)
Example: schematics --list-schematics @ngrx/schematics:
in the workspace of the project generated by Angular CLI with installed @ngrx/schematics
package.
We might have noticed that the first line of the angular.json
looks a bit funnyā¦
Example of code completion in the angular.json file powered by the JsonĀ Schema
The $schema property is responsible for the super awesome code completion capabilities!
Letās say we would like to add defaults to another schematics of our project. All we have to do is hit code completion key shortcut of our editor of choice and we would get the list of possible values!
Very often together with a helpful description!
Example of a property description provided by the code completion capabilities of theĀ IDE
I hope you enjoyed this article and will get more productive by using Angular Schematics in your projects!
Please support this guide with your ššš using the š button on the left side and help to spread it to a wider audience š. Also, donāt hesitate to ping me if you have any questions using the article responses or Twitter DMs @tomastrajan
Starting an Angular project? Check out Angular NgRx Material Starter!
Angular NgRx Material Starter with built in best practices, theming and muchĀ more!
And never forget, future isĀ bright
Obviously the bright future (šø by James Donaldson)
If you made it this far, feel free to check out some of my other articles about Angular and frontend software development in generalā¦
The Best Way To Unsubscribe RxJS Observable In The Angular Applications!_There are many different ways how to handle RxJS subscriptions in Angular applications and weāre going to explore theirā¦_blog.angularindepth.com
The Ultimate Answer To The Very Common Angular Question: subscribe() vs | async Pipe_Most of the popular Angular state management libraries like NgRx expose application state in a form of a stream ofā¦_blog.angularindepth.com
Total Guide To Angular 6+ Dependency InjectionāāāprovidedIn vs providers:[ ] š_Letās learn when and how to use new better Angular 6+ dependency injection mechanism with new providedIn syntax to makeā¦_medium.com
Total Guide To Dynamic Angular Animations That Can Be Customized At Runtime_Animations make projects look much better_blog.angularindepth.com
How Did Angular CLI Budgets Save My Day And How They Can Save Yours_Budgets is one of the less known features of the Angular CLI which helps you to keep application bundle sizes in checkā¦_medium.com