如何在 Nest.js 中提供静态 HTML 文件?

Posted

技术标签:

【中文标题】如何在 Nest.js 中提供静态 HTML 文件?【英文标题】:How to serve static HTML files in Nest.js? 【发布时间】:2019-08-14 22:37:04 【问题描述】:

我想提供位于 Nest 项目之外的 /dist 文件夹中的静态 html 文件。 index.html加载成功但加载任何JS文件失败(404错误)。

我有一个使用

的 Node/Express.js 项目
app.use('/', express.static('../client/dist'))

而且效果很好。

然而,在 Nest 项目中,

app.setBaseViewsDir(join(__dirname, '../../client/dist'))

不成功。

AppController我试过

import  Response  from 'express';

@Get()
  get(@Res() res: Response) 
    res.sendFile('index.html', 
      root: '../client/dist',
    );
  

但没有运气。

如前所述,index.html 已成功加载。所以问题不是走错路。 index.html 中的 src-paths 也不是问题,因为在 Express 项目中使用了完全相同的文件。

/dist
  |-index.html
  |-main.js
  |-etc.

在 index.html 中:

<script type="text/javascript" src="main.js"></script>

当我将 dist 文件夹放入 Nest 项目(并调整路径)时,它也不起作用。

我找到了解决办法:

我现在使用 express 模块:

import * as express from 'express';
...
app.use('/', express.static('../client/dist'));

【问题讨论】:

还有未解决的问题吗? :-) @KimKern 不,谢谢。我能够用上面提到的解决方案解决它:-) 很高兴听到您解决了它。 :-) 一般来说,考虑将您的解决方案添加为答案,而不是更新您的问题,以便其他人可以从中受益。然后您可以接受您的答案,向其他人展示您的问题已解决。在这种情况下,我建议使用 Nest API 而不是原生 express api,请参阅我的解决方案。 对于 Angular + NestJS + Cloud Functions for Firebase,请参阅答案:***.com/a/57493387/11127383 【参考方案1】:

为了提供静态文件,您必须使用useStaticAssets() 而不是setBaseViewsDir()

app.useStaticAssets(join(__dirname, '../../client/dist'))

当您使用useStaticAssets 时,您无需设置控制器,所有文件都将自动提供:

假设在client/dist 下,您有文件index.htmlpic.jpg。 他们将担任:

localhost:3000 -> index.html
localhost:3000/pic.jpg -> pic.jpg

当您想使用诸如hbs 之类的视图引擎时,需要设置基本视图目录,请参阅docs。

【讨论】:

这让我大失所望。谢谢! 谢谢你,你拯救了我的一天! 请注意,您需要将应用程序转换为正确的类型:const app = await NestFactory.create&lt;NestExpressApplication&gt;(AppModule); 才能在 typescript 中正确输入。【参考方案2】:

在 main.ts 中写入 app.useStaticAssets(join(__dirname, '../../client/dist'))

你也可以试试这个:

import  resolve  from 'path';

app.useStaticAssets(
    root: resolve("./build")
);

【讨论】:

这是不正确的。当您使用useStaticAssets 时,您不需要任何控制器。文件将自动提供,index.html 可在根路径下访问。【参考方案3】:

关于 Nest.js 的 official documentation 应该像这样提供静态文件:

安装所需的包:

npm install --save @nestjs/serve-static

将app.module.ts 更新为如下所示:

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 

【讨论】:

【参考方案4】:

如果你有这样的事情

/public
  |-index.html
  |-main.js
  |-etc.
/src
  |-app.controller.js
  |-app.module.js
  |-main.js

在 main.ts 或 main.js 中

async function bootstrap() 
  const app = await NestFactory.create(AppModule);
  app.useStaticAssets(join(__dirname, '..', 'public'));
  app.setViewEngine('html');

  await app.listen(5000);

bootstrap();

在 app.module.js 中

@Module(
  imports: 
  [ 
    ServeStaticModule.forRoot(
      rootPath: join(__dirname, '..', 'public'),
      exclude: ['/api*'],
    ),
  ],
  controllers: [AppController],
  providers: [AppService],
)
export class AppModule 

在 app.controller.js 中

@Controller()
@Dependencies(AppService)
export class AppController 
  constructor(appService) 
    this.appService = appService;
  

  @Get()
  @Render('index')
  root() 
  

使用此代码,您可以解决问题 :) :) :)

【讨论】:

【参考方案5】:

如果您决定在 "main.ts" "app.module.ts" 中执行此操作(您不需要它们两者),最好添加“前缀”选项在“main.ts”中:

app.useStaticAssets(join(__dirname, '..', 'public'), prefix: '/public');

或者“app.module.ts”中的“serveRoot”选项:

ServeStaticModule.forRoot(
   serveRoot: '/public',
   rootPath: join(__dirname, '..', 'public'),
),

并将静态文件的链接设为“[your host]/public/[your dir and files]” 将您的静态路径比其他路径划分。

【讨论】:

以上是关于如何在 Nest.js 中提供静态 HTML 文件?的主要内容,如果未能解决你的问题,请参考以下文章

Nest.js:如何覆盖导入模块中的提供程序?

Nest.js 为模型创建静态和实例函数的方法是啥?

如何将所有路由重定向到nest.js中的index.html(Angular)?

如何从 Nest.js 提供资产并添加中间件以检测图像请求

nest.js学习静态资源配置和模板引擎+服务Service+cookie+session

如何在 Nest.js 中参考打字稿源打印堆栈跟踪