关注「索引目录」公众号,获取更多干货。
一名拥有8 年经验的前端工程师,主要使用React 和Next.js。
在本系列文章中,我将根据大规模运行 CI/CD 的实际经验,指导您如何为 Next.js 应用程序设置一个全面的、生产级的 GitLab CI/CD 流水线。
在第一部分中,我们将重点介绍如何构建快速安全的验证流程,包括:
-
绒毛 -
类型检查 - 使用PNPM
实现环境感知缓存 -
经济高效的 GitLab CI/CD 执行
如果你还没读过,不妨从以下这本开始:
👉 Next.js 的 GitLab CI/CD — 第 0 部分:项目和仓库设置
一、设置验证任务(代码检查、类型检查)
首先,我们需要准备以下文件:
.gitlab.yml
在项目根目录下定义 CI 流水线和验证作业。 templates/node-job.yml
准备 Node.js Alpine 镜像并设置PNPM 存储缓存。
参考
- GitLab CI/CDextends
- GitLab CI/CD 缓存
.gitlab.yml
---
stages:
- validate
include:
- local: "templates/node-job.yml"
validate:
stage: validate
extends: .node-job # inherit from node-job template
needs: [] # trigger this job immediately
script:
- pnpm install --frozen-lockfile --ignore-scripts --prefer-offline
- pnpm lint
- pnpm check-types
目前,我们已经建立了一个基本的验证流程,以确保代码质量后再继续进行。
templates/node-job.yml
参考
- 在 GitLab CI/CD 上配置 PNPM
- GitLab 预定义变量
---
.node-job:
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/node:22.20.0-alpine3.22
variables:
PNPM_STORE_KEY: $CI_PROJECT_DIR/.pnpm-store
before_script:
- corepack enable && corepack prepare pnpm@10 --activate
- pnpm --version
- pnpm config set store-dir $PNPM_STORE_KEY
- export PNPM_HOME="$CI_PROJECT_DIR/.pnpm"
- export PATH="$PNPM_HOME:$PATH"
太好了!我们的验证任务已经成功设置。
现在提交代码并运行第一个流水线吧。
-
整个流程耗时36 秒,其中依赖项安装大约耗时8.1 秒👍
接下来,我们将通过引入GitLab CI/CD 缓存以及基于环境的变量来进一步改进这一点,以避免开发、测试和生产环境之间出现缓存冲突或意外变更。
在实际项目中,CI/CD 的成本和执行时间至关重要。
对每次提交都进行验证很快就会变得繁琐、缓慢且成本高昂。
新增:创建templates/rules.yml
参考
- 语义版本控制
---
.rules_dev:
rules:
- if: $CI_COMMIT_REF_SLUG == "develop"
.rules_staging:
rules:
- if: $CI_COMMIT_TAG =~ /^staging-\d+\.\d+\.\d+$/
.rules_prod:
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
.rules_protected:
rules:
- if: '$CI_COMMIT_REF_SLUG == "develop"'
- if: '$CI_COMMIT_TAG =~ /^staging-\d+\.\d+\.\d+$/'
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
我们定义了一些规则来控制CI/CD 作业何时运行。
验证任务仅在以下情况下触发:
-
代码已合并到 develop分支中 -
已创建一个暂存标签 staging-1.0.0(例如) -
已创建生产标签(例如 v1.0.0)
在其他所有情况下,管道都不会运行——这有助于我们节省 CI 时间并减少不必要的成本。
更新:.gitlab.yml
---
include:
- local: "templates/node-job.yml"
- local: "templates/rules.yml" # include rules template
# Convert validate job into a reusable template
.validate_job:
stage: validate
# old config...
cache:
policy: pull-push # allow validate jobs to revalidate cache when needed
# Validate Dev
validate_dev:
extends:
- .validate_job
- .rules_dev
variables:
ENV: "dev"
# Validate Staging
validate_staging:
extends:
- .validate_job
- .rules_staging
variables:
ENV: "staging"
# Validate Prod
validate_prod:
extends:
- .validate_job
- .rules_prod
variables:
ENV: "prod"
我们现在为每个环境定义单独的验证作业:
每项工作:
-
仅当使用正确的分支或标签时运行。 -
使用特定于环境的变量进行隔离 -
防止PNPM 缓存跨环境污染
更新:(templates/node-job.yml缓存配置)
---
.node-job:
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/node:22.20.0-alpine3.22
cache:
key:
files:
- pnpm-lock.yaml
prefix: $ENV
paths:
- $PNPM_STORE_KEY
policy: pull
分解
- PNPM 存储缓存:
我们缓存了包含所有已下载依赖项的PNPM 存储。我们不直接缓存 node_modulesPNPM 存储,因为压缩和传输它成本高昂且通常速度较慢。
如果您想了解PNPM 为何如此出色,请查看:
👉 PNPM 内容寻址存储 (Content-Addressable Store) 在 macOS 上似乎出现故障
- 默认缓存策略:
pull
扩展作业 node-job只能从缓存中读取数据,防止意外修改缓存。 - 缓存前缀:
$ENV
按环境(开发/测试/生产)限定缓存范围,以避免冲突和并发问题。 - 缓存文件:
pnpm-lock.yaml仅当依赖项发生变化时
才会重新验证缓存,从而保持其稳定性和可预测性。 CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX
允许 GitLab直接从 GitLab 注册表拉取镜像和缓存层,而不是访问 Docker Hub 或 AWS ECR。
我们提交代码并检查缓存行为。
由于需要下载、提取和推送缓存,管道在第一次运行时完成速度略慢(约 41 秒)。
但是请注意依赖项安装时间:约 2.1 秒🚀
这比不使用缓存快 4 倍以上。
随着项目的发展node_modules壮大,这种方法可以节省大量的持续集成时间和成本,尤其是在单元测试、端到端测试和未来的流水线阶段中重复使用时。
概括
在第 1 部分中,我们重点介绍了如何使用 GitLab CI/CD 为 Next.js 应用程序构建快速、安全且经济高效的验证管道。
我们取得了以下成果:
-
✅ 设置代码检查和类型检查作为早期验证关卡 -
✅ 引入了可重用的 CI 模板 extends -
✅ 应用基于规则的执行方式,仅在有意义的事件(开发、测试、生产)发生时才运行管道。 -
✅ 实现了环境感知型 PNPM 存储缓存,以避免缓存污染 -
✅ 利用GitLab 依赖代理来减少外部注册表流量 -
✅ 依赖项安装时间从约 8 秒缩短至约 2 秒,节省了 CI 时间和成本。
该基础确保只有高质量、类型安全的代码才能继续运行,而不会在每次提交时浪费 CI 时间。
接下来是什么——第二部分:大规模单元测试🚀
在第二部分中,我们将通过引入使用Vitest 的快速且可扩展的单元测试来提升管道水平。
我们将涵盖以下内容:
-
在 GitLab CI/CD 中设置Vitest -
并行运行单元测试 - 测试分片
将大型测试套件拆分到多个作业中 -
重用PNPM 存储缓存,使测试作业运行速度飞快 -
随着代码库的增长,减少总流水线时间
到第二部分结束时,您将拥有一个可用于生产的测试管道,该管道可以随着您的应用程序的扩展而平滑扩展,而不会牺牲速度或成本。
👉敬请期待GitLab CI/CD for Next.js — 第二部分:使用 Vitest 进行单元测试
*完整源代码:*
https://gitlab.com/kelvyn-labs/nextjs-cicd-template
关注「索引目录」公众号,获取更多干货。

