我正在制作Angular + NestJS应用程序,我想为所有路由发送index.html
文件。
main.ts
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
,但我不想使用一些引擎,我只想发送由角度构建的普通html而不像res.sendFile('path_to_file')
那样黑客攻击。请帮忙
您只能将setBaseViewsDir
和@Render()
与车把(hbs)等视图引擎一起使用;但是,对于提供静态文件(Angular),您只能使用useStaticAssets
和response.sendFile
。
要从所有其他路线服务index.html
,您有几种可能性:
您可以创建一个执行重定向的中间件,请参阅此article:
@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());
您还可以将Cloud Functions for Firebase与Firebase Hosting一起使用。你在main.ts中拥有的东西非常好,通过这种方法你甚至不需要控制器。你应该如下:
index.html
重命名为index2.html
。这对于渲染路径路径很重要,否则您将在所有路径上正常工作,不包括根/
。angular.json
以获得以下"index": "apps/myapp/src/index2.html",
(只需将index.html
更改为index2.html
)。注意:index.html的路径可能与您不同,我使用的是Nx工作区。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
})
]
})
它看起来应该是这样,或者至少是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),但是所有路由重定向到index.html
(或者更确切地说是index2.html
)都可以使用NestJS + Fire Functions for Firebase完成。另外你有一个SSR“免费”:)
展示的项目:
1)角色+角度通用(SSR)+ Firebase的云函数:https://github.com/Ismaestro/angular8-example-app(缺少NestJS)。
2)Angular + NestJS:https://github.com/kamilmysliwiec/universal-nest(缺少Firebase的Cloud Functions)。