(ちょっとしたこと) AngularでUIを作って、NestJSでREST APIと併せて公開するという使い方もあるので、そのやり方をまとめる。といっても、NestJSはExpress上で動いているようなものなので、やることは基本的にExpressと同じで、特に目新しいことはない。
Angular側の設定
Angularで作成したUIは、build
コマンドによってバンドルし、NestJSから見えるパスに生成する必要がある。生成先のパスはangular.json
のoutputPath
で指定する。
{
"projects": {
...中略...
"options": {
"outputPath": "<NestJsプロジェクトの場所>/public等",
あとは、ng build
やng build -w
でビルドすればよい。
NestJSで静的ファイルのパスを指定する
生成したバンドルファイルを開けるようにするために、以下のように静的ファイルを置くパス(この場合はmain.ts
基準の相対)で指定する。(参考:https://docs.nestjs.com/techniques/mvc)
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useStaticAssets(join(__dirname, '..', 'public'));
await app.listen(3000);
}
bootstrap();
訂正: 以下の内容は不要
publicを公開した時点で、エンドポイントからindex.htmlを公開する必要はありませんでした…
コントローラから公開する
REST APIと同様、静的ファイルをGetメソッドから開けるようにするために、コントローラを追加する。実はこれには色々なやり方があるらしく、どれが良いのかはいまいちわからない。
方法1 ファイルを送信する
Res(応答オブジェクト)のsendFileメソッドを使ってファイルを返すという方法。なんとなく、そのまま返すという点で速そう。
以下は、ルートへのGETメソッドの応答に、index.html
をそのまま送っている。
import { Controller, Get, Res } from '@nestjs/common';
@Controller()
export class AppController {
constructor() {}
@Get()
root( @Res() res ) {
res.sendFile( 'index.html' );
}
}
方法2 レンダリングする
Angularのバンドル後のファイルであれば、この方法のメリットはあまりないと思うが、テンプレートエンジンを使ってレンダリングするという方法もある。
以下では、@Render
デコレータに、テンプレート(static直下のindex.html)を使ってレンダリングするよう設定することで、テンプレートエンジンを介してAngularのバンドル後のファイルを公開している。
普通は関数の本体(ここではroot()
)でテンプレートエンジンに与えるパラメータを返すのだが、Angularの生成したファイルに対して加工することはないので、root()
では何もしていない。テンプレートエンジンを通している分、方法1と比べると若干遅いかもしれない…
import { Controller, Get, Render } from '@nestjs/common';
@Controller()
export class AppController {
constructor() {}
@Get()
@Render('index.html')
root() {}
}
実行結果
Angular CLIでサンプルを作成し、それをNestJSのサーバ(ポート:3000番)で公開すると、以下のような画面が表示される。