I am making Angular + NestJS app, and I want to send index.html
file for all routes.
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 {};
}
}
It works fine while I open localhost:3000/
, but if I open localhost:3000/some_route
the server falls with 500 internal error
and says Can not find html module
.
I was searching why I am getting this error and everyone says set default view engine like ejs or pug
, but I don't want to use some engines, I just want to send plain html built by angular without hacking like res.sendFile('path_to_file')
. Please help
To set a static redirection for a GET request in Nestjs, we can use the @Redirect() decorator function from the @nestjs/common module and call it just above the Controller class's method that handles that GET request.
It is lightweight, simple, and open source. NestJS is a relatively new option in backend development, with many features for building and deploying enterprise services quickly and following the principles of SOLID and 12-factor applications.
Language. We're in love with TypeScript, but above all - we love Node.js. That's why Nest is compatible with both TypeScript and pure JavaScript. Nest takes advantage of the latest language features, so to use it with vanilla JavaScript we need a Babel compiler.
Nest. js uses TypeScript for type checking and provides an out-of-the-box software architecture for building and deploying testable, scalable, loosely coupled, and easily maintainable applications. In this article, we'll explore Nest. js and what you can build with it.
You can only use setBaseViewsDir
and @Render()
with a view engine like handlebars (hbs); for serving static files (Angular), however, you can only use useStaticAssets
and response.sendFile
.
To serve index.html
from all other routes you have a couple of possibilities:
You can create a middleware that does the redirect, see this 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')));
};
}
}
and then register the middleware for all routes:
export class ApplicationModule implements NestModule {
configure(consumer: MiddlewaresConsumer): void {
consumer.apply(FrontendMiddleware).forRoutes(
{
path: '/**', // For all routes
method: RequestMethod.ALL, // For all methods
},
);
}
}
You can redirect all NotFoundExceptions
to your 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')));
}
}
and then register it as a global filter in your main.ts
:
app.useGlobalFilters(new NotFoundExceptionFilter());
Updated Answer for December 10, 2019
You need to create middleware for sending the react index.html
Create middleware file
frontend.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'));
}
}
Include middleware in
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
});
}
}
App Structure for Reference:
enter image description here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With