Nest.Js將所有路由導向index(Angular)
前言
使用Nest.Js做後端;Angular做前端。最後Angular打包後放置於Nest.Js做為主頁面呈現,是一種滿容易出現的作法
但如果直接無腦的將所有路由導向首頁,就會發現連一開始做好的api都全部死掉了,因為都被導回首頁了XD
稍稍研究了一下,比較好的作法就是採用middleware了
但實際用時,卻發現api還是無法回傳
後來才發現原來Nest.Js middleware的exclude用法特別奇怪
而這部份在github上也有不少討論(見Middleware Exclude behaviour not working)
但原作者似乎認為這是express的特性,沒有打算調整
而官方文件說明也不甚清晰
最後整個討論也沒下文就結束了
於是只好自己嘗試實作這個需求
一、將前端打包,並放置指定路徑,設定Nest.Js靜態路徑
我打包後的Angular,放在/dist/frontend
底下
即前、後端各自打包後,將前端的dist放到後端的/dist/frontend
打開Nest.Js的main.ts
在一開始宣告app
的地方,create
要加上泛型<NestExpressApplication>
,指定為express
此時就可以使用useStaticAssets
來指定靜態路徑
const app = await NestFactory.create<NestExpressApplication>(AppModule, {cors: true});
// 放置Angular build完後的路徑
app.useStaticAssets(path.join(`${process.cwd()}/dist/frontend`));
二、增加FrontendMiddleware
,指定網址非/api/*
,導回首頁
由於我在Nest.Js採用restful api,所有api路由固定/api/*
。還算好處理
路由開頭只要非api的,一律導回首頁
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';
@Injectable()
export class FrontendMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => void) {
if (req.originalUrl.indexOf('api') !== -1) {
next();
} else {
res.sendFile(`${process.cwd()}/dist/frontend/index.html`);
}
}
}
注意!
自動提示語法,會提示req.ip
。但Nest.Js取出來是沒有值的!
要使用req.originalUrl
才會得到路由
三、啟用middleware
打開app.module.ts
,加入此FrontendMiddleware
@Module({
//…略…
})
export class AppModule {
configure(consumer: MiddlewareConsumer): void {
consumer.apply(FrontendMiddleware).forRoutes(
{
path: '/**',
method: RequestMethod.ALL,
},
);
}
}
完成!
後記
目前這樣的寫法,若 Angular 有個 user 頁面,路由是/user
照理說,我將http://{域名或ip}/user
貼給別人,是直接觸發後端middware,而導回首頁
必須要由首頁點擊指向user的連結,才會再走Angular自己的route來導向
但我這樣做完後,直接貼上http://{域名或ip}/user
,居然就會直接進到前端我所期望的頁面!
雖然覺得有錯,但又不知道錯在哪邊。而目前的結果又是我所期望的方式@@…
所以就…將錯就錯用著來了!
如果有人知道原因的話,再煩請告知了XD
2020/7/15補充更新:
發現若在main.ts
使用app.setGlobalPrefix('api');
在browser輸入子網址(如http://{域名或ip}/user
)時會直接像是打api那樣,最後變成找不到網站
而前述作法,/api/
是寫在每一controller裡的,也較保有各別修改的靈活性!
參考資料
Stack Overflow/How to redirect all routes to index.html (Angular) in nest.js?
github/req.url is always ‘/‘ in Middleware
Middleware Exclude behaviour not working
若將網站部署至GAE,有遇到問題時,可以參考下列資料:
部署Nest.Js至GAE(二):掛載靜態網頁(Angular),syntaxError
部署Nest.Js至GAE(六):手動增加sitemap