HarmonyOS应用开发实战:小事记 - 应用包结构:HAP/HSP/HAR 的三层架构与 deliveryWithInstall 策略

前言
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
更多推荐

所有评论(0)