parent
a3ec058f6b
commit
bc99b774ba
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"projectType": "schematics"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../dist/my-lib",
|
||||
"lib": {
|
||||
"entryFile": "src/public_api.ts"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) { }
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
};
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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<MyLibComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ MyLibComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MyLibComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'lib-my-lib',
|
||||
template: `
|
||||
<p>
|
||||
my-lib works!
|
||||
</p>
|
||||
`,
|
||||
styles: []
|
||||
})
|
||||
export class MyLibComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { MyLibComponent } from './my-lib.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [MyLibComponent],
|
||||
imports: [
|
||||
],
|
||||
exports: [MyLibComponent]
|
||||
})
|
||||
export class MyLibModule { }
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MyLibService {
|
||||
|
||||
constructor() { }
|
||||
}
|
|
@ -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';
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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/**/*"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts"
|
||||
],
|
||||
"include": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<h2>Library Schematics</h2>
|
||||
`,
|
||||
styles: []
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'schematics-for-libraries';
|
||||
}
|
|
@ -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 { }
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>SchematicsForLibraries</title>
|
||||
<base href="/">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
|
@ -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));
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"description": "Schematics For Libraries",
|
||||
"files": [
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[1].*",
|
||||
"**/*.template"
|
||||
],
|
||||
"tags": ["Angular", "Libraries", "Schematics"]
|
||||
}
|
|
@ -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`.
|
||||
|
||||
<code-example language="TypeScript" linenums="false">
|
||||
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;
|
||||
};
|
||||
}
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example language="none" linenums="false">
|
||||
|
||||
import {
|
||||
JsonAstObject,
|
||||
JsonObject,
|
||||
JsonValue,
|
||||
Path,
|
||||
normalize,
|
||||
parseJsonAst,
|
||||
strings,
|
||||
} from '@angular-devkit/core';
|
||||
|
||||
</code-example>
|
||||
|
||||
### 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, `<schematic>/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:
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
npm install -g @angular-devkit/schematics-cli
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
schematics blank --name=hello-world
|
||||
</code-example>
|
||||
|
||||
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:
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
cd hello-world
|
||||
npm install
|
||||
npm run build
|
||||
code .
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
schematics <path-to-schematics-project>:<schematics-name> --<required-option>=<value>
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
schematics .:hello-world
|
||||
</code-example>
|
||||
|
||||
### 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.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
cd hello-world
|
||||
schematics blank --name=goodbye-world
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example language="none" linenums="false">
|
||||
{
|
||||
"$schema":
|
||||
"../node_modules/@angular-devkit/schematics/collection-schema.json",
|
||||
"schematics": {
|
||||
"hello-world": {
|
||||
"description": "A blank schematic.",
|
||||
"factory": "./hello-world/index#helloWorld"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code-example>
|
||||
|
||||
* 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`.
|
||||
|
||||
<figure>
|
||||
<img src="generated/images/guide/schematics/collection-files.gif" alt="overview">
|
||||
</figure>
|
||||
|
||||
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.
|
|
@ -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 <live-example downloadOnly>library schematics project</live-example> 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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/collection.json (Schematics Collection)" path="schematics-for-libraries/projects/my-lib/schematics/collection.1.json">
|
||||
</code-example>
|
||||
|
||||
* 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.
|
||||
|
||||
<code-example header="projects/my-lib/package.json (Schematics Collection Reference)" path="schematics-for-libraries/projects/my-lib/package.json" region="collection">
|
||||
</code-example>
|
||||
|
||||
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 <lib-root>/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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/ng-add/index.ts (ng-add Rule Factory)" path="schematics-for-libraries/projects/my-lib/schematics/ng-add/index.ts">
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example header="projects/my-lib/tsconfig.schematics.json (TypeScript Config)" path="schematics-for-libraries/projects/my-lib/tsconfig.schematics.json">
|
||||
</code-example>
|
||||
|
||||
* 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`).
|
||||
|
||||
<code-example header="projects/my-lib/package.json (Build Scripts)" path="schematics-for-libraries/projects/my-lib/package.json">
|
||||
</code-example>
|
||||
|
||||
* 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.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
ng generate my-lib:my-service
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/collection.json (Schematics Collection)" path="schematics-for-libraries/projects/my-lib/schematics/collection.json">
|
||||
</code-example>
|
||||
|
||||
1. Go to the `<lib-root>/schematics/my-service/` folder.
|
||||
|
||||
1. Create a `schema.json` file and define the available options for the schematic.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/schema.json (Schematic JSON Schema)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/schema.json">
|
||||
</code-example>
|
||||
|
||||
* *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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/schema.ts (Schematic Interface)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/schema.ts">
|
||||
</code-example>
|
||||
|
||||
* *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.
|
||||
|
||||
<code-example lang="ts" header="projects/my-lib/schematics/my-service/files/__name@dasherize__.service.ts.template (Schematic Template)">
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class <%= classify(name) %>Service {
|
||||
constructor(private http: HttpClient) { }
|
||||
}
|
||||
|
||||
</code-example>
|
||||
|
||||
* 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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts (Imports)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts" region="schematics-imports">
|
||||
</code-example>
|
||||
|
||||
1. Import the defined schema interface that provides the type information for your schematic's options.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts (Schema Import)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts" region="schema-imports">
|
||||
</code-example>
|
||||
|
||||
1. To build up the generation schematic, start with an empty rule factory.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts (Initial Rule)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.1.ts" region="factory">
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts (Schema Import)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts" region="workspace">
|
||||
</code-example>
|
||||
|
||||
* 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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts (Default Project)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts" region="project-fallback">
|
||||
</code-example>
|
||||
|
||||
1. Now that you have the project name, use it to retrieve the project-specific configuration information.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts (Project)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts" region="project-info">
|
||||
</code-example>
|
||||
|
||||
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`.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts (Project Info)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts" region="path">
|
||||
</code-example>
|
||||
|
||||
### 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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts (Template transform)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts" region="template">
|
||||
</code-example>
|
||||
|
||||
* 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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts (Chain Rule)" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts" region="chain">
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example header="projects/my-lib/schematics/my-service/index.ts" path="schematics-for-libraries/projects/my-lib/schematics/my-service/index.ts">
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
|
||||
ng build my-lib
|
||||
|
||||
</code-example>
|
||||
|
||||
Then, you change into your library directory to build the schematic
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
|
||||
cd projects/my-lib
|
||||
npm run build
|
||||
|
||||
</code-example>
|
||||
|
||||
### 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.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
|
||||
npm link dist/my-lib
|
||||
|
||||
</code-example>
|
||||
|
||||
### Run the schematic
|
||||
|
||||
Now that your library is installed, you can run the schematic using the `ng generate` command.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
|
||||
ng generate my-lib:my-service --name my-data
|
||||
|
||||
</code-example>
|
||||
|
||||
In the console, you will see that the schematic was run and the `my-data.service.ts` file was created in your app folder.
|
||||
|
||||
<code-example language="bash" linenums="false" hideCopy="true">
|
||||
|
||||
CREATE src/app/my-data.service.ts (208 bytes)
|
||||
|
||||
</code-example>
|
|
@ -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:
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
ng generate my-schematic-collection:my-schematic-name
|
||||
</code-example>
|
||||
|
||||
—or—
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
ng generate my-schematic-name --collection collection-name
|
||||
</code-example>
|
||||
|
||||
### 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 `<mat-table>` that is pre-configured with a datasource for sorting and pagination.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
ng generate @angular/material:table <component-name>
|
||||
</code-example>
|
||||
|
||||
### 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.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
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.
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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).
|
||||
|
||||
</div>
|
||||
|
||||
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.
|
||||
|
||||
<code-example language="bash" linenums="false">
|
||||
ng update @angular/material
|
||||
</code-example>
|
||||
|
||||
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.
|
|
@ -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:
|
||||
|
||||
<code-example format="." language="none" linenums="false">
|
||||
projects
|
||||
|
@ -23,11 +23,11 @@ projects
|
|||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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.
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
"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 <project>:server` command.
|
||||
* The `architect/server` section configures defaults for creating a Universal app with server-side rendering, using the `ng run <project>:server` command.
|
||||
|
||||
* The `architect/app-shell` section configures defaults for creating an app shell for a progressive web app (PWA), using the `ng run <project>: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.
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -88,6 +88,11 @@ BOILERPLATE_PATHS.ivy = {
|
|||
]
|
||||
};
|
||||
|
||||
BOILERPLATE_PATHS.schematics = [
|
||||
...cliRelativePath,
|
||||
'angular.json'
|
||||
];
|
||||
|
||||
const EXAMPLE_CONFIG_FILENAME = 'example-config.json';
|
||||
|
||||
class ExampleBoilerPlate {
|
||||
|
|
|
@ -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"
|
||||
}
|
Loading…
Reference in New Issue