この記事は Angular Advent Calendar 2018 の 3 日目の記事です。
みなさん今日もAngular CLI使っていますか?
Angular CLIは、ビルド周りや開発サーバの面倒を見てくれるだけでなく、ng generate
やng add
といったコマンドを実行するだけで必要なファイルの生成はもちろん、モジュールの追加や設定の変更も行ってくれるので非常に便利ですよね。
これらの処理はAngular Schematicsによって定義されており、自分で作ることもできます。また、既存のSchematicsを拡張することも可能です。
どうでしょう?試してみたくありませんか?
それでは、早速やってみましょう!
はじめよう
まずはschematics-cli
をインストールしましょう。
$ npm install -g @angular-devkit/schematics-cli
新規プロジェクトを作成します。
$ schematics blank my-schematics
$ cd my-schematics
※blank
の他にschematic
を指定すると実装サンプル付きのプロジェクトが作られます
生成されたファイルを見てみましょう。
{
"name": "my-schematics",
"schematics": "./src/collection.json",
"dependencies": {
}
}
package.json
のschematics
に指定されているcollection.json
に実行対象となるSchematicsが入っています。
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"my-schematics": {
"description": "A blank schematic.",
"factory": "./my-schematics/index#mySchematics"
}
}
}
my-schematics
が呼ばれたときに実行されるメソッドが./my-schematics/index.ts
のmySchematics
という事がわかります。
$schema
はIDEでの補完等に使われるものなので必須ではありません。
Schematicsの中身はRules
(= Tree
を返す関数)を返す関数です。Tree
はファイルシステムやファイルの変更が含まれています。
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
export function mySchematics(_options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
return tree;
};
}
作ってみよう
基本となるのはTree
の操作です。
export function mySchematics(_options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
tree.create(_options.path + '/hi', 'Hello world!');
return tree;
};
}
ビルドして実行すると、Schematicsの出力を見ることができます。
$ npm run build
$ schematics .:my-schematics --path=./
CREATE /hi (12 bytes)
デフォルトではプレビューだけですが、--dry-run=false
を指定することで実際にファイルが生成されるようになります。
$ schematics .:my-schematics --path=./ --dry-run=false
CREATE /hi (12 bytes)
$ cat hi
Hello world!
.:my-schematics
の部分は:
より前がcollection.json
へのパス、後がcollection.json
における定義名となります。そのため、他のディレクトリで呼び出す場合はschematics ./path/to/collection.json:my-schematics
のようになります。
ログ出力
進捗やエラー表示などにはlogger
を用います。用途に応じて、
- debug
- info
- warn
- error
などがあります。
export function mySchematics(_options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
_context.logger.info('🎉 Hello, schematics!');
return tree;
};
}
テンプレート
コンポーネント等に使うファイル一式を生成する際はテンプレートを利用しましょう。
import { strings } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
applyTemplates,
mergeWith,
apply,
url,
} from '@angular-devkit/schematics';
export function mySchematics(_options: any): Rule {
return (_, _context: SchematicContext) => {
return mergeWith(apply(url('./files'), [
applyTemplates({
...strings,
name: _options.name,
}),
]));
};
}
url()
でテンプレートのパスを指定し、applyTemplates()
を実行しましょう。
ファイル名は__name__
のようにアンダースコアで囲まれた部分が置換されます。
/* styles */
テンプレートはEJSのような構文で、 <% %>
で囲んだ部分に条件式を書いたり、<%= %>
で囲んだ部分に文字列を代入することができます。
<% if (name) { %>
Hello <%= name %>, I'm a schematic.
<% } else { %>
Why don't you give me your name with --name?
<% } %>
@angular-devkit/core
には、セレクタ→クラス名の変換(classify
)やケバブケースへの変換(dasherize
)といった処理のための便利なユーティリティもあるので是非活用しましょう。
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-<%= name %>',
templateUrl: './<%= name %>.component.html',
styleUrls: ['./<%= name %>.component.css'] }
})
export class <%= classify(name) %>Component implements OnInit {
constructor() { }
ngOnInit() {
}
}
それでは、実行してみましょう。
$ schematics .:my-schematics --name=sample --dry-run=false
CREATE /sample.component.css (12 bytes)
CREATE /sample.component.html (35 bytes)
CREATE /sample.component.ts (270 bytes)
コンポーネントが生成されました
公開する
いい感じのSchematicsができたら是非公開してみましょう!
$ npm run build
$ npm publish
おわりに
今回は単純なサンプルの紹介でしたが、ng add
など他のSchematicsの実装例は以下のリポジトリを参考にすると良いと思います。
https://github.com/angular/material2/tree/master/src/lib/schematics
https://github.com/ng-bootstrap/schematics
https://github.com/ionic-team/ionic/tree/master/angular/src/schematics
Onsen UIのSchematicsも開発中です!(宣伝)
https://github.com/OnsenUI/OnsenUI/pull/2591
ちなみにschematics-cliのヘルプは↓で表示できます。
$ schematics --help
利用可能なAPIについてはGitHubのドキュメントを読みましょう。
https://github.com/angular/angular-cli/tree/master/packages/angular_devkit/schematics
明日は@MasanobuAkibaさんです!
参考文献
https://medium.com/@michael.warneke/merging-custom-angular-schematics-c14a303f63b6
https://github.com/angular/angular-cli/tree/master/packages/schematics/angular
https://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2