Rush Stack商店博客活动
跳至主要内容

部署项目

假设您的单体仓库包含一个要部署到 Web 服务器的 Node.js 服务。例如,假设 Node.js 服务是一个名为 app1 的本地 Rush 项目,并且仓库的组织方式如下

  • apps/app1:
    • 依赖于 ext-lib7(来自 NPM)和 lib3(本地项目)
    • 开发依赖项 ext-tool8(来自 NPM)和 tool6(本地项目)
  • apps/app2: 依赖于 lib3lib4
  • libraries/lib3: 依赖于 lib5
  • libraries/lib4: 没有依赖项
  • libraries/lib5: ext-lib7 的对等依赖项
  • tools/tool6: 没有依赖项

一种解决方案可能是运行 rush installrush build,然后将整个单体仓库复制到服务器。但是,这可能会包含许多无关的文件和 NPM 包。相反,我们希望只复制 app1 及其常规依赖项(ext-lib7lib3lib5)。我们不希望包含开发依赖项,例如 ext-tool8

rush deploy 命令会计算此文件集并将它们复制到目标文件夹,然后您可以将它们上传到服务器。

配置“rush deploy”

rush deploy 命令从一个配置文件 common/config/rush/deploy.json 中读取其设置。此配置文件不是由 rush init 创建的。相反,您使用 rush init-deploy 创建该文件。

继续我们的示例,我们可以使用以下命令创建该文件

# Create common/config/rush/deploy.json and configure it to deploy "app1"
rush init-deploy --project app1

创建 deploy.json 文件后,在您的编辑器中打开它并根据需要调整设置。然后将此文件提交到 Git。

准备部署

要将文件复制到部署目标文件夹,您将使用以下命令

# Install dependencies
rush install

# Build the monorepo
rush build

# Copy app1 and its dependencies to the default target folder: common/deploy/
rush deploy

这将通过将 app1 及其依赖项复制到目标文件夹来准备部署。复制的文件将类似于单体仓库的文件夹结构组织

  • common/deploy/apps/app1/...
  • common/deploy/common/temp/node_modules/ext-lib7/...
  • common/deploy/libraries/lib3/...
  • common/deploy/libraries/lib4/...

您可以通过在部署目标文件夹中执行 app1 来测试部署是否正确

# Change to the app1 location under the target folder
cd common/deploy/apps/app1

# Invoke the package.json script that starts the web service
rushx start

如果项目无法运行(但在其原始位置 apps/app1 中运行正常),那么您可能需要调整 deploy.json 中的设置。确认项目正常运行后,下一步是将 common/deploy 子树上传到您的服务器。

common/deploy 子树将包含 rush install 创建的符号链接。例如,如果您使用的是 PNPM 包管理器,那么 common/deploy/apps/app1/node_modules/ext-lib7 可能是指向 common/deploy/common/temp/node_modules/.pnpm/... 路径下某个文件夹的符号链接。正确复制这些链接对于 tarftp 等上传工具来说可能很麻烦。

deploy.json 配置文件提供了一个名为 linkCreation 的设置,它提供用于处理链接的选择

  • "default": 在复制文件时创建链接;这是默认行为。如果您的文件复制工具可以正确处理链接,请使用此设置。
  • "script": 一个名为 create-links.js 的 Node.js 脚本将被写入目标文件夹。使用此设置在服务器上创建链接,在文件上传后。
  • "none": 不执行任何操作;一些其他工具可能会稍后根据 deploy-metadata.json 文件创建链接。

deploy-metadata.json 文件被写入到部署目标文件夹,并包含需要创建的链接的完整清单。它可能看起来像这样

{
"scenarioName": "deploy.json",
"mainProjectName": "app1",
"links": [
{
"kind": "folderLink",
"linkPath": "common/deploy/apps/app1/node_modules/ext-lib7",
"targetPath": "common/deploy/common/temp/node_modules/.pnpm/registry.npmjs.org/ext-lib7/1.0.0/node_modules/ext-lib7"
},
. . .
]
}

如果您指定 "linkCreation": "script",那么 rush deploy 将创建 common/deploy 文件夹,没有任何链接。在将此文件夹上传到服务器后,您可以执行脚本以创建链接

# Invoke this command on the server machine, after the files have been uploaded
node create-links.js create

注意:当使用 "linkCreation": "script" 时,当前的实现尚未生成 node_modules/.bin 命令行二进制文件。如果您有兴趣贡献修复,请参阅 此 PR 评论 以获取建议的解决方案。

包含其他项目

继续我们的示例,假设我们要将 app1app2 一起作为单个部署包含进来。由于 app2 不是 app1 的依赖项,因此它不会被自动包含。我们可以将 app1 视为“主项目”(列在 deploymentProjectNames 中),然后将 app2 声明为“附加项目”。配置文件如下所示

common/config/rush/deploy.json

{
. . .
// The main project
"deploymentProjectNames": ["app1"],
. . .
"projectSettings": [
{
"projectName": "app1",

// When deploying "app1", include "app2". We need to add this explicitly because
// "app2" is not a dependency of "app1".
"additionalProjectsToInclude": [ "app2" ]
}
]
}

使用同一个配置文件进行多次部署

继续我们的示例,假设我们希望将 app1app2 分别部署到两个不同的 Web 服务器。如果设置相同,我们只需将它们都添加到 deploymentProjectNames 数组中,如下所示

common/config/rush/deploy.json

  . . .
"deploymentProjectNames": [ "app1", "app2" ],
. . .

在执行部署时,--project 参数将选择要部署的项目。例如

# Copy app1 and its dependencies to /mnt/deploy/app1
rush deploy --project app1 --target-folder /mnt/deploy/app1

# Copy app2 and its dependencies to /mnt/deploy/app2
rush deploy --project app2 --target-folder /mnt/deploy/app2

--target-folder 参数将文件复制到自定义位置,而不是 common/deploy/ 默认文件夹。

使用不同的配置文件进行多次部署

继续我们的示例,假设 app2 是独立部署的,并且它需要与 app1 不同的设置。例如,假设我们希望对 app1 使用 "linkCreation": "default",但对 app2 使用 "linkCreation": "script"。我们将创建两个配置文件

  • common/config/rush/deploy.json - 默认情况下的文件,我们将用于 app1
  • common/config/rush/deploy-app2-example.json -- app2-example 场景,我们将用于 app2

这两个文件都可以使用 rush init-deploy 创建

# Create common/config/rush/deploy.json
rush init-deploy --project app1

# Create common/config/rush/deploy-app2-example.json
rush init-deploy --project app2 --scenario app2-example

在编辑 deploy-app2-example.json 以指定 "linkCreation": "script" 后,我们现在可以使用 rush deploy--scenario 参数

# Copy app1 and its dependencies to /mnt/deploy/app1
# Uses scenario file: common/config/rush/deploy.json
rush deploy --target-folder /mnt/deploy/app1

# Copy app2 and its dependencies to /mnt/deploy/app2
# Uses scenario file: common/config/rush/deploy-app2-example.json
rush deploy --target-folder /mnt/deploy/app2 --scenario app2-example

请注意,rush deploy 不需要 --project 参数,因为每个配置文件在其 "deploymentProjectNames" 数组中只有一个项目。

另请参阅