前言
HarmonyOS 的应用包结构采用了分层模块化设计,将代码和资源组织为 HAP(HarmonyOS Ability Package)、HSP(HarmonyOS Shared Package)和 HAR(HarmonyOS Archive)三种包格式。这种设计使得应用可以按需交付、动态加载,从而显著减小安装包体积并提升启动速度。本文以 小事记(xiaoshiji_ohos_app) 项目的build-profile.json5和oh-package.json5为切入点,深入解析 HAP/HSP/HAR 三种包格式的差异、deliveryWithInstall的交付策略以及多products的构建配置。
核心特点:
- 简单易用:API 设计直观,上手成本低
- 性能优异:底层优化充分,运行效率高
- 扩展性强:支持自定义配置和扩展
本文参考 HarmonyOS 官方文档:application-package-overview.md 和 application-package-structure-stage.md。
一、三种包格式概述
1.1 包格式对比
| 对比维度 | HAP | HSP | HAR |
|---|---|---|---|
| 全称 | HarmonyOS Ability Package | HarmonyOS Shared Package | HarmonyOS Archive |
| 是否可独立运行 | ✅ | ❌ | ❌ |
| 包含代码 | ✅ | ✅ | ✅ |
| 包含资源 | ✅ | ✅ | ✅ |
| 包含配置文件 | ✅ | ✅ | ❌ |
| 依赖方式 | 安装时包含 | 运行时共享 | 编译时静态引用 |
| 多模块共享 | 不共享 | 运行时实例共享 | 编译时代码复制 |
| 典型用途 | 应用主入口、功能模块 | 公共组件库、工具库 | 纯代码库、SDK |
包格式的选择决策树:
需要独立运行? ├── ✅ 是 → HAP (entry / feature) └── ❌ 否 → 需要被多个 HAP 共享? ├── ✅ 是 → 需要运行时实例共享? │ ├── ✅ 是 → HSP(动态共享包) │ └── ❌ 否 → HAR(静态共享包) └── ❌ 否 → HAR(纯代码库)1.2 小事记当前使用的包结构
小事记是一个单模块应用,当前只包含一个entry类型的 HAP 包:
xiaoshiji_ohos_app/ ├── AppScope/ ← 应用级配置 ├── entry/ ← 主 HAP 模块 │ ├── src/main/ │ │ ├── ets/ ← ArkTS 源代码 │ │ ├── resources/ ← 资源文件 │ │ └── module.json5 ← 模块配置 │ ├── build-profile.json5 ← 模块构建配置 │ └── oh-package.json5 ← 模块依赖声明 ├── build-profile.json5 ← 工程级构建配置 ├── oh-package.json5 ← 工程级依赖声明 └── hvigor/ ← 构建工具配置工程的build-profile.json5中modules数组定义了包含的模块:
{ "modules": [ { "name": "entry", "srcPath": "./entry", "targets": [ { "name": "default", "applyToProducts": [ "default" ] } ] } ] }二、HAP(HarmonyOS Ability Package)
2.1 HAP 的两种类型
HAP 是应用的基本交付单元,分为entry和feature两种:
entry 类型— 应用主入口,必须存在且唯一:
// entry/src/main/module.json5 { "module": { "name": "entry", "type": "entry", // 主入口模块 "mainElement": "EntryAbility", // ... } }feature 类型— 按需加载的功能模块:
// feature_share/src/main/module.json5 { "module": { "name": "feature_share", "type": "feature", // 功能模块 "mainElement": "ShareAbility", "deliveryWithInstall": false, // 按需交付 // ... } }2.2 deliveryWithInstall 交付策略
deliveryWithInstall是 HAP 模块的关键属性,决定模块是否随应用安装包一起交付:
| deliveryWithInstall | 安装时行为 | 运行时行为 | 使用场景 |
|---|---|---|---|
true | 随主包一起安装 | 立即可用 | 核心功能、首页 |
false | 不安装,需按需下载 | 使用时通过requestBundleInstall下载 | 低频功能、大资源模块 |
// 按需下载并安装 feature 模块 import { bundleManager } from '@kit.AbilityKit'; async function downloadFeatureModule() { try { const installParam = { bundleFilePath: '', hapModules: [ { moduleName: 'feature_share', hapFilePaths: ['/data/.../feature_share.hap'] } ] }; await bundleManager.requestBundleInstall(installParam); console.log('feature 模块安装成功'); } catch (err) { console.error(`模块安装失败: ${err.message}`); } }2.3 HAP 的构建产物
HAP 的构建产物是.hap文件,实际是一个 ZIP 压缩包,包含:
entry.hap ├── ets/ ← 编译后的字节码 │ └── entryability/ │ └── EntryAbility.abc ├── resources/ ← 资源文件 │ ├── base/ │ │ ├── element/ │ │ ├── media/ │ │ └── profile/ │ └── en_US/ ├── module.json5 ← 模块配置 └── pack.info ← 打包信息三、HSP(HarmonyOS Shared Package)
3.1 HSP 的共享机制
HSP是运行时共享包,多个 HAP 可以同时引用同一个 HSP,运行时只有一份实例,节省内存:
// hsp_common/src/main/module.json5 { "module": { "name": "hsp_common", "type": "hsp", // 动态共享包 // ... } }HSP 的引用方式:
// entry/oh-package.json5 — 在 entry 中引用 HSP { "name": "entry", "version": "1.0.0", "dependencies": { "@xiaoshiji/common": "file:../hsp_common" // 本地路径引用 } }3.2 HSP 与 HAR 的共享区别
| 对比维度 | HSP | HAR |
|---|---|---|
| 编译方式 | 单独编译为 .hsp 文件 | 编译后拷贝到宿主 HAP |
| 运行时实例 | 共享同一个实例 | 各 HAP 各自持有一份拷贝 |
| 代码体积 | 总体积小(不重复) | 总体积大(重复拷贝) |
| 更新方式 | 独立更新 HSP | 需要更新整个 HAP |
| 调试难度 | 需要独立调试 | 调试简单 |
何时选择 HSP 而非 HAR:
- 多个 entry/feature 共享公共代码— 避免代码重复打包导致包体积膨胀
- 公共组件库需要运行时单例— 如主题管理、日志模块
- 需要独立更新组件库— HSP 可以单独发布新版本而不需要更新整个应用
3.3 HSP 的升级路径
如果小事记计划增加一个“分享“功能模块,可以按以下路径将公共组件抽取为 HSP:
# 当前结构(单模块) xiaoshiji_ohos_app/ ├── entry/ ← 所有代码都在 entry 中 # 重构后结构(多模块 + HSP) xiaoshiji_ohos_app/ ├── entry/ ← 主 HAP(保持不变) ├── feature_share/ ← 新增 feature HAP(分享功能) └── hsp_common/ ← 新增 HSP(公共组件) ├── src/main/ets/ │ ├── components/ ← 共享组件 │ ├── utils/ ← 工具函数 │ └── models/ ← 共享数据模型 └── src/main/module.json5四、HAR(HarmonyOS Archive)
4.1 HAR 的静态引用机制
HAR是静态共享包,编译时将其代码和资源复制到宿主 HAP 中,类似 Android 的 AAR 或 iOS 的静态库:
// har_utils/oh-package.json5 { "name": "@xiaoshiji/utils", "version": "1.0.0", "description": "公共工具函数库", "dependencies": {} }在宿主模块中引用:
// entry/oh-package.json5 { "name": "entry", "version": "1.0.0", "dependencies": { "@xiaoshiji/utils": "file:../har_utils" // 静态引用 } }4.2 HAR 的使用限制
- 不支持
module.json5— HAR 不包含配置文件,不能声明 Ability 或 ExtensionAbility - 不支持
$profile资源引用— 配置资源必须在宿主模块中定义 - 不支持页面路由— HAR 中不能包含
@Entry装饰的页面组件 - 资源 ID 冲突— 多个 HAR 中的资源 ID 可能冲突,需要通过
$r('@package:name/xxx')指定包名
// 在 HAR 中引用自己的资源 import { BusinessError } from '@kit.BasicServicesKit'; // 使用 $r 引用 HAR 包内的资源 // 格式:$r('@包名/资源类型:资源名称') let sharedString = $r('@xiaoshiji/utils/string:hello_world');五、oh-package.json5 依赖管理
5.1 工程级与模块级依赖
小事记的依赖管理分为两级:
工程级依赖(根目录oh-package.json5):
// 根目录 oh-package.json5 { "modelVersion": "6.0.2", "description": "Please describe the basic information.", "dependencies": { }, "devDependencies": { "@ohos/hypium": "1.0.25", // 单元测试框架 "@ohos/hamock": "1.0.0" // Mock 测试框架 } }模块级依赖(entry/oh-package.json5):
// entry/oh-package.json5 { "name": "entry", "version": "1.0.0", "description": "Please describe the basic information.", "main": "", "author": "", "license": "", "dependencies": {} }5.2 依赖版本管理
oh-package-lock.json5文件锁定了所有依赖的具体版本,确保构建可复现:
// oh-package-lock.json5(部分内容) { "lockfileVersion": "1.0", "packages": { "@ohos/hypium": { "version": "1.0.25", "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/1.0.25.tgz" }, "@ohos/hamock": { "version": "1.0.0", "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hamock/-/1.0.0.tgz" } } }5.3 依赖类型对比
| 依赖类型 | 配置位置 | 作用域 | 示例 |
|---|---|---|---|
dependencies | 运行依赖 | 编译 + 运行时 | 业务库、组件库 |
devDependencies | 开发依赖 | 仅编译时 | 测试框架、构建工具 |
peerDependencies | 同伴依赖 | 运行时提供 | 插件化框架 |
六、products 构建配置
6.1 多产品变体
build-profile.json5中的products数组定义了应用的不同构建变体:
{ "app": { "products": [ { "name": "default", // 产品名称 "signingConfig": "default", // 签名配置 "targetSdkVersion": "6.0.2(22)", // 目标 SDK 版本 "compatibleSdkVersion": "6.0.2(22)", // 兼容 SDK 版本 "runtimeOS": "HarmonyOS", // 目标操作系统 "buildOption": { "strictMode": { "caseSensitiveCheck": true, // 文件名大小写检查 "useNormalizedOHMUrl": true // 标准化 OHM URL } } } ] } }6.2 多产品场景下的配置
| 产品名称 | 用途 | 签名配置 | 目标 SDK |
|---|---|---|---|
default | 开发调试 | debug 证书 | 最新 SDK |
release | 应用商店发布 | release 证书 | 最低兼容 SDK |
beta | 内测分发 | beta 证书 | 最新 SDK |
// 多产品配置示例 { "app": { "products": [ { "name": "debug", "signingConfig": "debug", "targetSdkVersion": "6.0.2(22)", "compatibleSdkVersion": "5.0.0(12)" }, { "name": "release", "signingConfig": "release", "targetSdkVersion": "6.0.2(22)", "compatibleSdkVersion": "5.0.0(12)" }, { "name": "beta", "signingConfig": "beta", "targetSdkVersion": "6.0.2(22)", "compatibleSdkVersion": "5.0.0(12)" } ] } }6.3 buildModeSet 构建模式
buildModeSet定义了两种构建模式:
{ "buildModeSet": [ { "name": "debug" // 调试模式:未混淆、可调试 }, { "name": "release" // 发布模式:已混淆、不可调试 } ] }debug 与 release 模式的区别:
| 对比维度 | debug | release |
|---|---|---|
| 代码混淆 | ❌ 不混淆 | ✅ 已混淆 |
| 可调试性 | ✅ 可调试 | ❌ 不可调试 |
| 签名证书 | debug 证书 | release 证书 |
| 性能 | 较低 | 较高 |
| 安装方式 | DevEco Studio 直接安装 | 通过应用市场分发 |
七、包体积优化策略
7.1 资源混淆与压缩
| 优化手段 | 节省空间 | 配置方式 | 说明 |
|---|---|---|---|
| 资源混淆 | 10%-15% | arkOptions.obfuscation | 混淆资源名称 |
| 代码混淆 | 20%-30% | obfuscation-rules.txt | 混淆类名、方法名 |
| 图片压缩 | 50%-80% | 使用 WebP 格式 | 替代 PNG/JPG |
| 移除未用资源 | 5%-10% | Lint 检查 | 删除未引用的资源文件 |
7.2 按需交付策略
// 低频功能模块设置为按需交付 { "module": { "name": "feature_ai_generate", "type": "feature", "deliveryWithInstall": false, // 不随安装包交付 "installationFree": false } }7.3 公共代码抽取为 HSP
// 将公共代码抽取为 HSP 避免重复打包 { "module": { "name": "hsp_common", "type": "hsp" } }八、版本号与构建号管理
8.1 版本号的编码规范
小事记的versionCode: 1000000遵循标准的编码规范:
// 版本号编码公式 // versionCode = MAJOR * 1000000 + MINOR * 10000 + PATCH * 100 + BUILD // 1.0.0.0 → 1000000 // 2.3.4.5 → 2030405 function encodeVersion(major: number, minor: number, patch: number, build: number): number { return major * 1000000 + minor * 10000 + patch * 100 + build; } function decodeVersion(versionCode: number): { major: number, minor: number, patch: number, build: number } { return { major: Math.floor(versionCode / 1000000), minor: Math.floor((versionCode % 1000000) / 10000), patch: Math.floor((versionCode % 10000) / 100), build: versionCode % 100 }; }8.2 版本更新策略
| 场景 | versionCode 变化 | versionName 变化 | 是否强制更新 |
|---|---|---|---|
| 修复 Bug | +1 | 1.0.0.x → 1.0.0.y | ❌ |
| 新增功能 | +100 | 1.0.x → 1.0.y | ❌ |
| 重大变更 | +10000 | 1.x → 1.y | ✅ |
| 架构重构 | +1000000 | x → y | ✅ |
九、Hvigor 构建工具
9.1 构建配置文件
小事记的hvigor/hvigor-config.json5配置了构建工具的基本参数:
// hvigor/hvigor-config.json5 { "modelVersion": "6.0.2", "dependencies": { "@ohos/hvigor": "5.0.0", "@ohos/hvigor-ohos-plugin": "5.0.0" } }9.2 构建流程
hvigor clean ← 清理构建产物 hvigor assembleDebug ← 构建 debug 版本 hvigor assembleRelease ← 构建 release 版本 hvigor install ← 安装到设备 hvigor run ← 运行应用十、实际项目中的包结构选择
10.1 小事记当前的包结构评估
当前小事记采用单模块 HAP 架构,适合以下场景:
- 应用功能相对集中,没有明显的模块化边界
- 团队规模小,单模块开发效率更高
- 不需要按需加载功能,所有功能都是核心功能
- 不需要跨模块共享运行时实例
10.2 未来包结构演进路径
| 阶段 | 包结构 | 触发条件 |
|---|---|---|
| 阶段一(当前) | 单 entry HAP | 原型验证、MVP 阶段 |
| 阶段二 | entry + HAR(工具库) | 出现可复用的纯逻辑代码 |
| 阶段三 | entry + HSP(共享组件) | 需要多个模块共享组件实例 |
| 阶段四 | entry + feature(按需加载)+ HSP | 功能模块体积庞大,需要按需交付 |
总结
本文从xiaoshiji_ohos_app项目的构建配置文件和依赖声明出发,深入解析了 HarmonyOS 的HAP/HSP/HAR 三层包结构。核心要点如下:
- HAP 是应用的基本交付单元,分为
entry(主入口)和feature(按需加载)两种类型,通过deliveryWithInstall控制交付策略 - HSP 是运行时共享包,多个 HAP 可共享同一个 HSP 实例,适用于公共组件库和工具库
- HAR 是编译时静态共享包,代码复制到宿主 HAP 中,适用于纯逻辑库和 SDK
- oh-package.json5管理工程级和模块级依赖,支持
dependencies、devDependencies和peerDependencies - products 构建配置支持多产品变体(debug/release/beta),通过
buildModeSet控制构建模式
下一篇文章将深入解析应用生命周期全景,从 Ability 到 WindowStage 再到 UI 组件的完整状态流转。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- 小事记项目源码:xiaoshiji_ohos_app
- 官方文档 - 包结构概览:application-package-overview.md
- 官方文档 - 包结构 Stage:application-package-structure-stage.md
- 官方文档 - 包基础:application-package-fundamentals.md
- 官方文档 - 包开发:application-package-dev.md
- 官方文档 - 安装卸载:application-package-install-uninstall.md
- 官方文档 - 配置文件:application-configuration-file-stage.md
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net