Reputation: 707
I want to serve static HTML files which are in a /dist
folder outside of the Nest project. index.html
is loaded successfully but it fails to load any JS file (404
error).
I have a Node/Express.js project which uses
app.use('/', express.static('../client/dist'))
and it works perfectly fine.
In the Nest project, however,
app.setBaseViewsDir(join(__dirname, '../../client/dist'))
does not do the trick.
In the AppController
I tried
import { Response } from 'express';
@Get()
get(@Res() res: Response) {
res.sendFile('index.html', {
root: '../client/dist',
});
}
But no luck.
As mentioned, the index.html
is loaded successfully. So the problem is not a wrong path. Neither is the problem wrong src-paths in the index.html
because in the Express project the exact same files are used.
/dist
|-index.html
|-main.js
|-etc.
In the index.html:
<script type="text/javascript" src="main.js"></script>
It does not work either when I put the dist folder into the Nest project (and adapt the path).
I use the express module now:
import * as express from 'express';
...
app.use('/', express.static('../client/dist'));
Upvotes: 26
Views: 68360
Reputation: 34125
I had a lot of trial an error with the solutions here.
My file structure has a folder public
right next to src
with the NestJS app source.
This is what ended up working for me
import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { resolve } from 'path';
import { AppModule } from './app.module';
async function bootstrap(): Promise<void> {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// ^^^ This generic type is key!
app.useStaticAssets(resolve('./public/assets'), { prefix: '/assets' });
await app.listen(3000);
}
when I visit localhost:3000/assets/example.png
I get the file at /public/assets/example.png
Upvotes: 0
Reputation: 9961
I was facing the same issue, I want to serve the public images through API, so I tried the below approach:
Create a constant to configure the public folder:
// src\constants\constant.ts
export const PUBLIC_IMAGES = 'public/images';
Add ServeStaticModule in your app.module.ts:
// src\app.module.ts
import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
import { PUBLIC_IMAGES } from './constants/constant';
@Module({
imports: [
ServeStaticModule.forRoot({
serveRoot: '/public',
rootPath: join(__dirname, '..', PUBLIC_IMAGES),
})
],
controllers: [],
providers: [ ],
})
export class AppModule {}
Create a public folder for your images:
root->public\images\myImage.png
Hit URL in the browser:
http://localhost:3010/public/myImage.png
Upvotes: 0
Reputation: 1454
If you decide to do it in "main.ts" or "app.module.ts" (you don't need them both), it's better for you to add "prefix" option in the "main.ts":
app.useStaticAssets(join(__dirname, '..', 'public'), {prefix: '/public'});
Or the "serveRoot" option in the "app.module.ts":
ServeStaticModule.forRoot({
serveRoot: '/public',
rootPath: join(__dirname, '..', 'public'),
}),
And make the link to your static files as "[your host]/public/[your dir and files]" To divide your static path than other paths.
Upvotes: 3
Reputation: 181
If you have something like this
/public
|-index.html
|-main.js
|-etc.
/src
|-app.controller.js
|-app.module.js
|-main.js
In main.ts or main.js
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useStaticAssets(join(__dirname, '..', 'public'));
app.setViewEngine('html');
await app.listen(5000);
}
bootstrap();
In app.module.js
@Module({
imports:
[
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'public'),
exclude: ['/api*'],
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
In app.controller.js
@Controller()
@Dependencies(AppService)
export class AppController {
constructor(appService) {
this.appService = appService;
}
@Get()
@Render('index')
root() {
}
}
With this code, you can do the trick :) :) :)
Upvotes: 8
Reputation: 8613
Regarding the official documentation of Nest.js one should serve static files like this:
Install the required package:
npm install --save @nestjs/serve-static
Update app.module.ts to look like this:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
@Module({
imports: [
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'client'), // <-- path to the static files
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Upvotes: 20
Reputation: 67
Write app.useStaticAssets(join(__dirname, '../../client/dist'))
in main.ts
And also you can try for fastify app this:
import { resolve } from 'path';
app.useStaticAssets({
root: resolve("./build")
});
Upvotes: 2
Reputation: 60537
For serving static files you have to use useStaticAssets()
instead of setBaseViewsDir()
:
app.useStaticAssets(join(__dirname, '../../client/dist'))
When you use useStaticAssets
you don't need to set up a controller, all your files will be served automatically:
Let's say under client/dist
you have the files index.html
and pic.jpg
.
They will be served as:
localhost:3000 -> index.html
localhost:3000/pic.jpg -> pic.jpg
Setting the base views dir is needed when you want to use a view engine like for example hbs
, see docs.
Upvotes: 19