From bc99b774baa3f6ffa01b650552b15f3e35745a79 Mon Sep 17 00:00:00 2001 From: Judy Bogart Date: Thu, 24 Jan 2019 08:45:34 -0800 Subject: [PATCH] docs: add schematics guide (#28343) PR Close #28343 --- aio/content/examples/.gitignore | 3 + .../example-config.json | 3 + .../projects/my-lib/ng-package.json | 7 + .../projects/my-lib/package.json | 20 ++ .../my-lib/schematics/collection.1.json | 9 + .../my-lib/schematics/collection.json | 14 + .../__name@dasherize__.service.ts.template | 10 + .../my-lib/schematics/my-service/index.1.ts | 11 + .../my-lib/schematics/my-service/index.ts | 66 ++++ .../my-lib/schematics/my-service/schema.json | 28 ++ .../my-lib/schematics/my-service/schema.ts | 10 + .../my-lib/schematics/ng-add/index.ts | 10 + .../my-lib/src/lib/my-lib.component.spec.ts | 25 ++ .../my-lib/src/lib/my-lib.component.ts | 19 ++ .../projects/my-lib/src/lib/my-lib.module.ts | 10 + .../my-lib/src/lib/my-lib.service.spec.ts | 12 + .../projects/my-lib/src/lib/my-lib.service.ts | 9 + .../projects/my-lib/src/public_api.ts | 7 + .../projects/my-lib/tsconfig.lib.json | 32 ++ .../projects/my-lib/tsconfig.schematics.json | 35 ++ .../projects/my-lib/tsconfig.spec.json | 17 + .../src/app/app.component.ts | 12 + .../src/app/app.module.ts | 16 + .../schematics-for-libraries/src/index.html | 14 + .../schematics-for-libraries/src/main.ts | 12 + .../schematics-for-libraries/zipper.json | 10 + aio/content/guide/schematics-authoring.md | 194 +++++++++++ aio/content/guide/schematics-for-libraries.md | 320 ++++++++++++++++++ aio/content/guide/schematics.md | 121 +++++++ aio/content/guide/workspace-config.md | 28 +- .../guide/schematics/collection-files.gif | Bin 0 -> 38619 bytes aio/content/navigation.json | 23 +- aio/package.json | 2 +- .../customizer/package-json/schematics.json | 24 ++ aio/tools/example-zipper/exampleZipper.js | 5 +- aio/tools/examples/example-boilerplate.js | 5 + .../boilerplate/schematics/angular.json | 170 ++++++++++ 37 files changed, 1295 insertions(+), 18 deletions(-) create mode 100644 aio/content/examples/schematics-for-libraries/example-config.json create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/ng-package.json create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/package.json create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/collection.1.json create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/collection.json create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/files/__name@dasherize__.service.ts.template create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/index.1.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/schema.json create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/schema.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/ng-add/index.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.component.spec.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.component.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.module.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.service.spec.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.service.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/src/public_api.ts create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.lib.json create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.schematics.json create mode 100644 aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.spec.json create mode 100644 aio/content/examples/schematics-for-libraries/src/app/app.component.ts create mode 100644 aio/content/examples/schematics-for-libraries/src/app/app.module.ts create mode 100644 aio/content/examples/schematics-for-libraries/src/index.html create mode 100644 aio/content/examples/schematics-for-libraries/src/main.ts create mode 100644 aio/content/examples/schematics-for-libraries/zipper.json create mode 100644 aio/content/guide/schematics-authoring.md create mode 100644 aio/content/guide/schematics-for-libraries.md create mode 100644 aio/content/guide/schematics.md create mode 100644 aio/content/images/guide/schematics/collection-files.gif create mode 100644 aio/tools/example-zipper/customizer/package-json/schematics.json create mode 100644 aio/tools/examples/shared/boilerplate/schematics/angular.json diff --git a/aio/content/examples/.gitignore b/aio/content/examples/.gitignore index 6d03b437e2..905ed736fe 100644 --- a/aio/content/examples/.gitignore +++ b/aio/content/examples/.gitignore @@ -92,3 +92,6 @@ upgrade-phonecat-3-final/tsconfig-aot.json upgrade-phonecat-3-final/rollup-config.js !upgrade-phonecat-*/**/karma.conf.js !upgrade-phonecat-*/**/karma-test-shim.js + +# schematics +!schematics-for-libraries/projects/my-lib/package.json \ No newline at end of file diff --git a/aio/content/examples/schematics-for-libraries/example-config.json b/aio/content/examples/schematics-for-libraries/example-config.json new file mode 100644 index 0000000000..7f9f83ed6b --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/example-config.json @@ -0,0 +1,3 @@ +{ + "projectType": "schematics" +} \ No newline at end of file diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/ng-package.json b/aio/content/examples/schematics-for-libraries/projects/my-lib/ng-package.json new file mode 100644 index 0000000000..7ca31cd528 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/my-lib", + "lib": { + "entryFile": "src/public_api.ts" + } +} \ No newline at end of file diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/package.json b/aio/content/examples/schematics-for-libraries/projects/my-lib/package.json new file mode 100644 index 0000000000..3607e2c0ce --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/package.json @@ -0,0 +1,20 @@ +// #docplaster +// #docregion collection +{ + "name": "my-lib", + "version": "0.0.1", +// #enddocregion collection + "scripts": { + "build": "../../node_modules/.bin/tsc -p tsconfig.schematics.json", + "copy:schemas": "cp --parents schematics/*/schema.json ../../dist/my-lib/", + "copy:files": "cp --parents -p schematics/*/files/** ../../dist/my-lib/", + "copy:collection": "cp schematics/collection.json ../../dist/my-lib/schematics/collection.json", + "postbuild": "npm run copy:schemas && npm run copy:files && npm run copy:collection" + }, + "peerDependencies": { + "@angular/common": "^7.2.0", + "@angular/core": "^7.2.0" + }, +// #docregion collection + "schematics": "./schematics/collection.json" +} \ No newline at end of file diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/collection.1.json b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/collection.1.json new file mode 100644 index 0000000000..1d5afc53e2 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/collection.1.json @@ -0,0 +1,9 @@ +{ + "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json", + "schematics": { + "ng-add": { + "description": "Add my library to the project.", + "factory": "./ng-add/index#ngAdd" + } + } +} \ No newline at end of file diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/collection.json b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/collection.json new file mode 100644 index 0000000000..1853903237 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/collection.json @@ -0,0 +1,14 @@ +{ + "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json", + "schematics": { + "ng-add": { + "description": "Add my library to the project.", + "factory": "./ng-add/index#ngAdd" + }, + "my-service": { + "description": "Generate a service in the project.", + "factory": "./my-service/index#myService", + "schema": "./my-service/schema.json" + } + } +} \ No newline at end of file diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/files/__name@dasherize__.service.ts.template b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/files/__name@dasherize__.service.ts.template new file mode 100644 index 0000000000..0001ceda9a --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/files/__name@dasherize__.service.ts.template @@ -0,0 +1,10 @@ +// #docregion template +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class <%= classify(name) %>Service { + constructor(private http: HttpClient) { } +} \ No newline at end of file diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/index.1.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/index.1.ts new file mode 100644 index 0000000000..8c82892a6a --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/index.1.ts @@ -0,0 +1,11 @@ +import { Rule, Tree } from '@angular-devkit/schematics'; + +import { Schema as MyServiceSchema } from './schema'; + +// #docregion factory +export function myService(options: MyServiceSchema): Rule { + return (tree: Tree) => { + return tree; + }; +} +// #enddocregion factory diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts new file mode 100644 index 0000000000..a36cf29acd --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts @@ -0,0 +1,66 @@ +// #docplaster +// #docregion schematics-imports, schema-imports, workspace +import { + Rule, Tree, SchematicsException, + apply, url, applyTemplates, move, + chain, mergeWith +} from '@angular-devkit/schematics'; + +import { strings, normalize, experimental } from '@angular-devkit/core'; +// #enddocregion schematics-imports + +import { Schema as MyServiceSchema } from './schema'; +// #enddocregion schema-imports + +export function myService(options: MyServiceSchema): Rule { + return (tree: Tree) => { + const workspaceConfig = tree.read('/angular.json'); + if (!workspaceConfig) { + throw new SchematicsException('Could not find Angular workspace configuration'); + } + + // convert workspace to string + const workspaceContent = workspaceConfig.toString(); + + // parse workspace string into JSON object + const workspace: experimental.workspace.WorkspaceSchema = JSON.parse(workspaceContent); +// #enddocregion workspace +// #docregion project-fallback + if (!options.project) { + options.project = workspace.defaultProject; + } +// #enddocregion project-fallback + +// #docregion project-info + const projectName = options.project as string; + + const project = workspace.projects[projectName]; + + const projectType = project.projectType === 'application' ? 'app' : 'lib'; +// #enddocregion project-info + +// #docregion path + if (options.path === undefined) { + options.path = `${project.sourceRoot}/${projectType}`; + } +// #enddocregion path + +// #docregion template + const templateSource = apply(url('./files'), [ + applyTemplates({ + classify: strings.classify, + dasherize: strings.dasherize, + name: options.name + }), + move(normalize(options.path as string)) + ]); +// #enddocregion template + +// #docregion chain + return chain([ + mergeWith(templateSource) + ]); +// #enddocregion chain +// #docregion workspace + }; +} diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/schema.json b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/schema.json new file mode 100644 index 0000000000..7ea68d3b62 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/schema", + "id": "SchematicsMyService", + "title": "My Service Schema", + "type": "object", + "properties": { + "name": { + "description": "The name of the service.", + "type": "string" + }, + "path": { + "type": "string", + "format": "path", + "description": "The path to create the service.", + "visible": false + }, + "project": { + "type": "string", + "description": "The name of the project.", + "$default": { + "$source": "projectName" + } + } + }, + "required": [ + "name" + ] +} \ No newline at end of file diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/schema.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/schema.ts new file mode 100644 index 0000000000..4389b72f59 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/my-service/schema.ts @@ -0,0 +1,10 @@ +export interface Schema { + // The name of the service. + name: string; + + // The path to create the service. + path?: string; + + // The name of the project. + project?: string; +} diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/ng-add/index.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/ng-add/index.ts new file mode 100644 index 0000000000..f749c7a61f --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/schematics/ng-add/index.ts @@ -0,0 +1,10 @@ +import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; +import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks'; + +// Just return the tree +export function ngAdd(_options: any): Rule { + return (tree: Tree, _context: SchematicContext) => { + _context.addTask(new NodePackageInstallTask()); + return tree; + }; +} diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.component.spec.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.component.spec.ts new file mode 100644 index 0000000000..f3c07b177c --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MyLibComponent } from './my-lib.component'; + +describe('MyLibComponent', () => { + let component: MyLibComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MyLibComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MyLibComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.component.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.component.ts new file mode 100644 index 0000000000..dee805290e --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.component.ts @@ -0,0 +1,19 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'lib-my-lib', + template: ` +

+ my-lib works! +

+ `, + styles: [] +}) +export class MyLibComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.module.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.module.ts new file mode 100644 index 0000000000..b48e140f60 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { MyLibComponent } from './my-lib.component'; + +@NgModule({ + declarations: [MyLibComponent], + imports: [ + ], + exports: [MyLibComponent] +}) +export class MyLibModule { } diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.service.spec.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.service.spec.ts new file mode 100644 index 0000000000..d580b96d47 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { MyLibService } from './my-lib.service'; + +describe('MyLibService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: MyLibService = TestBed.get(MyLibService); + expect(service).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.service.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.service.ts new file mode 100644 index 0000000000..b204cb9bdb --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/lib/my-lib.service.ts @@ -0,0 +1,9 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class MyLibService { + + constructor() { } +} diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/src/public_api.ts b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/public_api.ts new file mode 100644 index 0000000000..0b6a50ce9b --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/src/public_api.ts @@ -0,0 +1,7 @@ +/* + * Public API Surface of my-lib + */ + +export * from './lib/my-lib.service'; +export * from './lib/my-lib.component'; +export * from './lib/my-lib.module'; diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.lib.json b/aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.lib.json new file mode 100644 index 0000000000..3fe337fcf5 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.lib.json @@ -0,0 +1,32 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "target": "es2015", + "module": "es2015", + "moduleResolution": "node", + "declaration": true, + "sourceMap": true, + "inlineSources": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "importHelpers": true, + "types": [], + "lib": [ + "dom", + "es2018" + ] + }, + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true, + "enableResourceInlining": true + }, + "exclude": [ + "src/test.ts", + "**/*.spec.ts" + ] +} diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.schematics.json b/aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.schematics.json new file mode 100644 index 0000000000..4722c6029a --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.schematics.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "lib": [ + "es2018", + "dom" + ], + "declaration": true, + "module": "commonjs", + "moduleResolution": "node", + "noEmitOnError": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitThis": true, + "noUnusedParameters": true, + "noUnusedLocals": true, + "rootDir": "schematics", + "outDir": "../../dist/my-lib/schematics", + "skipDefaultLibCheck": true, + "skipLibCheck": true, + "sourceMap": true, + "strictNullChecks": true, + "target": "es6", + "types": [ + "jasmine", + "node" + ] + }, + "include": [ + "schematics/**/*" + ], + "exclude": [ + "schematics/*/files/**/*" + ] +} \ No newline at end of file diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.spec.json b/aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.spec.json new file mode 100644 index 0000000000..16da33db07 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/aio/content/examples/schematics-for-libraries/src/app/app.component.ts b/aio/content/examples/schematics-for-libraries/src/app/app.component.ts new file mode 100644 index 0000000000..7befb56b70 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/src/app/app.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + template: ` +

Library Schematics

+ `, + styles: [] +}) +export class AppComponent { + title = 'schematics-for-libraries'; +} diff --git a/aio/content/examples/schematics-for-libraries/src/app/app.module.ts b/aio/content/examples/schematics-for-libraries/src/app/app.module.ts new file mode 100644 index 0000000000..f65716351a --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/src/app/app.module.ts @@ -0,0 +1,16 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; + +import { AppComponent } from './app.component'; + +@NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/aio/content/examples/schematics-for-libraries/src/index.html b/aio/content/examples/schematics-for-libraries/src/index.html new file mode 100644 index 0000000000..ddcdfcdbe5 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/src/index.html @@ -0,0 +1,14 @@ + + + + + SchematicsForLibraries + + + + + + + + + diff --git a/aio/content/examples/schematics-for-libraries/src/main.ts b/aio/content/examples/schematics-for-libraries/src/main.ts new file mode 100644 index 0000000000..c7b673cf44 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); diff --git a/aio/content/examples/schematics-for-libraries/zipper.json b/aio/content/examples/schematics-for-libraries/zipper.json new file mode 100644 index 0000000000..d5e148b7d9 --- /dev/null +++ b/aio/content/examples/schematics-for-libraries/zipper.json @@ -0,0 +1,10 @@ +{ + "description": "Schematics For Libraries", + "files": [ + "!**/*.d.ts", + "!**/*.js", + "!**/*.[1].*", + "**/*.template" + ], + "tags": ["Angular", "Libraries", "Schematics"] +} diff --git a/aio/content/guide/schematics-authoring.md b/aio/content/guide/schematics-authoring.md new file mode 100644 index 0000000000..b2ce1ac70e --- /dev/null +++ b/aio/content/guide/schematics-authoring.md @@ -0,0 +1,194 @@ +# Authoring Schematics + +You can create your own schematics to operate on Angular projects. +Library developers typically package schematics with their libraries in order to integrate them with the Angular CLI. +You can also create stand-alone schematics to manipulate the files and constructs in Angular applications as a way of customizing them for your development environment and making them conform to your standards and constraints. +Schematics can be chained, running other schematics to perform complex operations. + +Manipulating the code in an application has the potential to be both very powerful and correspondingly dangerous. +For example, creating a file that already exists would be an error, and if it was applied immediately, it would discard all the other changes applied so far. +The Angular Schematics tooling guards against side effects and errors by creating a virtual file system. +A schematic describes a pipeline of transformations that can be applied to the virtual file system. +When a schematic runs, the transformations are recorded in memory, and only applied in the real file system once they're confirmed to be valid. + +## Schematics concepts + +The public API for schematics defines classes that represent the basic concepts. + +* The virtual file system is represented by a `Tree`. The `Tree` data structure contains a *base* (a set of files that already exists) and a *staging area* (a list of changes to be applied to the base). +When making modifications, you don't actually change the base, but add those modifications to the staging area. + +* A `Rule` object defines a function that takes a `Tree`, applies transformations, and returns a new `Tree`. The main file for a schematic, `index.ts`, defines a set of rules that implement the schematic's logic. + +* A transformation is represented by an `Action`. There are four action types: `Create`, `Rename`, `Overwrite`, and `Delete`. + +* Each schematic runs in a context, represented by a `SchematicContext` object. + +The context object passed into a rule provides access to utility functions and metadata that the schematic may need to work with, including a logging API to help with debugging. +The context also defines a *merge strategy* that determines how changes are merged from the staged tree into the base tree. A change can be accepted or ignored, or throw an exception. + +### Defining rules and actions + +When you create a new blank schematic with the [Schematics CLI](#cli), the generated entry function is a *rule factory*. +A `RuleFactory`object defines a higher-order function that creates a `Rule`. + + +import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; + +// You don't have to export the function as default. +// You can also have more than one rule factory per file. +export function helloWorld(_options: any): Rule { + return (tree: Tree, _context: SchematicContext) => { + return tree; + }; +} + + +Your rules can make changes to your projects by calling external tools and implementing logic. +You need a rule, for example, to define how a template in the schematic is to be merged into the hosting project. + +Rules can make use of utilities provided with the `@schematics/angular` package. Look for helper functions for working with modules, dependencies, TypeScript, AST, JSON, Angular CLI workspaces and projects, and more. + + + +import { + JsonAstObject, + JsonObject, + JsonValue, + Path, + normalize, + parseJsonAst, + strings, +} from '@angular-devkit/core'; + + + +### Defining input options with a schema and interfaces + +Rules can collect option values from the caller and inject them into templates. +The options available to your rules, with their allowed values and defaults, are defined in the schematic's JSON schema file, `/schema.json`. +You can define variable or enumerated data types for the schema using TypeScript interfaces. + +You can see examples of schema files for the Angular CLI command schematics in [`@schematics/angular`](https://github.com/angular/angular-cli/blob/7.0.x/packages/schematics/angular/application/schema.json). + +{@a cli} + +## Schematics CLI + +Schematics come with their own command-line tool. +Using Node 6.9 or above, install the Schematics command line tool globally: + + +npm install -g @angular-devkit/schematics-cli + + +This installs the `schematics` executable, which you can use to create a new schematics collection in its own project folder, add a new schematic to an existing collection, or extend an existing schematic. + +In the following sections, we will create a new schematics collection using the CLI in order to introduce the files and file structure, and some of the basic concepts. + +The most common use of schematics, however, is to integrate an Angular library with the Angular CLI. +You can do this by creating the schematic files directly within the library project in an Angular workspace, without using the Schematics CLI. +See [Schematics for Libraries](guide/schematics-for-libraries). + +### Creating a schematics collection + +The following command creates a new schematic named `hello-world` in a new project folder of the same name. + + +schematics blank --name=hello-world + + +The `blank` schematic is provided by the Schematics CLI. The command creates a new project folder (the root folder for the collection) and an initial named schematic in the collection. + +Go to the collection folder, install your npm dependencies, and open your new collection in your favorite editor to see the generated files. For example, if you are using VSCode: + + +cd hello-world +npm install +npm run build +code . + + +The initial schematic gets the same name as the project folder, and is generated in `src/hello-world`. +You can add related schematics to this collection, and modify the generated skeleton code to define your schematic's functionality. +Each schematic name must be unique within the collection. + +### Running a schematic + +Use the `schematics` command to run a named schematic. +Provide the path to the project folder, the schematic name, and any mandatory options, in the following format. + + +schematics <path-to-schematics-project>:<schematics-name> --<required-option>=<value> + + +The path can be absolute or relative to the current working directory where the command is executed. +For example, to run the schematic we just generated (which has no required options), use the following command. + + +schematics .:hello-world + + +### Adding a schematic to a collection + +To add a schematic to an existing collection, use the same command you use to start a new schematics project, but run the command inside the project folder. + + +cd hello-world +schematics blank --name=goodbye-world + + +The command generates the new named schematic inside your collection, with a main `index.ts` file and its associated test spec. +It also adds the name, description, and factory function for the new schematic to the collection's schema in the `collection.json` file. + +## Collection contents + +The top level of the root project folder for a collection contains configuration files, a `node_modules` folder, and a `src/` folder. +The `src/` folder contains subfolders for named schematics in the collection, and a schema, `collection.json`, which describes the collected schematics. +Each schematic is created with a name, description, and factory function. + + +{ + "$schema": + "../node_modules/@angular-devkit/schematics/collection-schema.json", + "schematics": { + "hello-world": { + "description": "A blank schematic.", + "factory": "./hello-world/index#helloWorld" + } + } +} + + +* The `$schema` property specifies the schema that the CLI uses for validation. +* The `schematics` property lists named schematics that belong to this collection. + Each schematic has a plain-text description, and points to the generated entry function in the main file. +* The `factory` property points to the generated entry function. In this example, you invoke the `hello-world` schematic by calling the `helloWorld()` factory function. +* The optional `schema` property points to a JSON schema file that defines the command-line options available to the schematic. +* The optional `aliases` array specifies one or more strings that can be used to invoke the schematic. + For example, the schematic for the Angular CLI “generate” command has an alias “g”, allowing you to use the command `ng g`. + +### Named schematics + +When you use the Schematics CLI to create a blank schematics project, the new blank schematic is the first member of the collection, and has the same name as the collection. +When you add a new named schematic to this collection, it is automatically added to the `collection.json` schema. + +In addition to the name and description, each schematic has a `factory` property that identifies the schematic’s entry point. +In the example, you invoke the schematic's defined functionality by calling the `helloWorld()` function in the main file, `hello-world/index.ts`. + +
+ overview +
+ +Each named schematic in the collection has the following main parts. + +| | | +| :------------- | :-------------------------------------------| +| `index.ts` | Code that defines the transformation logic for a named schematic. | +| `schema.json` | Schematic variable definition. | +| `schema.d.ts` | Schematic variables. | +| `files/` | Optional component/template files to replicate. | + +It is possible for a schematic to provide all of its logic in the `index.ts` file, without additional templates. +You can create dynamic schematics for Angular, however, by providing components and templates in the `files/` folder, like those in standalone Angular projects. +The logic in the index file configures these templates by defining rules that inject data and modify variables. diff --git a/aio/content/guide/schematics-for-libraries.md b/aio/content/guide/schematics-for-libraries.md new file mode 100644 index 0000000000..34edbfa839 --- /dev/null +++ b/aio/content/guide/schematics-for-libraries.md @@ -0,0 +1,320 @@ +# Schematics for Libraries + +When you create an Angular library, you can provide and package it with schematics that integrate it with the Angular CLI. +With your schematics, your users can use `ng add` to install an initial version of your library, +`ng generate` to create artifacts defined in your library, and `ng update` to adjust their project for a new version of your library that introduces breaking changes. + +All three types of schematics can be part of a collection that you package with your library. + +Download the library schematics project for a completed example of the steps below. + +## Creating a schematics collection + +To start a collection, you need to create the schematic files. +The following steps show you how to add initial support without modifying any project files. + +1. In your library's root folder, create a `schematics/` folder. + +1. In the `schematics/` folder, create an `ng-add/` folder for your first schematic. + +1. At the root level of the `schematics/` folder, create a `collection.json` file. + +1. Edit the `collection.json` file to define the initial schema for your collection. + + + + + * The `$schema` path is relative to the Angular Devkit collection schema. + * The `schematics` object describes the named schematics that are part of this collection. + * The first entry is for a schematic named `ng-add`. It contains the description, and points to the factory function that is called when your schematic is executed. + +1. In your library project's `package.json` file, add a "schematics" entry with the path to your schema file. + The Angular CLI uses this entry to find named schematics in your collection when it runs commands. + + + + +The initial schema that you have created tells the CLI where to find the schematic that supports the `ng add` command. +Now you are ready to create that schematic. + +## Providing installation support + +A schematic for the `ng add` command can enhance the initial installation process for your users. +The following steps will define this type of schematic. + +1. Go to the /schematics/ng-add/ folder. + +1. Create the main file, `index.ts`. + +1. Open `index.ts` and add the source code for your schematic factory function. + + + + +The only step needed to provide initial `ng add` support is to trigger an installation task using the `SchematicContext`. +The task uses the user's preferred package manager to add the library to the project's `package.json` configuration file, and install it in the project’s `node_modules` directory. + +In this example, the function receives the current `Tree` and returns it without any modifications. +If you need to, you can do additional setup when your package is installed, such as generating files, updating configuration, or any other initial setup your library requires. + +## Building your schematics + +To bundle your schematics together with your library, you must configure the library to build the schematics separately, then add them to the bundle. +You must build your schematics *after* you build your library, so they are placed in the correct directory. + +* Your library needs a custom Typescript configuration file with instructions on how to compile your schematics into your distributed library. + +* To add the schematics to the library bundle, add scripts to the library's `package.json` file. + +Assume you have a library project `my-lib` in your Angular workspace. +To tell the library how to build the schematics, add a `tsconfig.schematics.json` file next to the generated `tsconfig.lib.json` file that configures the library build. + +1. Edit the `tsconfig.schematics.json` file to add the following content. + + + + + * The `rootDir` specifies that your `schematics/` folder contains the input files to be compiled. + + * The `outDir` maps to the library's output folder. By default, this is the `dist/my-lib` folder at the root of your workspace. + +1. To make sure your schematics source files get compiled into the library bundle, add the following scripts to the `package.json` file in your library project's root folder (`projects/my-lib`). + + + + + * The `build` script compiles your schematic using the custom `tsconfig.schematics.json` file. + * The `copy:*` statements copy compiled schematic files into the proper locations in the library output folder in order to preserve the file structure. + * The `postbuild` script copies the schematic files after the `build` script completes. + +## Providing generation support + +You can add a named schematic to your collection that lets your users use the `ng generate` command to create an artifact that is defined in your library. + +We'll assume that your library defines a service, `my-service`, that requires some setup. You want your users to be able to generate it using the following CLI command. + + +ng generate my-lib:my-service + + +To begin, create a new subfolder, `my-service`, in the `schematics` folder. + +### Configure the new schematic + +When you add a schematic to the collection, you have to point to it in the collection's schema, and provide configuration files to define options that a user can pass to the command. + +1. Edit the `schematics/collection.json` file to point to the new schematic subfolder, and include a pointer to a schema file that will specify inputs for the new schematic. + + + + +1. Go to the `/schematics/my-service/` folder. + +1. Create a `schema.json` file and define the available options for the schematic. + + + + + * *id* : A unique id for the schema in the collection. + * *title* : A human-readable description of the schema. + * *type* : A descriptor for the type provided by the properties. + * *properties* : An object that defines the available options for the schematic. + + Each option associates key with a type, description, and optional alias. + The type defines the shape of the value you expect, and the description is displayed when the user requests usage help for your schematic. + + See the workspace schema for additional customizations for schematic options. + +1. Create a `schema.ts` file and define an interface that stores the values of the options defined in the `schema.json` file. + + + + + * *name* : The name you want to provide for the created service. + * *path* : Overrides the path provided to the schematic. The default path value is based on the current working directory. + * *project* : Provides a specific project to run the schematic on. In the schematic, you can provide a default if the option is not provided by the user. + +### Add template files + +To add artifacts to a project, your schematic needs its own template files. +Schematic templates support special syntax to execute code and variable substitution. + +1. Create a `files/` folder inside the `schematics/my-service/` folder. + +1. Create a file named `__name@dasherize__.service.ts.template` that defines a template you can use for generating files. This template will generate a service that already has Angular's `HttpClient` injected into its constructor. + + + +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class <%= classify(name) %>Service { + constructor(private http: HttpClient) { } +} + + + +* The `classify` and `dasherize` methods are utility functions you schematic will use to transform your source template and filename. + +* The `name` is provided as a property from your factory function. It is the same `name` you defined in the schema. + +### Add the factory function + +Now that you have the infrastructure in place, you can define the main function that performs the modifications you need in the user's project. + +The Schematics framework provides a file templating system, which supports both path and content templates. +The system operates on placeholders defined inside files or paths that loaded in the input `Tree`. +It fills these in using values passed into the `Rule`. + +For details of these data structure and syntax, see the [Schematics README](https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/README.md). + + +1. Create the main file, `index.ts` and add the source code for your schematic factory function. + +1. First, import the schematics definitions you will need. The Schematics framework offers many utility functions to create and use rules when running a schematic. + + + + +1. Import the defined schema interface that provides the type information for your schematic's options. + + + + +1. To build up the generation schematic, start with an empty rule factory. + + + + +This simple rule factory returns the tree without modification. +The options are the option values passed through from the `ng generate` command. + +## Define a generation rule + +We now have the framework in place for creating the code that actually modifies the user's application to set it up for the service defined in your library. + +The Angular workspace where the user has installed your library contains multiple projects (applications and libraries). +The user can specify the project on the command line, or allow it to default. +In either case, your code needs to identify the specific project to which this schematic is being applied, so that you can retrieve information from the project configuration. + +You can do this using the `Tree` object that is passed in to the factory function. +The `Tree` methods give you access to the complete file tree in your workspace, allowing you to read and write files during the execution of the schematic. + +### Get the project configuration + +1. To determine the destination project, use the `Tree.read()` method to read the contents of the workspace configuration file, `angular.json`, at the root of the workspace. + Add the following code to your factory function. + + + + + * Be sure to check that the context exists and throw the appropriate error. + + * After reading the contents into a string, parse the configuration into a JSON object, typed to the `WorkspaceSchema`. + +1. The `WorkspaceSchema` contains all the properties of the workspace configuration, including a `defaultProject` value for determining which project to use if not provided. + We will use that value as a fallback, if no project is explicitly specified in the `ng generate` command. + + + + +1. Now that you have the project name, use it to retrieve the project-specific configuration information. + + + + + The `workspace projects` object contains all the project-specific configuration information. + +1. The `options.path` determines where the schematic template files are moved to once the schematic is applied. + + The `path` option in the schematic's schema is substituted by default with the current working directory. + If the `path` is not defined, use the `sourceRoot` from the project configuration along with the `projectType`. + + + + +### Define the rule + +A `Rule` can use external template files, transform them, and return another `Rule` object with the transformed template. You can use the templating to generate any custom files required for your schematic. + +1. Add the following code to your factory function. + + + + + * The `apply()` method applies multiple rules to a source and returns the transformed source. It takes 2 arguments, a source and an array of rules. + * The `url()` method reads source files from your filesystem, relative to the schematic. + * The `applyTemplates()` method receives an argument of methods and properties you want make available to the schematic template and the schematic filenames. It returns a `Rule`. This is where you define the `classify()` and `dasherize()` methods, and the `name` property. + * The `classify()` method takes a value and returns the value in title case. For example, if the provided name is `my service`, it is returned as `MyService` + * The `dasherize()` method takes a value and returns the value in dashed and lowercase. For example, if the provided name is MyService, it is returned as `my-service. + * The `move` method moves the provided source files to their destination when the schematic is applied. + +1. Finally, the rule factory must return a rule. + + + + + The `chain()` method allows you to combine multiple rules into a single rule, so that you can perform multiple operations in a single schematic. + Here you are only merging the template rules with any code executed by the schematic. + +See a complete exampled of the schematic rule function. + + + + +For more information about rules and utility methods, see [Provided Rules](https://github.com/angular/angular-cli/tree/master/packages/angular_devkit/schematics#provided-rules). + +## Running your library schematic + +After you build your library and schematics, you can install the schematics collection to run against your project. The steps below show you how to generate a service using the schematic you created above. + + +### Build your library and schematics + +From the root of your workspace, run the `ng build` command for your library. + + + + ng build my-lib + + + +Then, you change into your library directory to build the schematic + + + + cd projects/my-lib + npm run build + + + +### Link the library + +Your library and schematics are packaged and placed in the `dist/my-lib` folder at the root of your workspace. For running the schematic, you need to link the library into your `node_modules` folder. From the root of your workspace, run the `npm link` command with the path to your distributable library. + + + +npm link dist/my-lib + + + +### Run the schematic + +Now that your library is installed, you can run the schematic using the `ng generate` command. + + + +ng generate my-lib:my-service --name my-data + + + +In the console, you will see that the schematic was run and the `my-data.service.ts` file was created in your app folder. + + + +CREATE src/app/my-data.service.ts (208 bytes) + + diff --git a/aio/content/guide/schematics.md b/aio/content/guide/schematics.md new file mode 100644 index 0000000000..27612abddc --- /dev/null +++ b/aio/content/guide/schematics.md @@ -0,0 +1,121 @@ +# Schematics + +A schematic is a template-based code generator that supports complex logic. +It is a set of instructions for transforming a software project by generating or modifying code. +Schematics are packaged into [collections](guide/glossary#collection) and installed with npm. + +The schematic collection can be a powerful tool for creating, modifying, and maintaining any software project, but is particularly useful for customizing Angular projects to suit the particular needs of your own organization. +You might use schematics, for example, to generate commonly-used UI patterns or specific components, using predefined templates or layouts. +You can use schematics to enforce architectural rules and conventions, making your projects consistent and inter-operative. + +## Schematics for the Angular CLI + +Schematics are part of the Angular ecosystem. The [Angular CLI](guide/glossary#cli) uses schematics to apply transforms to a web-app project. +You can modify these schematics, and define new ones to do things like update your code to fix breaking changes in a dependency, for example, or to add a new configuration option or framework to an existing project. + +Schematics that are included in the `@schematics/angular` collection are run by default by the commands `ng generate` and `ng add`. +The package contains named schematics that configure the options that are available to the CLI for `ng generate` sub-commands, such as `ng generate component` and `ng generate service`. +The subcommands for `ng generate` are shorthand for the corresponding schematic. You can specify a particular schematic (or collection of schematics) to generate, using the long form: + + +ng generate my-schematic-collection:my-schematic-name + + +—or— + + +ng generate my-schematic-name --collection collection-name + + +### Configuring CLI schematics + +A JSON schema associated with a schematic tells the Angular CLI what options are available to commands and subcommands, and determines the defaults. +These defaults can be overridden by providing a different value for an option on the command line. +See [Workspace Configuration](guide/workspace-config) for information about how you can change the generation option defaults for your workspace. + +The JSON schemas for the default schematics used by the CLI to generate projects and parts of projects are collected in the package [`@schematics/angular`](https://raw.githubusercontent.com/angular/angular-cli/v7.0.0/packages/schematics/angular/application/schema.json). +The schema describes the options available to the CLI for each of the `ng generate` sub-commands, as shown in the `--help` output. + +## Developing schematics for libraries + +As a library developer, you can create your own collections of custom schematics to integrate your library with the Angular CLI. + +* An *add schematic* allows developers to install your library in an Angular workspace using `ng add`. + +* *Generation schematics* can tell the `ng generate` subcommands how to modify projects, add configurations and scripts, and scaffold artifacts that are defined in your library. + +* An *update schematic* can tell the `ng update` command how to update your library's dependencies and adjust for breaking changes when you release a new version. + +For more details of what these look like and how to create them, see: +* [Authoring Schematics](guide/schematics-authoring) +* [Schematics for Libraries](guide/schematics-for-libraries) + +### Add schematics + +An add schematic is typically supplied with a library, so that the library can be added to an existing project with `ng add`. +The `add` command uses your package manager to download new dependencies, and invokes an installation script that is implemented as a schematic. + +For example, the [`@angular/material`](https://material.angular.io/guide/schematics) schematic tells the `add` command to install and set up Angular Material and theming, and register new starter components that can be created with `ng generate`. +You can look at this one as an example and model for your own add schematic. + +Partner and third party libraries also support the Angular CLI with add schematics. +For example, `@ng-bootstrap/schematics` adds [ng-bootstrap](https://ng-bootstrap.github.io/) to an app, and `@clr/angular` installs and sets up [Clarity from VMWare](https://vmware.github.io/clarity/documentation/v1.0/get-started). + +An add schematic can also update a project with configuration changes, add additional dependencies (such as polyfills), or scaffold package-specific initialization code. +For example, the `@angular/pwa` schematic turns your application into a PWA by adding an app manifest and service worker, and the `@angular/elements`  schematic adds the `document-register-element.js` polyfill and dependencies for Angular Elements. + +### Generation schematics + +Generation schematics are instructions for the `ng generate` command. +The documented sub-commands use the default Angular generation schematics, but you can specify a different schematic (in place of a sub-command) to generate an artifact defined in your library. + +Angular Material, for example, supplies generation schematics for the UI components that it defines. +The following command uses one of these schematics to render an Angular Material `` that is pre-configured with a datasource for sorting and pagination. + + +ng generate @angular/material:table + + +### Update schematics + + The `ng update` command can be used to update your workspace's library dependencies. If you supply no options or use the help option, the command examines your workspace and suggests libraries to update. + + +ng update + We analyzed your package.json, there are some packages to update: + + Name Version Command to update + -------------------------------------------------------------------------------- + @angular/cdk 7.2.2 -> 7.3.1 ng update @angular/cdk + @angular/cli 7.2.3 -> 7.3.0 ng update @angular/cli + @angular/core 7.2.2 -> 7.2.3 ng update @angular/core + @angular/material 7.2.2 -> 7.3.1 ng update @angular/material + rxjs 6.3.3 -> 6.4.0 ng update rxjs + + + There might be additional packages that are outdated. + Run "ng update --all" to try to update all at the same time. + + +If you pass the command a set of libraries to update (or the `--all` flag), it updates those libraries, their peer dependencies, and the peer dependencies that depend on them. + +
+ +If there are inconsistencies (for example, if peer dependencies cannot be matched by a simple [semver](https://semver.io/) range), the command generates an error and does not change anything in the workspace. + +We recommend that you do not force an update of all dependencies by default. Try updating specific dependencies first. + +For more about how the `ng update` command works, see [Update Command](https://github.com/angular/angular-cli/blob/master/docs/specifications/update.md). + +
+ +If you create a new version of your library that introduces potential breaking changes, you can provide an *update schematic* to enable the `ng update` command to automatically resolve any such changes in the project being updated. + +For example, suppose you want to update the Angular Material library. + + +ng update @angular/material + + +This command updates both `@angular/material` and its dependency `@angular/cdk` in your workspace's `package.json`. +If either package contains an update schematic that covers migration from the existing version to a new version, the command runs that schematic on your workspace. diff --git a/aio/content/guide/workspace-config.md b/aio/content/guide/workspace-config.md index 6bb1979420..5c67cfbccc 100644 --- a/aio/content/guide/workspace-config.md +++ b/aio/content/guide/workspace-config.md @@ -1,18 +1,18 @@ # Angular Workspace Configuration -A file named `angular.json` at the root level of an Angular [workspace](guide/glossary#workspace) provides workspace-wide and project-specific configuration defaults for build and development tools provided by the Angular CLI. -Path values given in the configuration are relative to the root workspace folder. +A file named `angular.json` at the root level of an Angular [workspace](guide/glossary#workspace) provides workspace-wide and project-specific configuration defaults for build and development tools provided by the Angular CLI. +Path values given in the configuration are relative to the root workspace folder. ## Overall JSON structure -At the top level of `angular.json`, a few properties configure the workspace, and a `projects` section contains the remaining per-project configuration options. +At the top level of `angular.json`, a few properties configure the workspace, and a `projects` section contains the remaining per-project configuration options. * `version`: The configuration-file version. * `newProjectRoot`: Path where new projects are created. Absolute or relative to the workspace folder. * `defaultProject`: Default project name to use in commands, where not provided as an argument. When you use `ng new` to create a new app in a new workspace, that app is the default project for the workspace until you change it here. -* `projects` : Contains a subsection for each project (library, app, e2e test app) in the workspace, with the per-project configuration options. +* `projects` : Contains a subsection for each project (library, app, e2e test app) in the workspace, with the per-project configuration options. -The initial app that you create with `ng new app_name` is listed under "projects", along with its corresponding end-to-end test app: +The initial app that you create with `ng new app_name` is listed under "projects", along with its corresponding end-to-end test app: projects @@ -23,11 +23,11 @@ projects Each additional app that you create with `ng generate application` has a corresponding end-to-end test project, with its own configuration section. -When you create a library project with `ng generate library`, the library project is also added to the `projects` section. +When you create a library project with `ng generate library`, the library project is also added to the `projects` section.
- Note that the `projects` section of the configuration file does not correspond exactly to the workspace file structure. + Note that the `projects` section of the configuration file does not correspond exactly to the workspace file structure. * The initial app created by `ng new` is at the top level of the workspace file structure, along with its e2e app. * Additional apps, e2e apps, and libraries go into a `projects` folder in the workspace. @@ -56,14 +56,14 @@ The following top-level configuration properties are available for each project, | `sourceRoot` | The root folder for this project's source files. | | `projectType` | One of "application" or "library". An application can run independently in a browser, while a library cannot. Both an app and its e2e test app are of type "application".| | `prefix` | A string that Angular prepends to generated selectors. Can be customized to identify an app or feature area. | -| `schematics` | An object containing schematics that customize CLI commands for this project. | +| `schematics` | An object containing configuration defaults that customize the CLI command behavior for this project. See [Schematics Overview](guide/schematics). | | `architect` | An object containing configuration defaults for Architect builder targets for this project. | ## Project tool configuration options Architect is the tool that the CLI uses to perform complex tasks such as compilation and test running, according to provided configurations. The `architect` section contains a set of Architect *targets*. Many of the targets correspond to the CLI commands that run them. Some additional predefined targets can be run using the `ng run` command, and you can define your own targets. -Each target object specifies the `builder` for that target, which is the npm package for the tool that Architect runs. In addition, each target has an `options` section that configure default options for the target, and a `configurations` section that names and specifies alternative configurations for the target. See the example in [Build target](#build-target) below. +Each target object specifies the `builder` for that target, which is the npm package for the tool that Architect runs. In addition, each target has an `options` section that configure default options for the target, and a `configurations` section that names and specifies alternative configurations for the target. See the example in [Build target](#build-target) below. "architect": { @@ -90,11 +90,11 @@ Each target object specifies the `builder` for that target, which is the npm pac * The `architect/extract-i18n` section configures defaults for options of the `ng-xi18n` tool used by the `ng xi18n` command, which extracts marked message strings from source code and outputs translation files. -* The `architect/server` section configures defaults for creating a Universal app with server-side rendering, using the `ng run :server` command. +* The `architect/server` section configures defaults for creating a Universal app with server-side rendering, using the `ng run :server` command. * The `architect/app-shell` section configures defaults for creating an app shell for a progressive web app (PWA), using the `ng run :app-shell` command. -In general, the options for which you can configure defaults correspond to the command options listed in the [CLI reference page](cli) for each command. +In general, the options for which you can configure defaults correspond to the command options listed in the [CLI reference page](cli) for each command. Note that all options in the configuration file must use [camelCase](guide/glossary#case-conventions), rather than dash-case. {@a build-target} @@ -113,15 +113,15 @@ The `architect/build` section configures defaults for options of the `ng build` ### Alternate build configurations -By default, a `production` configuration is defined, and the `ng build` command has `--prod` option that builds using this configuration. The `production` configuration sets defaults that optimize the app in a number of ways, such bundling files, minimizing excess whitespace, removing comments and dead code, and rewriting code to use short, cryptic names ("minification"). +By default, a `production` configuration is defined, and the `ng build` command has `--prod` option that builds using this configuration. The `production` configuration sets defaults that optimize the app in a number of ways, such bundling files, minimizing excess whitespace, removing comments and dead code, and rewriting code to use short, cryptic names ("minification"). -You can define and name additional alternate configurations (such as `stage`, for instance) appropriate to your development process. Some examples of different build configurations are `stable`, `archive` and `next` used by AIO itself, and the individual locale-specific configurations required for building localized versions of an app. For details, see [Internationalization (i18n)](guide/i18n#merge-aot). +You can define and name additional alternate configurations (such as `stage`, for instance) appropriate to your development process. Some examples of different build configurations are `stable`, `archive` and `next` used by AIO itself, and the individual locale-specific configurations required for building localized versions of an app. For details, see [Internationalization (i18n)](guide/i18n#merge-aot). {@a build-props} ### Additional build and test options -The configurable options for a default or targeted build generally correspond to the options available for the [`ng build`](cli/build), [`ng serve`](cli/serve), and [`ng test`](cli/test) commands. For details of those options and their possible values, see the [CLI Reference](cli). +The configurable options for a default or targeted build generally correspond to the options available for the [`ng build`](cli/build), [`ng serve`](cli/serve), and [`ng test`](cli/test) commands. For details of those options and their possible values, see the [CLI Reference](cli). Some additional options (listed below) can only be set through the configuration file, either by direct editing or with the [`ng config`](cli/config) command. diff --git a/aio/content/images/guide/schematics/collection-files.gif b/aio/content/images/guide/schematics/collection-files.gif new file mode 100644 index 0000000000000000000000000000000000000000..125406ed4a8ce3b7eb93933937d6ebcd7908721c GIT binary patch literal 38619 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 DUjCJs literal 0 HcmV?d00001 diff --git a/aio/content/navigation.json b/aio/content/navigation.json index 0171498018..a7171846b5 100644 --- a/aio/content/navigation.json +++ b/aio/content/navigation.json @@ -503,6 +503,27 @@ } ] }, + { + "title": "Schematics", + "tooltip": "Understanding schematics.", + "children": [ + { + "url": "guide/schematics", + "title": "Schematics Overview", + "tooltip": "Understand how schematics are used in Angular." + }, + { + "url": "guide/schematics-authoring", + "title": "Authoring Schematics", + "tooltip": "Understand the structure of a schematic." + }, + { + "url": "guide/schematics-for-libraries", + "title": "Schematics for Libraries", + "tooltip": "Use schematics to integrate your library with the Angular CLI." + } + ] + }, { "url": "guide/ivy", "title": "Angular Ivy", @@ -761,4 +782,4 @@ "url": "https://v2.angular.io" } ] -} +} \ No newline at end of file diff --git a/aio/package.json b/aio/package.json index 22a344533f..2a6acf570e 100644 --- a/aio/package.json +++ b/aio/package.json @@ -93,7 +93,6 @@ "classlist.js": "^1.1.20150312", "core-js": "^2.4.1", "rxjs": "^6.3.0", - "tslib": "^1.9.0", "zone.js": "^0.8.26" }, "devDependencies": { @@ -156,6 +155,7 @@ "shelljs": "^0.7.7", "tree-kill": "^1.1.0", "ts-node": "^3.3.0", + "tslib": "^1.9.0", "tslint": "~5.9.1", "typescript": "~3.3.3333", "uglify-js": "^3.0.15", diff --git a/aio/tools/example-zipper/customizer/package-json/schematics.json b/aio/tools/example-zipper/customizer/package-json/schematics.json new file mode 100644 index 0000000000..44e2cc572e --- /dev/null +++ b/aio/tools/example-zipper/customizer/package-json/schematics.json @@ -0,0 +1,24 @@ +{ + "scripts": [ + { "name": "ng", "command": "ng" }, + { "name": "build", "command": "ng build --prod" }, + { "name": "build:lib", "command": "ng build my-lib" }, + { "name": "start", "command": "ng serve" }, + { "name": "test", "command": "ng test" }, + { "name": "lint", "command": "ng lint" }, + { "name": "e2e", "command": "ng e2e" } + ], + "dependencies": [], + "devDependencies": [ + "@angular-devkit/build-angular", + "@angular-devkit/build-ng-packagr", + "@angular/cli", + "@types/jasminewd2", + "jasmine-spec-reporter", + "karma-coverage-istanbul-reporter", + "ng-packagr", + "tsickle", + "tslib", + "ts-node" + ] +} diff --git a/aio/tools/example-zipper/exampleZipper.js b/aio/tools/example-zipper/exampleZipper.js index 3afce755d7..00d713428a 100644 --- a/aio/tools/example-zipper/exampleZipper.js +++ b/aio/tools/example-zipper/exampleZipper.js @@ -102,7 +102,9 @@ class ExampleZipper { 'src/typings.d.ts', 'src/environments/**/*', 'src/tsconfig.*', - 'src/tslint.*' + 'src/tslint.*', + // Only ignore root package.json + '!package.json' ]; var alwaysExcludes = [ '!**/bs-config.e2e.json', @@ -110,7 +112,6 @@ class ExampleZipper { '!**/*zipper.*', '!**/systemjs.config.js', '!**/npm-debug.log', - '!**/package.json', '!**/example-config.json', '!**/wallaby.js', // AoT related files diff --git a/aio/tools/examples/example-boilerplate.js b/aio/tools/examples/example-boilerplate.js index 612243857b..4304264fe4 100644 --- a/aio/tools/examples/example-boilerplate.js +++ b/aio/tools/examples/example-boilerplate.js @@ -88,6 +88,11 @@ BOILERPLATE_PATHS.ivy = { ] }; +BOILERPLATE_PATHS.schematics = [ + ...cliRelativePath, + 'angular.json' +]; + const EXAMPLE_CONFIG_FILENAME = 'example-config.json'; class ExampleBoilerPlate { diff --git a/aio/tools/examples/shared/boilerplate/schematics/angular.json b/aio/tools/examples/shared/boilerplate/schematics/angular.json new file mode 100644 index 0000000000..7923d1b35f --- /dev/null +++ b/aio/tools/examples/shared/boilerplate/schematics/angular.json @@ -0,0 +1,170 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "angular.io-example": { + "root": "", + "sourceRoot": "src", + "projectType": "application", + "prefix": "app", + "schematics": {}, + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.app.json", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "src/styles.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + } + ] + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "angular.io-example:build" + }, + "configurations": { + "production": { + "browserTarget": "angular.io-example:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "angular.io-example:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.spec.json", + "karmaConfig": "src/karma.conf.js", + "styles": [ + "src/styles.css" + ], + "scripts": [], + "assets": [ + "src/favicon.ico", + "src/assets" + ] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "src/tsconfig.app.json", + "src/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "angular.io-example-e2e": { + "root": "e2e/", + "projectType": "application", + "prefix": "", + "architect": { + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "angular.io-example:serve" + }, + "configurations": { + "production": { + "devServerTarget": "angular.io-example:serve:production" + } + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": "e2e/tsconfig.e2e.json", + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "my-lib": { + "root": "projects/my-lib", + "sourceRoot": "projects/my-lib/src", + "projectType": "library", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/my-lib/tsconfig.lib.json", + "project": "projects/my-lib/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/my-lib/src/test.ts", + "tsConfig": "projects/my-lib/tsconfig.spec.json", + "karmaConfig": "projects/my-lib/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/my-lib/tsconfig.lib.json", + "projects/my-lib/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + } + }, + "defaultProject": "angular.io-example" +}