この記事は Angular #2 Advent Calendar 2019 9日目の記事です。
今年のng-japanで発表されていた「Angular + NestJS」に興味を持ったのでやってみました。
https://www.youtube.com/watch?v=2QTumr8-KhU
NestJSはAngularに影響を受けて作られたサーバーサイドアプリケーションフレームワークです。フロントエンド・バックエンド両方を同じ感覚で書けるのは良いですよね。
ng-japanの発表ではLernaを使ったモノレポ構成となっていましたが、最近だとNxを使うのも良さそうだったので、サンプルを交えながら解説していこうと思います。
ワークスペースの作成
create-nx-workspace
コマンドでワークスペースを生成します。
$ npx create-nx-workspace
ワークスペース名を指定し、テンプレートとして「angular-nest」を選択しましょう。
$ npx create-nx-workspace
? Workspace name (e.g., org name) workspace
? What to create in the new workspace
empty [an empty workspace]
web components [a workspace with a single app built using web components]
angular [a workspace with a single Angular application]
❯ angular-nest [a workspace with a full stack application (Angular + Nest)]
react [a workspace with a single React application]
react-express [a workspace with a full stack application (React + Express)
(Move up and down to reveal more choices)
? Application name web
? Default stylesheet format SASS(.scss) [ http://sass-lang.com ]
なんとたったこれだけで「Angular + NestJS」の環境ができました。
アプリケーションの起動
nx serve <プロジェクト名>
で各アプリケーションを起動できます。
$ npm run nx serve api
$ npm run nx serve web
プロジェクト構成
生成されたプロジェクトにはapps
ディレクトリにフロントエンド・バックエンドそれぞれのアプリケーションが入っており、libs/api-interfaces
内に共通のインターフェースが定義されています。
tsconfig.json
でパスのエイリアスも設定済みなので、インポートの際は@workspace/api-interfaces
を指定すればOKです。
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Message } from '@workspace/api-interfaces';
@Component({...})
export class AppComponent {
hello$ = this.http.get<Message>('/api/hello');
constructor(private http: HttpClient) {}
}
アプリケーションの追加
下記のコマンドでアプリケーションを追加できます。
$ npm run ng g @nrwl/angular:app <アプリケーション名>
生成されたアプリケーションは、ユニットテストとE2EテストにそれぞれJest、Cypressをデフォルトで使用する設定となっています。
ライブラリの追加
下記のコマンドでライブラリを追加できます。アプリケーション間で共通で使うサービスやコンポーネントを入れると良いでしょう。
$ npm run ng g @nrwl/angular:lib <ライブラリ名>
tsconfig.json
のエイリアス設定もライブラリ生成時に自動で追加されます。
{
"compileOnSave": false,
"compilerOptions": {
"rootDir": ".",
(中略)
"baseUrl": ".",
"paths": {
"@workspace/api-interfaces": ["libs/api-interfaces/src/index.ts"],
"@workspace/ui": ["libs/ui/src/index.ts"]
}
},
"exclude": ["node_modules", "tmp"]
}
Schematicの追加
追加のインストールや設定無しでSchematicを作成・実行できるのもNxの面白いところです。
$ npm run ng g workspace-schematic
ng g workspace-schematic
コマンドを実行するとshcema.json
とindex.json
が生成されます。
以下の例ではsrc/environments/envirnment.ts
を生成するSchematicを示しています。APIキーが含まれているなど、ビルドに必要でもバージョン管理下に置きたくない場合はSchematicを使って生成するのも一つの手かと思います。
{
"$schema": "http://json-schema.org/schema",
"id": "environment",
"type": "object",
"properties": {
"project": {
"type": "string",
"description": "Name of the project.",
"x-prompt": "Which project would you like to add environment variables?"
},
"production": {
"type": "boolean",
"description": "Production",
"default": false
},
"apiToken": {
"type": "string",
"description": "API token"
},
},
"required": ["project"]
}
import { strings } from '@angular-devkit/core';
import { Rule, SchematicContext, apply, applyTemplates, mergeWith, mov, url } from '@angular-devkit/schematics';
import { toFileName } from '@nrwl/workspace';
export interface Schema {
project: string;
production: boolean;
apiToken?: string;
}
export default function(schema: Schema): Rule {
const name = toFileName(schema.production ? 'environment.prod' : 'environment');
const directory = `apps/${schema.project}/src/environments`;
return (_, _context: SchematicContext) => {
return mergeWith(apply(url('./files'), [
applyTemplates({
...strings,
name,
production: schema.production,
apiToken: `'${schema.apiToken || ''}'`,
}),
move(directory)
]));
};
}
export const environment = {
production: <%= production %>,
apiToken: <%= apiToken %>
};
アプリケーションのテスト
nx test <プロジェクト名>
でユニットテスト、nx e2e <プロジェクト名>-e2e
でE2Eテストを実行します。
$ npm run nx test web
$ npm run nx e2e web-e2e
nx affected:test
コマンドを使うとNxが自動で差分を検出して必要なテストを実行してくれます。CI環境などで実行時間を最適化したい場合にオススメです。
$ npm run nx affected:test # nx affected -- --target=testでも可
> NX NOTE Affected criteria defaulted to --base=master --head=HEAD
> NX Running target test for projects:
- api-interfaces
- web
- api
- ui
アプリケーションのビルド
アプリケーションをビルドするにはnx build <プロジェクト名>
を実行します。プロダクションビルドの場合は--prod
オプションを指定します。
$ npm run nx build api -- --prod
$ npm run nx build web -- --prod
おわりに
バックエンドにNestJSを採用するとAngularと知見を共有できるの効率的に開発できそうです。さらにNxを利用することで、Angular + NestJSの環境を簡単に作成できます。Angular + NestJSでフルスタックWebアプリ開発したい場合はNxを試してみると良いと思います。