HarmonyOS开发:自动化构建
HarmonyOS开发:自动化构建
📌 核心要点:hvigorw是鸿蒙的构建引擎——搞懂它的命令体系、缓存机制和产物管理,构建速度能从5分钟压到1分钟以内。
背景与动机
你有没有数过,从点击"运行"到应用安装到设备上,要等多久?
一个小项目可能30秒就搞定了。但项目一大,模块一多,3分钟、5分钟甚至10分钟都有可能。一天构建20次,光等构建就花了一个多小时。更别提CI环境里,构建慢意味着流水线排队,团队效率直接拉胯。
构建慢的常见原因:
- 依赖重复下载:每次构建都重新拉ohpm包
- 全量编译:改了一个文件,整个项目重新编译
- 产物混乱:不知道哪些产物有用、哪些可以清理
- 配置低效:多模块项目没有优化构建顺序
这些问题不是DevEco Studio的锅,而是你没搞懂底层构建工具hvigorw的脾气。它就像一个厨师——你给它正确的食材和步骤,它出菜很快;你瞎指挥,它就只能慢工出细活。
核心原理
hvigorw是HarmonyOS的构建命令行工具,底层基于Node.js,用TypeScript编写构建脚本。它和Android的Gradle定位类似,但架构完全不同。
flowchart TB
A[hvigorw命令] --> B{解析参数}
B --> C[加载hvigor-config.json5]
C --> D[初始化构建图]
D --> E[解析模块依赖]
E --> F[执行Task]
F --> G[预处理]
G --> H[编译ArkTS]
H --> I[打包资源]
I --> J[生成HAP/APP]
J --> K{产物类型}
K -->|HAP| L[单模块安装包]
K -->|APP| M[上架发布包]
K -->|HAR| N[共享库包]
classDef cmd fill:#E17055,stroke:#D63031,color:#fff
classDef process fill:#00CEC9,stroke:#00B894,color:#fff
classDef product fill:#6C5CE7,stroke:#5B4BC9,color:#fff
classDef decision fill:#FFEAA7,stroke:#FDCB6E,color:#333
class A cmd
class B,C,D,E,F,G,H,I process
class J,K decision
class L,M,N product
hvigorw的核心概念:
| 概念 | 说明 | 类比 |
|---|---|---|
| Task | 最小构建单元 | Gradle的Task |
| Module | 构建模块 | Android的Module |
| Product | 构建产物配置 | Gradle的Product Flavor |
| Mode | 构建模式(module/rebuild) | Gradle的Build Type |
| Plugin | 构建插件 | Gradle Plugin |
构建命令的基本格式:
hvigorw [task] --mode [mode] -p module=[module] -p product=[product]
代码实战
基础用法:hvigorw构建命令
先掌握最常用的构建命令,这是自动化的基础。
# ===== 最基础的构建命令 =====
# 构建HAP(单模块安装包,用于调试和安装)
./hvigorw assembleHap
# 构建APP(上架发布包,包含所有模块)
./hvigorw assembleApp
# 构建HAR(共享库,供其他模块引用)
./hvigorw assembleHar
# ===== 指定模块和产品 =====
# 构建指定模块的HAP
./hvigorw assembleHap --mode module -p module=entry@default -p product=default
# 构建指定模块的APP
./hvigorw assembleApp --mode module -p module=entry@default -p product=default
# ===== 清理命令 =====
# 清理构建产物
./hvigorw clean
# 彻底清理(包括缓存)
./hvigorw clean --no-daemon
# ===== 其他常用命令 =====
# 查看所有可用Task
./hvigorw --list
# 查看构建帮助
./hvigorw --help
# 查看版本信息
./hvigorw --version
# 干跑模式(不实际执行,只显示会做什么)
./hvigorw assembleHap --dry-run
这里有个重要细节:--mode module和默认模式的区别。
- 默认模式:构建所有模块,适合全量构建
--mode module:只构建指定模块,适合增量构建和CI环境
CI环境里一定要用--mode module,不然10个模块全量构建,时间直接翻倍。
进阶用法:多模块构建配置
真实项目通常是多模块的:entry主模块 + feature功能模块 + shared共享库。构建顺序和配置直接影响效率。
// build-profile.json5 - 多模块构建配置
{
"app": {
"signingConfigs": [],
"products": [
{
"name": "default",
"signingConfig": "default",
"compatibleSdkVersion": "5.0.0(12)",
"runtimeSdkVersion": "5.0.0(12)",
"buildOption": {
// 构建优化配置
"strictMode": {
"useNormalizedOhmUrl": true // 严格模式,依赖URL规范化
},
// ArkTS编译优化
"arkOptions": {
"compilerOptions": {
"sourceMap": false // 生产构建关闭sourceMap,加快编译
}
}
}
},
{
// 开发调试配置
"name": "debug",
"signingConfig": "debug",
"buildOption": {
"arkOptions": {
"compilerOptions": {
"sourceMap": true // 调试构建开启sourceMap
}
}
}
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{ "name": "default", "applyToProducts": ["default", "debug"] }
]
},
{
"name": "feature_home",
"srcPath": "./features/home",
"targets": [
{ "name": "default", "applyToProducts": ["default", "debug"] }
]
},
{
"name": "shared_utils",
"srcPath": "./shared/utils",
"targets": [
{ "name": "default", "applyToProducts": ["default", "debug"] }
]
}
]
}
多模块项目的构建脚本,关键是控制构建顺序:
#!/bin/bash
# multi_module_build.sh - 多模块构建脚本
set -e
echo "===== 开始多模块构建 ====="
START_TIME=$(date +%s)
# 第一步:构建共享库(其他模块依赖它)
echo "📦 构建共享库模块..."
./hvigorw assembleHar --mode module -p module=shared_utils@default -p product=default --no-daemon
# 第二步:并行构建功能模块(它们之间互不依赖)
echo "📦 构建功能模块..."
./hvigorw assembleHap --mode module -p module=feature_home@default -p product=default --no-daemon
# 第三步:构建入口模块并打包APP
echo "📦 构建入口模块..."
./hvigorw assembleApp --mode module -p module=entry@default -p product=default --no-daemon
END_TIME=$(date +%s)
ELAPSED=$((END_TIME - START_TIME))
echo "✅ 构建完成,耗时: ${ELAPPED}秒"
完整示例:构建缓存优化与产物管理
构建缓存是提速的关键。hvigorw支持增量构建,但需要正确配置。
// hvigorfile.ts - 构建缓存优化配置
import { hapTasks, appTasks, harTasks, OhosHarContext, OhosHapContext, OhosAppContext } from '@ohos/hvigor-ohos-plugin';
// 缓存配置
const CACHE_CONFIG = {
// 启用构建缓存
enableCache: true,
// 缓存目录(CI环境建议用共享目录)
cacheDir: process.env.CI ? '/cache/hvigor-cache' : '.hvigor/cache',
// 缓存最大大小(MB)
maxCacheSize: 2048,
};
// 构建产物管理
export default {
system: appTasks,
plugins: [{
// 自定义构建插件:产物清理和归档
apply() {
this.registerTask({
name: 'archiveProduct',
run: () => {
console.log('📦 归档构建产物...');
const fs = require('fs');
const path = require('path');
// 产物目录
const outputDir = 'entry/build/default/outputs/default';
const archiveDir = `archive/${Date.now()}`;
if (fs.existsSync(outputDir)) {
fs.mkdirSync(archiveDir, { recursive: true });
// 复制HAP文件
const files = fs.readdirSync(outputDir);
files.forEach(file => {
if (file.endsWith('.hap') || file.endsWith('.app')) {
fs.copyFileSync(
path.join(outputDir, file),
path.join(archiveDir, file)
);
console.log(` ✅ 归档: ${file}`);
}
});
// 写入构建信息
const buildInfo = {
timestamp: new Date().toISOString(),
gitHash: require('child_process').execSync('git rev-parse HEAD').toString().trim(),
nodeVersion: process.version,
};
fs.writeFileSync(
path.join(archiveDir, 'build-info.json'),
JSON.stringify(buildInfo, null, 2)
);
}
}
});
}
}],
buildConfig: {
// 增量构建配置
incrementalBuild: true,
// 并行编译
parallelCompile: true,
// ArkTS编译优化
arkOptions: {
compilerOptions: {
// 生产环境关闭sourceMap
sourceMap: process.env.BUILD_TYPE !== 'release',
// 开启编译缓存
incremental: true,
}
}
}
};
构建产物管理的最佳实践——定期清理、按需归档:
#!/bin/bash
# manage_build_artifacts.sh - 构建产物管理脚本
# ===== 1. 清理过期产物 =====
echo "🧹 清理过期构建产物..."
# 删除7天前的归档
find archive/ -type d -mtime +7 -exec rm -rf {} + 2>/dev/null || true
# 删除构建临时文件
find entry/build/ -name "*.tsbuildinfo" -delete 2>/dev/null || true
# ===== 2. 产物大小分析 =====
echo "📊 构建产物大小分析..."
HAP_FILE="entry/build/default/outputs/default/entry-default-signed.hap"
if [ -f "$HAP_FILE" ]; then
HAP_SIZE=$(stat -f%z "$HAP_FILE" 2>/dev/null || stat -c%s "$HAP_FILE" 2>/dev/null)
HAP_SIZE_MB=$((HAP_SIZE / 1024 / 1024))
echo " HAP大小: ${HAP_SIZE_MB}MB"
# 大小阈值检查(超过50MB告警)
if [ $HAP_SIZE_MB -gt 50 ]; then
echo " ⚠️ HAP包超过50MB,请检查资源文件!"
fi
fi
# ===== 3. 产物内容检查 =====
echo "🔍 产物内容检查..."
# 解压HAP检查内容(HAP本质是ZIP格式)
if command -v unzip &> /dev/null; then
TEMP_DIR=$(mktemp -d)
unzip -q "$HAP_FILE" -d "$TEMP_DIR" 2>/dev/null || true
# 检查是否有debug符号
if grep -r "console.log\|console.debug\|console.info" "$TEMP_DIR" --include="*.js" -q 2>/dev/null; then
echo " ⚠️ 发现debug日志,生产构建应移除"
fi
# 检查资源文件大小
LARGE_FILES=$(find "$TEMP_DIR" -type f -size +1M 2>/dev/null)
if [ -n "$LARGE_FILES" ]; then
echo " ⚠️ 发现大文件(>1MB):"
echo "$LARGE_FILES"
fi
# 清理临时目录
rm -rf "$TEMP_DIR"
fi
echo "✅ 产物管理完成"
踩坑与注意事项
坑1:增量构建不生效
改了一行代码,结果全量重新编译了?增量构建没生效通常是因为缓存被破坏。
解决方案:
# 检查缓存状态
ls -la .hvigor/cache/
# 如果缓存损坏,清理后重新构建
./hvigorw clean
./hvigorw assembleHap
# CI环境确保缓存目录持久化
# GitLab CI
cache:
paths:
- .hvigor/cache/
坑2:多模块循环依赖
A模块依赖B模块,B模块又依赖A模块,构建直接死循环。
解决方案:严格按层级划分模块——shared库在最底层,feature模块在中间,entry在最上层。禁止上层模块被下层依赖。
// 模块依赖层级
// Layer 0: shared_utils(纯工具库,不依赖任何模块)
// Layer 1: shared_network(网络库,只依赖shared_utils)
// Layer 2: feature_home(功能模块,依赖shared_utils和shared_network)
// Layer 3: entry(入口模块,依赖所有模块)
坑3:构建产物找不到
构建成功了,但HAP文件不知道去哪了。
解决方案:记住鸿蒙构建产物的标准路径。
项目根目录/
├── entry/
│ └── build/
│ └── default/
│ └── outputs/
│ └── default/
│ ├── entry-default-signed.hap # 签名后的HAP
│ ├── entry-default-unsigned.hap # 未签名的HAP
│ └── entry-default.app # APP包
├── shared_utils/
│ └── build/
│ └── default/
│ └── outputs/
│ └── default/
│ └── shared_utils-default.har # HAR包
坑4:hvigorw版本不一致
本地DevEco Studio用的hvigorw 4.x,CI环境装的是3.x,构建配置不兼容。
解决方案:在项目中锁定hvigorw版本,CI环境使用项目自带的hvigorw。
// hvigor-config.json5
{
"modelVersion": "4.0.2", // 锁定版本
"dependencies": {
"@ohos/hvigor-ohos-plugin": "4.0.2" // 锁定插件版本
}
}
# CI环境使用项目自带的hvigorw,不依赖全局安装
chmod +x ./hvigorw
./hvigorw assembleHap --no-daemon
坑5:构建内存溢出
大项目构建时Node.js进程OOM(Out of Memory),构建直接崩。
解决方案:增加Node.js内存限制。
# 临时增加内存限制
export NODE_OPTIONS="--max-old-space-size=8192"
./hvigorw assembleHap --no-daemon
# 或者在hvigorw脚本中直接修改
# 打开 hvigorw.bat(Windows)或 hvigorw(macOS/Linux)
# 找到 node 命令行,添加 --max-old-space-size=8192
HarmonyOS 6适配说明
HarmonyOS 6对构建系统做了几项重要升级:
-
hvigorw 5.x:新版本构建速度提升约30%,支持更细粒度的增量编译。升级方法:更新
hvigor-config.json5中的modelVersion。 -
ArkCompiler优化:HarmonyOS 6的Ark编译器支持AOT(Ahead-of-Time)编译,构建时可以选择开启AOT以提升运行时性能,但构建时间会增加。
-
多产物配置增强:一个模块可以配置多个Product,支持同时构建手机版和平板版。
-
构建缓存共享:HarmonyOS 6的hvigorw支持分布式缓存,CI集群中的构建节点可以共享缓存,大幅减少重复编译。
-
产物格式优化:新的HAP格式支持更好的压缩率,构建产物体积平均减少10-15%。
总结
构建自动化是CI/CD的基础——构建本身都跑不快、跑不稳,后面的流水线再漂亮也是空中楼阁。
| 维度 | 评价 |
|---|---|
| 学习难度 | ⭐⭐⭐ hvigorw命令不算复杂,但多模块配置和缓存优化需要经验 |
| 使用频率 | ⭐⭐⭐⭐⭐ 每次构建都会用到,是开发效率的直接决定因素 |
| 重要程度 | ⭐⭐⭐⭐⭐ 构建速度影响整个团队的产出效率 |
几个关键提醒:
--mode module是CI标配,别用默认模式全量构建- 缓存配置好,构建快一倍,CI环境记得持久化缓存目录
- 模块依赖要分层,循环依赖是万恶之源
- 产物管理别忽视,定期清理、大小检查、内容审计
- 版本要锁定,本地和CI环境的hvigorw版本必须一致
构建搞定了,下一步是让测试也自动化——每次构建完自动跑测试,有问题立刻知道。
- 点赞
- 收藏
- 关注作者
评论(0)