CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
GitHub Actions CI/CD/课时/构建 Next.js platform
RawBlame
课时目录12 节

GitHub Actions CI/CD

  1. 01CI/CD 与 GitHub Actions
  2. 02Workflow 文件结构
  3. 03Jobs 与运行器
  4. 04Steps 与 Actions
  5. 05Secrets 与环境
  6. 06依赖缓存
  7. 07构建 Spring Boot
  8. 08构建 Next.js platform
  9. 09构建推送镜像
  10. 10部署策略
  11. 11PR 检查与分支保护
  12. 12综合练习

构建 Next.js platform

setup-node、npm ci、lint/test/build。

35 分钟

构建 Next.js platform

这一课你将能做到

  1. 写出完整的 platform job:setup-node + npm ci + lint / test / build,工作目录落在 platform/
  2. 处理 Next 构建期的环境变量(如 NEXT_PUBLIC_API_BASE),避免「本机有 .env.local、CI 没有」导致的假红
  3. 说清 CI 验证的是「可生产构建」,与本地 next dev 开发流的区别与分工

为什么要学

本站的 platform 是 npm + Next.js。前端的失败形态和 Java 不同:lint 违规、类型错误、next build 编译期才暴露的问题(导入错路径、页面级类型不匹配、SSR 兼容问题),在 dev 热更新下常被忽略。

CI 里跑一遍 lint + test + build,等于强制「合并前必须能产出生产包」。对 monorepo 而言,它与 backend job 并行,组成完整门禁。

本课给出可粘贴的 job 骨架,并点出 env、lockfile、缓存三个最常见卡点。

先建立图像

job: platform(ubuntu-latest)
  checkout
  setup-node 20 + cache npm(lock: platform/package-lock.json)
  working-directory: platform
    npm ci          ← 按锁文件干净安装
    npm run lint
    npm test
    npm run build   ← 生产构建,最接近「能不能上线」

人话:把 CI 当成一位从不打开 IDE 的前端同事——只认 package-lock.json 与 npm run 脚本。你本地靠 .env.local 的侥幸,他那里没有。

脚本作用CI 是否建议
npm ci按锁文件干净安装是(优于随手 npm i)
lint风格与部分错误是
test单元/组件测是(有则跑)
build生产编译是
dev开发服务器否(不适合当门禁)

跟着做

步骤 1:本地先对齐脚本

cd platform
npm ci
npm run lint
npm test
npm run build

任一失败先本地修。同时确认 package.json 里的脚本名(lint/test/build)与即将写入的 YAML 一致——脚本名对不上是入门常见乌龙。

步骤 2:写入 platform job

jobs:
  platform:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: platform
    steps:
      - name: 拉取代码
        uses: actions/checkout@v4

      - name: 安装 Node 20
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: npm
          # monorepo:锁文件不在仓库根
          cache-dependency-path: platform/package-lock.json

      - name: 干净安装依赖
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: 测试
        run: npm test

      - name: 生产构建
        env:
          # CI 无 .env.local 时给构建期占位,避免缺变量直接炸
          NEXT_PUBLIC_API_BASE: http://localhost:8080
        run: npm run build

与 backend 放同一 ci.yml、不写 needs,即可并行。

步骤 3:验证锁文件纪律

临时把 npm ci 改成 npm install 对比一次(看完改回):npm install 会容忍 lock 与 package.json 漂移,npm ci 则直接报错——这正是它的优点。笔记写:CI 用 npm ci 保卫锁文件,不被「随手 install」漂版本。

步骤 4:故意制造 lint/build 失败

引入一条 eslint 违规(如未使用变量)→ push → 看红在哪个 step;再弄坏一个页面导入,看红移到 build。修回后确认全绿。练习「点开失败 step 直接读日志」,而不是从头翻十分钟下载日志。

步骤 5:认识构建产物(为 Docker 课铺路)

若项目启用 Next 的 standalone 输出,构建后常见:

platform/.next/standalone   ← 可独立运行的 server.js 及最小 node_modules
platform/.next/static       ← 静态资源

本站打包脚本与 Dockerfile 会消费这些产物。CI 本课以「build 成功」为门禁;要不要把 .next 传成 artifact 看下游需求——若 Docker 构建在 CI 里重跑 next build(多阶段构建),则无需传递。

步骤 6:paths 过滤(与第 11 课呼应)

仅改 backend/** 时,可让 platform job 跳过(paths / paths-ignore 或 job 级条件表达式)。入门阶段先两边都跑保证简单;分钟数吃紧再优化。

讲清楚要点

  1. 因为生产环境跑的是 build 产物,所以 CI 必须跑 npm run build——大量错误只在 build 编译期出现,dev 永远发现不了。
  2. 因为依赖版本应可复现,所以提交 package-lock.json 并用 npm ci——与本地「能跑就行」的惯性对抗。
  3. 因为 Next 构建期读 NEXT_PUBLIC_*,所以 CI 要显式提供所需 env——不要假设存在 .env.local(它通常被 gitignore)。
  4. 因为 monorepo 锁文件在子目录,所以 cache-dependency-path 与 working-directory 都要指对——根目录 npm 会装错地方。
  5. 因为 lint/test/build 失败原因不同,所以拆成多个 step——一条 && 糊到底,日志没法定位。
  6. 因为前端 CI 与后端 CI 目标对称,所以与 backend job 并列组成仓库门禁——一边绿不够。

你可能会懵的地方

  1. 「本机 build 过、CI 报缺少 env?」 本机有 .env*.local(不进 Git)。把构建真正需要的变量写进 workflow env,或在仓库维护 .env.example 文档化。注意:NEXT_PUBLIC_* 会被打进客户端产物,所以不要放敏感值。

  2. 「npm ci 报 lock 不同步?」 在 platform/ 重新生成并提交 lock(npm install 一次后提交变更),不要在 CI 里用 npm install 掩盖——那等于放弃版本锁定。

  3. 「只要 lint 绿是不是就够了?」 不够。类型错误、非法导入、服务端组件约束等都在 next build 才爆。门禁必须包含 build。

  4. 「Node 18 还是 20?」 与项目 engines 字段/文档对齐;主路径先钉一版(如 20),需要兼容验证时用 matrix node: [20, 22]。

  5. 「构建时内存不够(OOM)?」 Next 大项目偶见堆内存不足,可加 env: NODE_OPTIONS: --max-old-space-size=4096。托管 runner 7GB 内存,够绝大多数场景;仍 OOM 说明构建本身要瘦身(依赖、图片、未用代码)。

错法对照

错法问题正解
CI 用 npm install 且不提交 lock版本漂移,复现困难提交 lock + npm ci
只跑 lint 不 build假绿,上线才炸lint + test + build
在仓库根执行 npm 脚本找错 package.jsonworking-directory: platform
依赖本机 .env.localCI 缺变量假红workflow env 或 .env.example
把敏感值放进 NEXT_PUBLIC_*打进客户端产物公开可见敏感值走服务端 env / secrets

卡点急救

  1. npm ci 报 lock file ... does not satisfy:lock 与 package.json 不同步。本地在 platform/ 跑一次 npm install,提交更新的 package-lock.json;顺带检查是不是有人手改了 package.json 没装。
  2. build 报 NEXT_PUBLIC_XXX is not defined 或行为异常:列出项目构建期真正读取的公开变量,全部写进 build step 的 env;区分构建期(NEXT_PUBLIC_*)与运行期(服务端 process.env)变量,前者必须 build 时存在。
  3. 构建耗时从 2 分钟涨到 10 分钟:先看是否缓存 miss(lock 变更属正常);再看是否新增了巨型依赖或开启了未用的分析/追踪;必要时把 lint 与 build 拆成并行 job 缩短墙钟。

面试常问

  • npm ci 和 npm install 有什么区别?CI 里为什么用 ci? npm install 按 package.json 解析并可能更新 lock;npm ci 严格按 lock 全新安装,lock 与 manifest 不一致时直接失败。CI 要的是可复现:同一 lock 永远装出同一依赖树,还能顺带把「lock 忘了提交」这种问题在 PR 阶段暴露。

  • Next.js 的 NEXT_PUBLIC_* 环境变量有什么特殊性?对 CI 有什么要求? 以 NEXT_PUBLIC_ 开头的变量在构建时被内联进客户端产物,所以必须在 next build 时可用且会随构建固化——运行时改环境变量不生效,敏感值绝不能放这里。因此 CI 的 build step 要显式提供这些变量(或约定默认值),并且构建用的值要与部署环境约定一致。

  • 前端 CI 门禁应该包含哪些环节?为什么? 依赖安装(npm ci 保可复现)→ lint(秒级,便宜检查放前面)→ 测试(单元/组件)→ 生产构建(catch 类型与编译期错误)。顺序遵循「便宜的先跑」:lint 3 秒挂掉就不浪费后面几分钟的 build。如果产出镜像,build 可挪进 Docker 多阶段构建,CI 门禁至少保证能产出可运行包。

自测三问

  1. 为什么 CI 推荐 npm ci 而不是 npm install?
  2. platform job 建议的四个命令阶段是什么?顺序为什么这样排?
  3. monorepo 里 cache-dependency-path 应指向哪个文件?

小结一句话

npm ci + lint + test + build(含必要的构建期 env)是本站 Next.js 前端 CI 四件套。

延伸

  • Building and testing Node.js
  • Next.js — Production Optimization
  • 下一课:构建推送镜像——把两端产物变成可部署的 Docker 镜像。
加载本节练习…
← 上一课构建 Spring Boot下一课 →构建推送镜像