[英]How to redirect all Angular request to index.html in Nginx
[英]How to redirect all routes to index.html (Angular) in nest.js?
我正在制作 Angular + NestJS 應用程序,我想為所有路由發送index.html
文件。
主文件
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useStaticAssets(join(__dirname, '..', 'frontend', 'dist', 'my-app'));
app.setBaseViewsDir(join(__dirname, '..', 'frontend', 'dist', 'my-app'));
await app.listen(port);
}
app.controller.ts
@Controller('*')
export class AppController {
@Get()
@Render('index.html')
root() {
return {};
}
}
當我打開localhost:3000/
時它工作正常,但是如果我打開localhost:3000/some_route
服務器會出現500 internal error
並說Can not find html module
。 我在搜索為什么我會收到這個錯誤,每個人都說set default view engine like ejs or pug
,但我不想使用某些引擎,我只想發送由 angular 構建的純 html,而不像res.sendFile('path_to_file')
。 請幫忙
您只能將setBaseViewsDir
和@Render()
與像把手 (hbs) 這樣的視圖引擎一起使用; 但是,對於提供靜態文件(Angular),您只能使用useStaticAssets
和response.sendFile
。
要從所有其他路由提供index.html
,您有幾種可能性:
您可以創建一個執行重定向的中間件,請參閱這篇文章:
@Middleware()
export class FrontendMiddleware implements NestMiddleware {
resolve(...args: any[]): ExpressMiddleware {
return (req, res, next) => {
res.sendFile(path.resolve('../frontend/dist/my-app/index.html')));
};
}
}
然后為所有路由注冊中間件:
export class ApplicationModule implements NestModule {
configure(consumer: MiddlewaresConsumer): void {
consumer.apply(FrontendMiddleware).forRoutes(
{
path: '/**', // For all routes
method: RequestMethod.ALL, // For all methods
},
);
}
}
您可以將所有NotFoundExceptions
重定向到您的index.html
:
@Catch(NotFoundException)
export class NotFoundExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
response.sendFile(path.resolve('../frontend/dist/my-app/index.html')));
}
}
然后將其注冊為main.ts
的全局過濾器:
app.useGlobalFilters(new NotFoundExceptionFilter());
2019 年 12 月 10 日的更新答案
您需要創建中間件來發送 react index.html
創建中間件文件
前端.middleware.ts
import { NestMiddleware, Injectable } from '@nestjs/common';
import {Request, Response} from "express"
import { resolve } from 'path';
@Injectable()
export class FrontendMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: Function) {
res.sendFile(resolve('../../react/build/index.html'));
}
}
包括中間件
app.module.ts
import { FrontendMiddleware } from './frontend.middleware';
import {
Module,
MiddlewareConsumer,
RequestMethod,
} from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
configure(frontEnd: MiddlewareConsumer) {
frontEnd.apply(FrontendMiddleware).forRoutes({
path: '/**', // For all routes
method: RequestMethod.ALL, // For all methods
});
}
}
供參考的應用程序結構:
您還可以將 Cloud Functions for Firebase 與 Firebase 托管一起使用。 您在main.ts中擁有的內容非常好,使用這種方法您甚至不需要控制器。 你應該按照以下步驟進行:
index.html
重命名為index2.html
。 這對於渲染您的路線路徑很重要,否則您將在所有路線上都能正常渲染,不包括根/
。angular.json
以具有以下"index": "apps/myapp/src/index2.html",
(只需將index.html
更改為index2.html
)。 注意:你的 index.html 路徑可能不同,我使用的是Nx workspace 。templatePath: join(BROWSER_DIR, 'index2.html'),
到 NestJS 的ApplicationModule
,很可能你在服務器目錄中將該文件命名為app.module.ts 。像這樣:
@Module({
imports: [
AngularUniversalModule.forRoot({
bundle: require('./path/to/server/main'), // Bundle is created dynamically during build process.
liveReload: true,
templatePath: join(BROWSER_DIR, 'index2.html'),
viewsPath: BROWSER_DIR
})
]
})
初始化 Firebase Cloud Functions 和 Firebase Hosting,有關如何設置,您可以查看https://hackernoon.com/deploying-angular-universal-v6-with-firebase-c86381ddd445或https://blog.angularindepth.com/angular -5-universal-firebase-4c85a7d00862
編輯您的firebase.json 。
它應該看起來像那樣,或者至少是hosting
部分。
{
"hosting": {
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"public": "functions/dist/apps/path/to/browser",
"rewrites": [
{
"function": "angularUniversalFunction",
"source": "**"
}
]
}
}
在簡約的情況下,它會像這樣:
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
admin.initializeApp(); // Initialize Firebase SDK.
const expressApp: Express = express(); // Create Express instance.
// Create and init NestJS application based on Express instance.
(async () => {
const nestApp = await NestFactory.create<NestExpressApplication>(
ApplicationModule,
new ExpressAdapter(expressApp)
);
nestApp.init();
})().catch(err => console.error(err));
// Firebase Cloud Function for Server Side Rendering (SSR).
exports.angularUniversalFunction = functions.https.onRequest(expressApp);
使用這種方法,您不必關心 NestJS 端的路由。 您可以在 Angular 端設置所有內容,僅此而已。 Angular 負責路由。 您可能已經注意到這是服務器端渲染 (SSR),但是可以結合使用 NestJS + Cloud Functions for Firebase 將所有路由重定向到index.html
(或更准確地說index2.html
)。 另外你有一個“免費”的 SSR :)
展示項目:
1) Angular + Angular Universal (SSR) + Cloud Functions for Firebase: https : //github.com/Ismaestro/angular8-example-app (缺少 NestJS)。
2) Angular + NestJS: https : //github.com/kamilmysliwiec/universal-nest (缺少 Firebase 的雲函數)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.