Angular 10 + NgRx + Nest.js でプロジェクトを作る
はじめに
今回はサーバー側のプログラムも追加してみます。
今回は TypeScript 好きである、ということもあって Nest.js を選びました。
Environments
- Angular ver.10.0.2
- @ngrx/store ver.9.2.0
- @ngrx/effects ver.9.2.0
- @nestjs/ng-universal ver.2.0.1
Angular ver.10のプロジェクトに @ngrx/store が追加できない
前回同様「npx ng add @ngrx/store」で NgRx を追加しようとするとエラーが発生。
Installing packages for tooling via npm. Installed packages for tooling via npm. The package that you are trying to add does not support schematics. You can try using a different version of the package or contact the package author to add ng-add support.
下記の Issue によると、「@latest」をつける必要があるとのこと。
npx ng add @ngrx/store@latest
「@latest」をつけない場合、 1.2.0 のような古いバージョンのものがインストールされているようでした。
cannot use ng add to install ngrx store · Issue #2604 · ngrx/platform · GitHub
「@ngrx/effects」については「@latest」が必要かどうかはわかりませんでしたが、とりあえずつけてインストールしました。
npx ng add @ngrx/effects@latest
Nest.js のプロジェクトを追加する
「@nestjs/ng-universal」を使って Nest.js のプロジェクトを追加します。
GitHub - nestjs/ng-universal: Angular Universal module for Nest framework (node.js) 🌷
元々は Server-Side Rendering のためのものではありますが。
「ng add」コマンドを実行すると、プロジェクト名を聞かれるので先に作成した Angular のプロジェクト名を入力します。
npx ng add @nestjs/ng-universal
プロジェクトを実行する(失敗)
「npm run serve」で実行し、「localhost:4200」にアクセスするわけですが、ここでエラーが発生しました。
... [Nest] 12736 - 07/08/2020, 1:04:45 AM [ExceptionsHandler] Cannot read property 'indexOf' of undefined +28479ms TypeError: Cannot read property 'indexOf' of undefined ...
下記の Issue によると、「liveReload」を false にする必要があるとのこと。
TypeError: Cannot read property 'indexOf' of undefined · Issue #188 · nestjs/ng-universal · GitHub
server/app.module.ts
import { Module } from '@nestjs/common';
import { AngularUniversalModule } from '@nestjs/ng-universal';
import { join } from 'path';
@Module({
imports: [
AngularUniversalModule.forRoot({
viewsPath: join(process.cwd(), 'dist/browser'),
bundle: require('../server/main'),
liveReload: false
})
]
})
export class ApplicationModule {}
白いページが表示される
「liveReload」自体も気になるところですが、とにあれこれでエラーなしでページを表示できました。
が、そこにあるのはただ真っ白のページ。Angular のページではありません。
プロジェクトの README.md にある「bootstrap」は(恐らく)仕様変更のため「AngularUniversalOptions」に存在せず、サンプルコードをそのままコピペすることはできないようです。
ただ、「localhost:4200/index.html」にアクセスすると、正しく Angular のページが表示できました。
ということで、 デフォルトの Static file が設定されていないようだ、ということはわかりました。
またまた README.md を見ると「templatePath」というプロパティがあったため、追加してみたのですが動作しないようです。
server/app.module.ts
import { Module } from '@nestjs/common';
import { AngularUniversalModule } from '@nestjs/ng-universal';
import { join } from 'path';
@Module({
imports: [
AngularUniversalModule.forRoot({
viewsPath: join(process.cwd(), 'dist/browser'),
bundle: require('../server/main'),
liveReload: false,
templatePath: join(process.cwd(), 'dist/browser/index.html'),
})
]
})
export class ApplicationModule {}
「@nestjs/serve-static」を使ったり、ルーティングで index.html を表示させる、といった処理が必要なのでしょうか。。。?
2020-07-08 追記
@nestjs/serve-static 追加
今回は Nest.js で静的ファイルを扱うことができるようにする「@nestjs/serve-static」を使って解決することにしました。
npm install --save @nestjs/serve-static
server/main.ts
import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create(ApplicationModule);
app.setGlobalPrefix('api');
app.useStaticAssets(join(__dirname, '..', 'browser'));
await app.listen(4200);
}
bootstrap();