Nest项目(二)-静态资源配置并返回html页面
前言
到目前位置,已经确定了下面几个问题:
- 项目启动流程,main.ts
- 接口请求处理流程,app.module.ts
- 其他周边工具已经具备,除了 git hooks
接下来要做的是开放静态资源,并使用接口返回 html 页面。
虽然现在都已经是前后端分离了,但是有些特殊场景或者页面很简单的页面还是需要使用混编的方式去实现的。 例如:
- 点击跳转的方式下载文件
- 单点登录页面
- 监控信息页面
- . . .
配置过程
开放静态资源路径
express中开放静态资源是使用 app.use(express.static(path.join(__dirname, "public")));
的方式开放public路径,这样就可以使用从 public 里面拿到资源给浏览器使用了。
而 nest 是基于express 的,它提供了一个 api 用来处理静态资源。
最基本的配置方法是在main中直接开放 public 路径。首先在根目录中创建 public/img 路径并在 img 中放个图片,然后修改main.ts:
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.useStaticAssets('public');
await app.listen(3000);
}
bootstrap();
然后访问:http://localhost:3000/img/avantar.jpg 即可看到图片。
然而,实际开发中,一般的请求格式是这样的 http://[host]/static/[js|css|img]/fileName
,但是开发习惯来说又会把静态资源放在 public 里面,这样就需要将 public 转换成虚拟地址,其实也是避免后面的接口模块和静态资源造成干扰。具体配置如下:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// app.useStaticAssets('public');
app.useStaticAssets(join(__dirname, '..', 'public'), { prefix: '/static/' });
await app.listen(3000);
}
bootstrap();
访问方式则改成:http://localhost:3000/static/img/avantar.jpg
安装模板引擎返回HTML页面
首先在 public 路径下,创建 views 路径,并新建 index.html。
此时,已经可以通过 http://localhost:3000/static/views/index.html 或 http://localhost:3000/static/views/ 进行访问了,因为服务器默认会在 views 下找 index.html ,如果有则返回,没有的话才会返回 404。但是不能这样访问 http://localhost:3000/static/views/index ,这样最后一级index 会被看做路径而不是文件。
然而,这次要做的是做一个服务器渲染的页面,这样只能提供静态页面给浏览器。
一、 安装 ejs 并在入口声明
EJS 是什么?
“E” 代表什么?可以表示 “可嵌入(Embedded)”,也可以是“高效(Effective)”、“优雅(Elegant)”或者是“简单(Easy)”。EJS 是一套简单的模板语言,帮你利用普通的 JavaScript 代码生成 HTML 页面。EJS 没有如何组织内容的教条;也没有再造一套迭代和控制流语法;有的只是普通的 JavaScript 代码而已。
上面是从官网粘过来的原介绍,了解过 php 和 jsp 的同学肯定知道,可以在 html 中嵌入一些 jsp 和 php 语法,然后由服务器将 html 结合数据重新渲染,返回最终的 html 给到浏览器。而 ejs 和那两位一样,只不过是基于 js 实现的。
通过特殊的语法被渲染器识别,并将语法部分结合数据进行转换最终返回一个 html 页面。
安装 ejs :(我用的是 pnpm)
$ pnpm i ejs --save
改造 main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// app.useStaticAssets('public');
app.useStaticAssets(join(__dirname, '..', 'public'), { prefix: '/static/' }); //设置虚拟路径
app.setBaseViewsDir(join(__dirname, '..', 'views')); // 放视图的文件
app.setViewEngine('ejs');
await app.listen(3000);
}
bootstrap();
为了区分 public 中的html,所以平级创建 views 路径,用来存放 ejs 文件。而 setBaseViewsDir 这个 api 则是用来声明 ejs 文件的路径。
二、在接口中使用 ejs 渲染页面
为了减小对模板项目的影响,增加了一个接口 /index 用来返回混编后的页面:
// app.controller.ts
import { Controller, Get, Render } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
// 新增get接口,/index
@Get('index')
@Render('index')
getIndex(): { message: string } {
return { message: 'hello ejs!' };
}
}
对应创建 模板文件:
// views/index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<h1><%=message%></h1> <!-- 这就是渲染message的地方 -->
<h2>这是 ejs 演示代码</h2>
</body>
</html>
三、验证
浏览器访问:http://localhost:3000/index 即可看到页面。
可以看到,上面的 静态资源和现在的混编页面的访问路径是不一样的。
一个是返回 html文件被浏览器解析,一个是get请求接口,服务器模拟 html 文件被浏览器识别。是有着本质的区别的。
补充功能
服务端重定向
配合 res 进行重定向。
res.redirect('/user'); //路由跳转
下一步计划
服务连接 MySQL 数据库,并将数据渲染在 ejs 文件中,返回给用户浏览使用。
参考文档
转载自:https://juejin.cn/post/7171664682091020318