如何使用 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 startyarn start:devyarn 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_modulespackage.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 &lt;project&gt;,这会在dist/apps/&lt;project&gt; 上生成构建。该文件夹与 package.json 一起进入 docker 映像,仅此而已。您不需要添加 node_modules,因为它们位于 package.json 中。请务必在 Dockerfile 中包含 npm install

【讨论】:

以上是关于如何使用 NESTJS 生成 API 的生产版本的主要内容,如果未能解决你的问题,请参考以下文章

如何在nestjs中禁用swagger进行生产

如何使用捆绑包中的 node_modules 依赖项正确构建用于生产的 NestJS 应用程序?

@nestjs/swagger:如何添加 API URL?

NestJS swagger 生成的文档不显示参数信息

从使用 nestjs API 应用程序调试 npm 库(使用 noidejs、nestjs 和 typescript 构建)

如何在 nrwl monorep 中调试 NestJS 应用程序