4. 构建工具选择:Maven / Gradle / npm
CI 流水线里的第一关,往往就是构建。说白了,你要先把代码变成能跑的东西。工具选不对,后面全是坑。我早期带团队时,就因为一个项目混用了 Maven 和 Gradle 的插件版本,CI 上跑了整整两个钟头没跑通。后来我养成了一个习惯:在搭建流水线之前,先把构建工具定死。
4.1 Maven:稳重但有点啰嗦的老大哥
Maven 的特点是“约定优于配置”。你只要把项目结构摆好,它自己就知道怎么编译、测试、打包。pom.xml 里声明依赖,它就去中央仓库拉。很多 Java 老项目都用它。
我在一个金融项目里遇到过 Maven 的依赖地狱。两个 jar 包冲突,CI 上每次构建都跑错。后来用了 mvn dependency:tree 才揪出罪魁祸首。
<!-- pom.xml 典型配置 -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
</project>
-U 强制更新快照,但别默认开启。
4.2 Gradle:快,灵活,但别让它“灵活”过头
Gradle 用的是 Groovy 或 Kotlin DSL,比 Maven 那种 XML 清爽多了。它支持增量编译,只改一个类只重编那个类,CI 上构建速度能快一倍。Android 项目基本全是 Gradle。
我个人习惯在 Gradle 里用 buildCache,尤其是在多模块项目里。有一次我们 CI 上跑 40 个模块,没开缓存,每次全量编译花了 12 分钟。开了之后缩到 4 分钟。
// build.gradle.kts 片段
plugins {
java
id("org.springframework.boot") version "3.2.0"
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
}
tasks.withType<Test> {
useJUnitPlatform()
}
--build-cache 参数,配合远程缓存(比如 Redis)效果更好。但记得先跑一遍完整构建预热缓存。
不过 Gradle 太灵活了,有些团队会写出各种自定义 Task,最后连构建顺序都理不清。你想想看,一个 Task 里加了 dependsOn,另一个又 mustRunAfter,相互嵌套,调试起来头都大。我的建议是:能用插件解决的,就别自己写 Task。
4.3 npm:前端的标配,但锁文件要盯紧
Node.js 项目里,npm 基本是事实标准。package.json 定义依赖和脚本,CI 上跑 npm ci 代替 npm install,能保证一致性且更快。
npm ci 依赖 package-lock.json,如果锁文件没提交到 Git,CI 会直接失败。我一个同事就因为这个,每次构建版本都不一样……
{
"name": "my-frontend",
"scripts": {
"build": "vite build",
"test": "vitest run",
"lint": "eslint src/"
},
"devDependencies": {
"vite": "^5.0.0",
"vitest": "^1.0.0"
}
}
--no-audit 参数,每次构建还要跑安全审计,拖慢 3 分钟。后来加上了 npm ci --no-audit --no-fund,速度明显提升。如果你需要审计,单独在另外的流水线阶段做。
4.4 选型对比一览
下面这个表格是我多年经验总结的,你直接拿去用就行:
| 特性 | Maven | Gradle | npm |
|---|---|---|---|
| 语法稿 | XML 声明式 | Groovy / Kotlin 编程式 | JSON + 脚本 |
| 构建速度 | 中等(全量编译为主) | 快(增量编译 + 缓存) | 中等(取决于依赖树) |
| 学习曲线 | 低(约定多,配置少) | 中高(DSL 灵活,但也复杂) | 低(只用脚本就够) |
| 生态 | Java 领域极强 | Java + Android 标准 | Node.js / 前端统治 |
| CI 配置复杂度 | 低(直接跑 mvn 命令) | 中(需要调参数) | 低(npm ci 搞定) |
| 推荐项目 | 企业 Java、Spring 单体 | Android、大型多模块 Java | 前端、Node.js 服务、全栈 |
4.5 构建工具知识图谱
下面这张图帮你理清选择逻辑:从项目类型出发,看语言和生态,最终落到工具上。箭头上的灰色标签是场景说明。
说实话,没有银弹。我见过一个团队固执地用 Maven 做 Android 项目,结果配置极其痛苦,后来换 Gradle 才轻松。也见过有人用 Gradle 写一个只有 3 个类的简单服务,杀鸡用牛刀。嗯,这里要记住:选工具不是炫技,而是看你的项目规模、团队熟悉度和 CI 环境支持。