Santosh Yadav
Google Developer Expert for Angular GitHub Start and Nx Champion, Open source contributor for Angular and NgRx, creator ng deploy for Netlify, NestJSAddons core team.
Santosh Yadav
GDE for Angular and Web Technologies
Writer AngularInDepth, Mentor DotNetTricks
twitter.com/SantoshYadavDev
github.com/santoshyadav198613
santoshyadav.dev
Automate file creation/modification
Automate creating application/libraries
Automate Installation
npm install -g @angular-devkit/schematics-cli
schematics blank --name=ng-add
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
// You don't have to export the function as default. You can also have more than one rule factory
// per file.
export function ngAdd(_options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
_context.addTask(new NodePackageInstallTask());
//add a new file
tree.create('index.ts',`console.log('Schematics is amazing')`);
//read a file
const fileData= tree.read('index.ts') || '';
_context.logger.info(fileData?.toString());
//overwrite a file
tree.overwrite('index.ts',`console.log('schematics is great')`)
_context.logger.info(fileData?.toString());
//delete a file
tree.delete('index.ts');
return tree;
};
}
generate
import { Tree } from "@angular-devkit/schematics/src/tree/interface";
import { Rule, apply, url, applyTemplates, chain, branchAndMerge, mergeWith, SchematicContext } from "@angular-devkit/schematics";
import { strings } from "@angular-devkit/core";
export function generate(_options: any): Rule {
return (tree: Tree, context: SchematicContext) => {
const template = apply(url('./files'), [
applyTemplates({
...strings,
..._options
})
])
return chain([
branchAndMerge(mergeWith(template))
])(tree, context);
}
}
generate/index.ts
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"ng-add": {
"description": "A blank schematic.",
"factory": "./ng-add/index#ngAdd"
},
"generate": {
"description": "Generate schematic.",
"factory": "./generate/index#generate"
}
}
}
collection.json
{
"properties": {
"name": {
"type": "string",
"minLength": 1,
"default": "world",
"x-prompt": "What is your name?"
},
"useColor": {
"type": "boolean",
"x-prompt": "Would you like the response in color?"
}
}
}
schema.json
"schematics": "./src/collection.json",
package.json
// will not make any changes as debug is always false
schematcs .:ng-add
// will make actual changes
schematics .:ng-add --debug false
// test generate schematics
schematics .:generate --name test --debug false
Test Schematics
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"lint": [
{
"project": "src/tsconfig.app.json"
},
{
"project": "src/tsconfig.spec.json"
},
{
"project": "e2e/tsconfig.e2e.json"
}
],
"test": {
"karma": {
"config": "./karma.conf.js"
}
}
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"lint": [
{
"project": "src/tsconfig.app.json"
},
{
"project": "src/tsconfig.spec.json"
},
{
"project": "e2e/tsconfig.e2e.json"
}
],
"test": {
"karma": {
"config": "./karma.conf.js"
}
}
Overriding Webpack Configuration.
Building and Publishing Angular Libraries.
Using Other Tools for Test like Jest or cypress.io.
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "bulma-app:build"
},
"configurations": {
"production": {
"browserTarget": "bulma-app:build:production"
}
}
}
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "bulma-app:build"
},
"configurations": {
"production": {
"browserTarget": "bulma-app:build:production"
}
}
}
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/bulma-app",
"index": "projects/bulma-app/src/index.html",
"main": "projects/bulma-app/src/main.ts",
"polyfills": "projects/bulma-app/src/polyfills.ts",
"tsConfig": "projects/bulma-app/tsconfig.app.json",
"aot": false,
"assets": [
],
"styles": [
],
"scripts": [
]
},
"configurations": {
"production": {
}
}
}
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/bulma-app",
"index": "projects/bulma-app/src/index.html",
"main": "projects/bulma-app/src/main.ts",
"polyfills": "projects/bulma-app/src/polyfills.ts",
"tsConfig": "projects/bulma-app/tsconfig.app.json",
"aot": false,
"assets": [
],
"styles": [
],
"scripts": [
]
},
"configurations": {
"production": {
}
}
}
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "projects/ngx-bulma/tsconfig.lib.json",
"project": "projects/ngx-bulma/ng-package.json"
}
}
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "projects/ngx-bulma/tsconfig.lib.json",
"project": "projects/ngx-bulma/ng-package.json"
}
}
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/bulma-app/src/test.ts",
"polyfills": "projects/bulma-app/src/polyfills.ts",
"tsConfig": "projects/bulma-app/tsconfig.spec.json",
"karmaConfig": "projects/bulma-app/karma.conf.js",
"assets": [
"projects/bulma-app/src/favicon.ico",
"projects/bulma-app/src/assets"
],
"styles": [
"projects/bulma-app/src/styles.css"
],
"scripts": [
]
}
}
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/bulma-app/src/test.ts",
"polyfills": "projects/bulma-app/src/polyfills.ts",
"tsConfig": "projects/bulma-app/tsconfig.spec.json",
"karmaConfig": "projects/bulma-app/karma.conf.js",
"assets": [
"projects/bulma-app/src/favicon.ico",
"projects/bulma-app/src/assets"
],
"styles": [
"projects/bulma-app/src/styles.css"
],
"scripts": [
]
}
}
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "projects/bulma-app/e2e/protractor.conf.js",
"devServerTarget": "bulma-app:serve"
},
"configurations": {
"production": {
"devServerTarget": "bulma-app:serve:production"
}
}
}
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "projects/bulma-app/e2e/protractor.conf.js",
"devServerTarget": "bulma-app:serve"
},
"configurations": {
"production": {
"devServerTarget": "bulma-app:serve:production"
}
}
}
import { BuilderContext, BuilderOutput, createBuilder } from
'@angular-devkit/architect';
import { json } from '@angular-devkit/core';
import { schema as BuilderOptions } from './schema';
export default createBuilder<json.JsonObject
& BuilderOptions>(execute);
async function execute(options: BuilderOptions,
context: BuilderContext)
: Promise<BuilderOutput> {
// custom logic to process
}
index.ts
import { BuilderContext, BuilderOutput, createBuilder } from
'@angular-devkit/architect';
import { json } from '@angular-devkit/core';
import { schema as BuilderOptions } from './schema';
export default createBuilder<json.JsonObject
& BuilderOptions>(execute);
async function execute(options: BuilderOptions,
context: BuilderContext)
: Promise<BuilderOutput> {
// custom logic to process
}
index.ts
{
"$schema": "@angular-devkit/architect/src/builders-schema.json",
"builders": {
"custom_builder_name": {
"implementation": "./deploy",
"schema": "./deploy/schema.json",
"description": "Runs any command line in the operating system."
}
}
}
builders.json
{
"$schema": "@angular-devkit/architect/src/builders-schema.json",
"builders": {
"custom_builder_name": {
"implementation": "./deploy",
"schema": "./deploy/schema.json",
"description": "Runs any command line in the operating system."
}
}
}
builders.json
{
"name": "@netlify-builder/deploy",
"version": "2.0.3",
"description": "A Netlify builder schematics for deployment",
"main": "index.js",
"builders": "./builders.json"
}
package.json
{
"name": "@netlify-builder/deploy",
"version": "2.0.3",
"description": "A Netlify builder schematics for deployment",
"main": "index.js",
"builders": "./builders.json"
}
package.json
"custom_builder_name": {
"builder": "package:custom_builder_name",
"options": {
// provide options
}
}
ngx-build-plus
@angular/fire:deploy
Used Widely in Compilers
AST is a Data Structure
Represent the structure of the program
Used during Syntax analysis phase
Angular Internal APIs
import { parseTemplate } from '@angular/compiler';
const template = parseTemplate('<div *ngFor="let item of items">{{item.name}}</div>', '', {});
Angular Internal APIs
import * as t from '@angular/compiler/src/render3/r3_ast';
twitter.com/SantoshYadavDev
github.com/santoshyadav198613
santoshyadav.dev
Thank you
By Santosh Yadav
Google Developer Expert for Angular GitHub Start and Nx Champion, Open source contributor for Angular and NgRx, creator ng deploy for Netlify, NestJSAddons core team.