如何使用 NESTJS 生成 API 的生产版本
Posted
技术标签:
【中文标题】如何使用 NESTJS 生成 API 的生产版本【英文标题】:How to generate a production build of an API done with NESTJS 【发布时间】:2019-07-11 05:45:54 【问题描述】:我正在生成使用 NESTJS 框架制作的 API 的生产版本,并且想知道我应该将哪些文件上传到服务器。当我运行“npm run start: prod”编译时,它会生成“dist”文件夹,但我尝试仅使用它运行,但这还不足以运行我的应用程序。我需要将所有文件上传到服务器吗?我做了几个测试,删除了我在开发过程中使用的文件夹,但只有在我在开发模式下都一样时才能在生产模式下运行。
我在文档中查找了一些关于此的内容,但一无所获。有人可以帮帮我吗?
谢谢
【问题讨论】:
【参考方案1】:大多数情况下,您只需要 node_modules
中的依赖项。您应该在您的服务器上构建这些库,而不是从您的开发机器上复制它们。 bcrypt
之类的库具有特定于机器的代码,可能不会在不同的机器上运行。 (30% of the npm libraries 具有本机绑定。)
因此,对于您的部署,我建议您在服务器上签出您的 git 存储库,然后直接在那里运行 npm run start:prod
(每次都会构建项目)。
【讨论】:
天啊。 6 小时后,我看到了您的“机器特定”短语。我希望我知道这一点。谢谢! 在服务器上构建的一个缺点是 Webpack 需要大量内存来完成 Typescript 类型检查。例如,Node.js 在具有 1GB 内存的 AWS t2.micro 上运行良好,但在构建节点应用程序时,甚至 2GB 内存的服务器也会崩溃。你可以在 webpack 配置中使用transpileOnly: true
。然后应用程序在几秒钟内构建,但您没有类型检查。最好的选择可能是在部署之前构建 javascript,但在服务器上运行 npm/yarn install?【参考方案2】:
老实说,你应该只需要 dist 文件夹,因为那是 JS 的“编译”文件。要运行你的应用程序,通常你会使用这个命令node dist/main.js
。至于你上传什么文件,这取决于你。就我个人而言,我使用了很多持续集成,所以我只需克隆到我的容器/服务器中并使用yarn start:prod
。每次部署时,我都会生成在生产环境中运行所需的文件。
就像@Kim Kern 提到的,一些节点模块是使用节点陀螺仪本地构建的;因此,最好在部署时在服务器/容器上构建 node_modules。你的部署脚本应该是这样的
git clone git@github.com:myuser/myrepo.git /var/www/
cd /var/www/
node -v && \
yarn && \
yarn build && \
yarn start:prod
上面的脚本应该
1) 将所需的 repo 拉入“托管”目录 2) 检查节点版本 3) 安装 node_modules 并构建原生脚本等 4) 构建生产分布 5) 运行生产 JS 脚本
如果您查看 package.json 文件,您会注意到在使用 yarn start
、yarn start:dev
和 yarn start:prod
时运行的不同脚本。在开发时,您会注意到ts-node
的使用,这是一个打字稿节点运行器类型的东西(不记得正确的短语)。 start:dev
脚本也使用 nodemode 重新启动 ts-node
脚本。您还将看到 start:prod
脚本使用 node dist/main.js
并且 prestart:prod
脚本运行 rm -rf dist && tsc
删除 dist 文件夹并“编译”生产环境所需的 javascript。
但是,没有持续集成的服务器上的 typescript 应用程序的缺点是可能会出现 typescript 编译错误,在运行 prod 脚本之前您不会看到或知道这些错误。我建议在进行部署之前设置一个程序来从 typescript 编译 javascipt,因为您不想在知道下一个版本将构建和运行之前删除当前的 dist 构建!
【讨论】:
在服务器上构建的另一个缺点是 Webpack 需要大量内存来完成 Typescript 类型检查。例如,Node.js 在具有 1GB 内存的 AWS t2.micro 上运行良好,但在构建节点应用程序时,甚至 2GB 内存的服务器也会崩溃。你可以在 webpack 配置中使用transpileOnly: true
。然后应用程序在几秒钟内构建,但您没有类型检查。【参考方案3】:
我们不会在生产环境中构建应用程序,而是在创建 docker 容器时构建它。
我们的步骤大致是:
-
运行
npm install
以及构建应用程序所需的任何工具。
创建docker容器并复制dist/
、node_modules
和package.json
在 docker 容器内运行 npm rebuild bcrypt --update-binary
【讨论】:
这看起来更聪明。您不希望在构建传递给 CI 之后,生产构建最终会出现稍微不同的模块。生产版本应该与 CI 中构建的完全一致,无需从 Internet 下载代码到生产环境。【参考方案4】:对我来说,这种方法很有效,您只需要 dist
文件夹即可:
npm run start:prod
创建应用程序的 prod 版本,这将在应用程序源中创建一个 dist
文件夹
将dist
文件夹复制到您的服务器。
要在您的服务器上获取所有 node_modules
依赖项,只需将您的 package.json
文件复制到 dist
文件夹(您已复制到服务器上),然后从那里运行 npm install
。
如果您使用pm2
运行您的节点应用程序,只需在dist
文件夹中运行pm2 start main.js
【讨论】:
为什么需要将包json复制到dist文件夹中?你也可以从 root 运行 npm install 并在 dist 文件夹中运行你的应用程序。 嗨@Mick 当然你是正确的,如果你不介意你的源代码也在服务器上,你的方法是有效的。但是在您只需要将dist
文件捆绑到您的服务器上的情况下,您提到的方法可能不是一个可行的解决方案。这就是为什么您需要让package.json
安装您的node_modules 以便您使用您的dist
文件运行您的应用程序。我希望这会有所帮助。
我相信,dist
文件夹不包含特定于机器的代码,对吗?【参考方案5】:
只需使用 Nest-CLI 并使用构建
nest build
之后你会得到一个包含已编译代码的 dist 文件夹。 然后,您可以将它放在服务器上运行,例如与 PM2 流程管理器:
production=true pm2 start dist/main.js
在以前的命令中,环境变量 production 设置为 true。那可以例如在通过 HTTPS 运行 Nest.js 服务器时很有用。
如果您想运行 HTTPS 安全服务器,您还必须在服务器的启动过程中包含证书。当环境变量 production 设置为 true 时,证书将包含在 main.ts 中 Nest.js 应用程序的启动过程中,如下所示:
async function bootstrap()
let appConfig =
if (process.env.production)
console.log('process env production: ', process.env.production)
const httpsOptions =
key: fs.readFileSync('/etc/certs/letsencrypt/live/testtest.de/privkey.pem'),
cert: fs.readFileSync('/etc/certs/letsencrypt/live/testtest.de/fullchain.pem'),
// prod config
appConfig =
httpsOptions,
const app = await NestFactory.create<NestExpressApplication>(
AppModule,
appConfig,
)
app.enableCors()
app.setGlobalPrefix('v1')
await app.listen(3300)
bootstrap()
【讨论】:
【参考方案6】:我们将 NX 用于存放 API 的 monorepo。我们将 docker 用于我们的图像和容器。当我们必须创建 docker 镜像时,只运行:npx nx build <project>
,这会在dist/apps/<project>
上生成构建。该文件夹与 package.json 一起进入 docker 映像,仅此而已。您不需要添加 node_modules,因为它们位于 package.json 中。请务必在 Dockerfile 中包含 npm install
。
【讨论】:
以上是关于如何使用 NESTJS 生成 API 的生产版本的主要内容,如果未能解决你的问题,请参考以下文章
如何使用捆绑包中的 node_modules 依赖项正确构建用于生产的 NestJS 应用程序?
从使用 nestjs API 应用程序调试 npm 库(使用 noidejs、nestjs 和 typescript 构建)