构建、打包与制品管理
一、从源码到可部署制品
构建(Build)把源码和依赖变成可运行或可部署的产出:编译、打包、资源处理、测试、生成安装包或镜像。一条典型路径是:拉取源码与依赖 → 编译/转译(如 Java 编译、前端打包)→ 跑测试(可选但建议)→ 打包(jar、war、npm 包、Docker 镜像等)→ 打版本号并上传制品库。制品一旦生成就应可追溯(对应哪次提交、哪条流水线),部署时只取制品、不再在现场重新编译,保证「测的是什么、部署的就是什么」。
二、构建脚本、依赖管理、产物版本化
构建脚本(如 Makefile、Gradle、npm scripts、GitLab CI)把「怎么装依赖、怎么编译、怎么打包」固化下来,任何人或 CI 执行同一脚本得到一致结果。避免手敲命令、避免「在我机器上能跑」。依赖管理用声明式文件(如 package.json、pom.xml、requirements.txt)锁定依赖名称与版本,构建时按文件拉取,不依赖本机已装;可进一步用 lockfile(如 package-lock.json)锁定传递依赖,保证构建可复现。产物版本化:每个制品有唯一版本号(如语义化版本 1.2.3、或 commit SHA、或构建号),便于追溯、回滚与多版本并存;版本号在构建时注入,不手改。
三、制品仓库与不可变构建
制品仓库集中存放构建产物,支持按版本拉取、权限控制、保留策略(如只保留最近 N 个版本)。常见有 Nexus、JFrog Artifactory(通用)、Docker Registry(镜像)、npm registry(前端包)。部署时从仓库取指定版本,不在生产机器上现编。不可变构建指:同一版本号对应的制品内容永不修改;若代码或依赖变了,应生成新版本号、新制品,而不是覆盖旧版本。这样「1.2.3」在任何环境拉到的都是同一份,回滚即拉回旧版本,避免「同名不同内容」的混乱。
不可变构建
同一版本号 = 同一内容,永不覆盖。代码或依赖变更 → 新版本号 → 新制品入库。部署与回滚都按版本拉取,保证「测的即部署的」。
- 版本号与构建一一对应,构建时生成(如 tag、build number、SHA)
- 制品库不覆盖已发布版本;可配置保留策略与清理规则
四、多环境构建一致性
开发、测试、预发、生产应使用同一套构建产物(同一制品版本),仅通过配置(环境变量、配置文件、配置中心)区分环境。若每个环境各自编译或各自打包含入环境差异,就会出现「测试过了生产挂」——因为产物不一致。做法:构建阶段不把环境写死进包,只产出通用制品;部署时按环境注入配置(如数据库连接串、特性开关)。这样同一 jar/镜像 可从测试部署到生产,只有配置不同。
一致:同一制品 + 不同配置
构建一次,产出同一版本制品;部署到各环境时只换配置(DB、URL、开关)。
- 测试与生产用同一镜像/包,仅配置不同
- 避免「在测试能跑、在生产不能」因产物差异导致
不一致:各环境各自构建或包内写死环境
每环境单独编译、或包内写死环境名/连接串,产物不一致,难以保证行为一致。
- 易出现测试通过、生产异常
- 回滚与追溯也困难
一句话: 构建把源码与依赖变成可部署制品,路径为编译→测试→打包→版本化→入库。构建脚本固化步骤,依赖管理与 lockfile 保证可复现,产物版本化便于追溯与回滚。制品仓库集中存储,不可变构建保证同一版本内容不变。多环境用同一制品、只换配置,避免环境间产物不一致。
五、小结
从源码到制品:拉取源码与依赖 → 编译/打包 → 测试 → 打版本 → 入库。构建脚本固化流程,依赖管理与 lockfile 保证可复现,产物版本化用于追溯与回滚。制品仓库集中存、按版本取;不可变构建:同一版本不覆盖。多环境用同一制品、仅配置区分,保证测试与生产产物一致。下一章讲CI/CD 流水线入门,把构建与测试、部署自动化串成流水线。