如何使用NESTJS生成API的生产版本?

25

我正在使用NESTJS框架生成API的生产版本,并想知道应上传哪些文件到服务器。当我运行“npm run start: prod”编译时,它会生成“dist”文件夹,但我尝试只使用它运行,但这不足以运行我的应用程序。我需要上传所有文件到服务器吗?我尝试删除开发过程中使用的文件夹进行多次测试,但只有在开发模式下全部相同的情况下才能以生产模式运行。

我查看了文档,但没有找到相关内容。有人可以帮帮我吗?

谢谢。

6个回答

15

说实话,你只需要使用dist文件夹,因为那里是JS编译后的文件。通常情况下,运行应用程序会使用这个命令 node dist/main.js。至于上传哪些文件,取决于你自己。我个人经常使用持续集成,所以我只需将存储库克隆到我的容器/服务器上,并使用yarn start:prod。这样每次部署时都会生成在生产环境下运行所需的文件。

像@Kim Kern提到的那样,一些Node模块是使用node-gyro本地构建的;因此,在部署时最好在服务器/容器上构建你的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拉到“hosted”目录中 2)检查node版本 3)安装node_modules并构建本地脚本等 4)构建生产分发 5)运行生产JS脚本
如果您查看package.json文件,您会注意到使用"yarn start"、"yarn start:dev"和"yarn start:prod"时运行的不同脚本。在开发模式下,您会注意到使用了"ts-node",这是一种typescript节点运行器类型的东西(记不清确切的短语了)。此外,"start:dev"脚本使用nodemode重新启动"ts-node"脚本。您还将看到"start:prod"脚本使用"node dist/main.js",而"prestart:prod"脚本运行"rm -rf dist && tsc",它删除dist文件夹并“编译”生产环境所需的javascript。
然而,在没有持续集成的情况下,typescript应用程序在您的服务器上存在的缺点是可能会出现typescript编译错误,直到运行生产脚本之前您才会注意到或知道它们。我建议在部署之前放置一个步骤来从typescript编译javascipt,因为您不想在知道下一个发布版本能够构建和运行之前删除当前的dist构建!

4
在服务器上构建的另一个缺点是Webpack完成TypeScript类型检查需要大量的内存。例如,Node.js在拥有1GB RAM的AWS t2.micro上运行良好,但是构建节点应用程序时,甚至2GB RAM的服务器都会崩溃。您可以在Webpack配置中使用 transpileOnly: true。这样,应用程序将在几秒钟内构建,但是没有进行类型检查。 - Mick

15

这种方法对我有用,你只需使用dist文件夹即可实现:

  • 使用npm run start:prod创建应用程序的生产版本,这将在应用程序源中创建dist文件夹
  • dist文件夹复制到您的服务器上。
  • 要在服务器上获取所有的node_modules依赖项,只需将package.json文件复制到您已复制到服务器的dist文件夹中,然后从那里运行npm install
  • 如果您正在使用pm2运行您的node应用程序,只需在dist文件夹内运行pm2 start main.js

为什么需要将package.json复制到dist文件夹中?您可以从根目录运行npm install,并从根目录中的dist文件夹运行应用程序。 - Mick
1
嗨,@Mick,当然你是正确的,如果你不介意在服务器上也有源代码,那么你的方法是可行的。但在需要仅将“dist”文件捆绑到服务器的情况下,你提到的方法可能不是一个可行的解决方案。这就是为什么你需要使用package.json来安装你的node_modules,以便你可以使用你的dist文件运行应用程序。希望这可以帮助到你。 - Sandeep K Nair
我相信,“dist”文件夹不包含机器特定的代码,对吗? - Mizanur Rahman Mojumder
pm2 + dist 是干净的 - undefined

7

只需使用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()

5
大多数情况下,您只需要使用node_modules中的依赖项。但是,您应该在服务器上构建库,而不是从开发机器复制它们。像bcrypt这样的库具有特定于机器的代码,可能无法在其他机器上运行。(npm库的30%具有本地绑定。)
因此,在部署时,我建议您在服务器上检出git存储库,然后直接在那里运行npm run start:prod(每次都会构建项目)。

3
哦,六个小时后我看到了你的“机器特定”短语。我希望早点知道那个词。谢谢! - Arda Oğul Üçpınar
在服务器上构建的一个缺点是Webpack需要大量内存才能完成Typescript类型检查。例如,Node.js在AWS t2.micro上运行良好,只需1GB RAM,但构建节点应用程序时,即使是2GB RAM的服务器也会崩溃。您可以在Webpack配置中使用transpileOnly: true。然后应用程序可以在几秒钟内构建,但没有类型检查。最好的选择可能是在部署之前构建JavaScript,但在服务器上运行npm/yarn安装? - Mick

3
我们不会在生产环境上构建应用程序,而是在创建docker容器时进行构建。
我们的大致步骤如下:
1. 运行`npm install`和任何需要构建应用程序的工具。 2. 创建docker容器并复制`dist/`、`node_modules`和`package.json`。 3. 在docker容器内运行`npm rebuild bcrypt --update-binary`。

1
这似乎更加智能。您不希望在CI通过构建后,生产构建最终出现略有不同的模块。生产构建应该完全与CI中构建的内容相同,不应从互联网下载任何代码到生产环境中。 - Mark Stosberg

0

我们在使用NX作为我们API存储的单库,并且我们使用docker来制作我们的镜像和容器。当我们需要创建docker镜像时,只需运行:npx nx build <project>,这将在dist/apps/<project>上生成构建。此文件夹将与package.json一起放入docker镜像中即可。你不需要添加node_modules,因为它们已经在package.json中了。只需确保在Dockerfile中包含npm install


npm install 的注意事项是,除非您固定版本,否则它不会安装与 package.json 中定义的完全相同的版本。最好运行 npm ci --production 并将 node_modules 复制到镜像中 - 这将保证一致的版本。在您有 "lib": "^1.0.0" 的地方运行 npm install 将升级 "lib"v1.0.1,我曾经遇到过 mongoose 在补丁版本上引入破坏性更改的情况。 - Ash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接