前几天在项目中集成了swagger,一切准备就绪打算将其部署到服务器时发现并不顺利,访问的时候页面白屏,由于我的nest项目采用的是单文件部署,互联网上没有找到相关的解决方案,于是我就成了第一个吃螃蟹的人。
经过一番折腾后,终于解决了这个问题,本文就跟大家分享下我的解决方案,欢迎各位感兴趣的开发者阅读本文。
首先,我们通过yarn
安装三个依赖包,如下所示:
yarn add @nestjs/swagger swagger-ui-express fastify-swagger
安装完成后,我们打开项目的入口文件main.ts
添加如下所示的代码:
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
async function bootstrap() {
// **** 其它代码省略 ****
const config = new DocumentBuilder()
.setTitle("nest-demo")
.setDescription("nest-demo项目的API使用文档")
.setVersion("1.0.0")
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup("api", app, document);
}
接下来,我们启动项目,在浏览器访问http://127.0.0.1:3000/api
,显示的界面如下所示:
default
选项列出了我们项目中的所有接口image-20220317211550995
在@nestjs/swagger库中,它提供了丰富的依赖供我们使用, 为我们生成友好的接口文档,接下来我们列举几个较为常用的注解:
@ApiTags
注解,用于对controller层进行描述。@ApiOperation
注解,用于对controller中的具体接口进行描述。@ApiProperty
注解,用于对dto层的参数进行描述。@ApiResponse
注解,用于对接口的返回数据进行描述。关于上述各个注解的具体使用方法可参考我的项目代码,如下所示:
经过上述配置后 ,最终访问效果如下所示:
image-20220317224923516
❝有关swagger注解的更多使用方法请移步:OpenAPI (Swagger)[4]
接下来,我们要做的就是将项目打包部署到服务器了,本项目采用的是单文件构建法,对此不了解的开发者请移步:Nest项目部署的最佳方式[5]。
因为集成了swagger进来,在打包时终端报错了ERROR in ./node_modules/@nestjs/mapped-types/dist/type-helpers.utils.js 69:27-63 Module not found: Error: Can't resolve 'class-transformer/storage' in ...
经过一番查找后,在mapped-types
仓库的Issues[6]中找到了答案,需要在webpack.config.js
中的lazyImports
中加入class-transformer/storage
,打包的时候即可将其忽略,部分代码如下所示,完整代码请移步:
module.exports = {
entry: "./src/main",
target: "node",
// ** 其他配置代码省略 **
plugins: [
// 需要进行忽略的插件
new webpack.IgnorePlugin({
checkResource(resource) {
const lazyImports = [
"@nestjs/microservices",
"@nestjs/microservices/microservices-module",
"@nestjs/websockets/socket-module",
"cache-manager",
"class-validator",
"class-transformer",
"class-transformer/storage"
];
})
}
❝完整代码请移步:webpack.config.js[7]
我们将项目部署到服务器,启动后,在浏览器通过127.0.0.1:3000/api
访问swagger时发现页面一片空白,打开控制台后发现它的一些资源文件404了。
image-20220318072947623
这可真是个棘手的问题,直觉告诉我肯定是因为我配置了单文件部署才导致的,我在求助了很多人,查了很多资料后,发现他们都没像我这么玩过,他们都是在服务器上npm install
依赖来跑nest项目的。
真是糟了个大糕🤡,我成了第一个吃螃蟹的人,前面一片蓝海等着我去探索。
经过一番思考后,应该是因为webpack把所有依赖都打包进main.js了,swagger-ui引用的文件应该是相对路径的,所以才导致了404问题,抱着这个疑问,我打开了swagger-ui-express
的源码,在index.js
中发现了猫腻:它果然是引入的相对路径。
image-20220318074256928
既然是相对路径,它自己的包下面又没有这个文件,那么它肯定是从别的包引入的。
image-20220318074447502
继续查阅源码后,我发现它还require了一个swagger-ui-dist
。
image-20220318074604930
果然,它所依赖的资源包都在这个目录下,他为什么要这么做呢?我又抱着疑问打开了swagger-ui
仓库,在docs/usage/installation.md[8]中它讲述了原因,提供了webpack的配置方案。
image-20220318075453246
打开链接所指向的项目后,在webpack的配置文件中我看到了copy-webpack-plugin
插件,此时我茅塞顿开,它的做法就是将swagger-ui-dist
的文件拷贝到dist下
,这样就解决了它相对路径找不到文件的问题。
方案有了,那么就可以愉快的写出代码了,如下所示:
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
entry: "./src/main",
target: "node",
plugins: [
new CopyWebpackPlugin({
patterns: [
// 拷贝swagger相关的文件
{
from: __dirname + "/node_modules/swagger-ui-dist/",
to: "./"
}
]
})
]
}
重新构建后,我们发现dist目录下多了swagger-ui-dist
的文件,我们启动项目,重新在浏览器发现已经能正常看到swagger的界面了。
image-20220318111124109
细心的开发者可能发现swagger-ui-dist目录下有很多无用文件,污染了我们的dist目录,我们需要将这些无用的文件在打包后清理掉。
![image-20220318112446885](/Users/likai/Library/Application Support/typora-user-images/image-20220318112446885.png)
接下来就该clean-webpack-plugin
插件登场了,我们在webpack的配置文件中加入下述代码:
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: "./src/main",
target: "node",
plugins: [
// ** 其它代码省略 **
// 删除多余的文件
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: [
__dirname + "/dist/*.html",
__dirname + "/dist/*.map",
__dirname + "/dist/*.md",
__dirname + "/dist/*.json",
__dirname + "/dist/index.js",
__dirname + "/dist/LICENSE",
__dirname + "/dist/NOTICE"
]
})
]
}
现在dist目录看起来就舒服多了😼
image-20220318114857681
❝注意:copy-webpack-plugin、clean-webpack-plugin需要用yarn自行安装到devDependencies依赖中。 完整代码请移步:webpack.config.js[9]
最后,我们在yapi的数据管理模块,导入swagger数据过来,本以为很顺利,结果它报错:返回数据格式不是JSON。
image-20220318113759221
翻阅文档后,我找到了方案[10],原来是要在地址后面加-json
。
加了之后,就能顺利的导入到yapi了,大功告成🤗
image-20220318114103459
做第一个吃螃蟹的人太难了,为了解决这个问题,我在浏览器已经不知不觉的开了这么多标签页了🌚
image-20220318114447903
本文所使用的完整代码,请移步项目的GitHub仓库:nest-project[11]
至此,文章就分享完毕了。
我是神奇的程序员,一位前端开发工程师。
[1]AppController.ts: https://github.com/likaia/nest-project/blob/334f2875e46107e33647ea37a738bd21056019f8/src/controller/AppController.ts#L8
[2]AppDto.ts: https://github.com/likaia/nest-project/blob/334f2875e46107e33647ea37a738bd21056019f8/src/dto/AppDto.ts#L6
[3]ResultVO: https://github.com/likaia/nest-project/blob/334f2875e46107e33647ea37a738bd21056019f8/src/VO/ResultVO.ts#L4
[4]OpenAPI (Swagger): https://docs.nestjs.cn/7/recipes?id=openapi-swagger
[5]Nest项目部署的最佳方式: https://juejin.cn/post/7065724860688760862
[6]Issues: https://github.com/nestjs/mapped-types/issues/486
[7]webpack.config.js: https://github.com/likaia/nest-project/blob/master/webpack.config.js
[8]docs/usage/installation.md: https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/installation.md
[9]webpack.config.js: https://github.com/likaia/nest-project/blob/master/webpack.config.js
[10]方案: https://docs.nestjs.cn/8/openapi
[11]nest-project: https://github.com/likaia/nest-project/
[12]个人网站: https://www.kaisir.cn/