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 数组定义了包含的模块:

json5 复制代码
{
  "modules": [
    {
      "name": "entry",
      "srcPath": "./entry",
      "targets": [
        {
          "name": "default",
          "applyToProducts": [
            "default"
          ]
        }
      ]
    }
  ]
}

二、HAP(HarmonyOS Ability Package)

2.1 HAP 的两种类型

HAP 是应用的基本交付单元,分为 entry 和 feature 两种:

entry 类型 --- 应用主入口,必须存在且唯一:

json5 复制代码
// entry/src/main/module.json5
{
  "module": {
    "name": "entry",
    "type": "entry",  // 主入口模块
    "mainElement": "EntryAbility",
    // ...
  }
}

feature 类型 --- 按需加载的功能模块:

json5 复制代码
// 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 下载 低频功能、大资源模块
typescript 复制代码
// 按需下载并安装 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,运行时只有一份实例,节省内存:

json5 复制代码
// hsp_common/src/main/module.json5
{
  "module": {
    "name": "hsp_common",
    "type": "hsp",  // 动态共享包
    // ...
  }
}

HSP 的引用方式:

json5 复制代码
// 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:

  1. 多个 entry/feature 共享公共代码 --- 避免代码重复打包导致包体积膨胀
  2. 公共组件库需要运行时单例 --- 如主题管理、日志模块
  3. 需要独立更新组件库 --- 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 的静态库:

json5 复制代码
// har_utils/oh-package.json5
{
  "name": "@xiaoshiji/utils",
  "version": "1.0.0",
  "description": "公共工具函数库",
  "dependencies": {}
}

在宿主模块中引用:

json5 复制代码
// entry/oh-package.json5
{
  "name": "entry",
  "version": "1.0.0",
  "dependencies": {
    "@xiaoshiji/utils": "file:../har_utils"  // 静态引用
  }
}

4.2 HAR 的使用限制

  1. 不支持 module.json5 --- HAR 不包含配置文件,不能声明 Ability 或 ExtensionAbility
  2. 不支持 $profile 资源引用 --- 配置资源必须在宿主模块中定义
  3. 不支持页面路由 --- HAR 中不能包含 @Entry 装饰的页面组件
  4. 资源 ID 冲突 --- 多个 HAR 中的资源 ID 可能冲突,需要通过 $r('@package:name/xxx') 指定包名
typescript 复制代码
// 在 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):

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):

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 文件锁定了所有依赖的具体版本,确保构建可复现:

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 数组定义了应用的不同构建变体:

json5 复制代码
{
  "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
json5 复制代码
// 多产品配置示例
{
  "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 定义了两种构建模式:

json5 复制代码
{
  "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 按需交付策略

json5 复制代码
// 低频功能模块设置为按需交付
{
  "module": {
    "name": "feature_ai_generate",
    "type": "feature",
    "deliveryWithInstall": false,  // 不随安装包交付
    "installationFree": false
  }
}

7.3 公共代码抽取为 HSP

json5 复制代码
// 将公共代码抽取为 HSP 避免重复打包
{
  "module": {
    "name": "hsp_common",
    "type": "hsp"
  }
}

八、版本号与构建号管理

8.1 版本号的编码规范

小事记的 versionCode: 1000000 遵循标准的编码规范:

typescript 复制代码
// 版本号编码公式
// 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 配置了构建工具的基本参数:

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 架构,适合以下场景:

  1. 应用功能相对集中,没有明显的模块化边界
  2. 团队规模小,单模块开发效率更高
  3. 不需要按需加载功能,所有功能都是核心功能
  4. 不需要跨模块共享运行时实例

10.2 未来包结构演进路径

阶段 包结构 触发条件
阶段一(当前) 单 entry HAP 原型验证、MVP 阶段
阶段二 entry + HAR(工具库) 出现可复用的纯逻辑代码
阶段三 entry + HSP(共享组件) 需要多个模块共享组件实例
阶段四 entry + feature(按需加载)+ HSP 功能模块体积庞大,需要按需交付

总结

本文从 xiaoshiji_ohos_app 项目的构建配置文件和依赖声明出发,深入解析了 HarmonyOS 的 HAP/HSP/HAR 三层包结构。核心要点如下:

  1. HAP 是应用的基本交付单元 ,分为 entry(主入口)和 feature(按需加载)两种类型,通过 deliveryWithInstall 控制交付策略
  2. HSP 是运行时共享包,多个 HAP 可共享同一个 HSP 实例,适用于公共组件库和工具库
  3. HAR 是编译时静态共享包,代码复制到宿主 HAP 中,适用于纯逻辑库和 SDK
  4. oh-package.json5 管理工程级和模块级依赖,支持 dependencies、devDependencies 和 peerDependencies
  5. products 构建配置 支持多产品变体(debug/release/beta),通过 buildModeSet 控制构建模式

下一篇文章将深入解析 应用生命周期全景,从 Ability 到 WindowStage 再到 UI 组件的完整状态流转。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

相关推荐
用户117910488332 分钟前
AI粘贴多行需求为什么会误执行?hmharness安全粘贴拆解 GitHub:swsgbl/hmharness
ai编程·harmonyos
用户0934077735142 分钟前
HarmonyOS WPS Open SDK 实践:从 HAR 集成到 OpenFileRequest 最小闭环
typescript·harmonyos
Thneonl4 分钟前
一启动就 Exited(137):内存限制背后藏了四个参数
后端·架构
Thneonl28 分钟前
etcd 磁盘写满的那 6 分钟:控制面是怎么一步步瘫的
后端·架构
mldong2 小时前
事务不归引擎管:ITransactionTemplate,聚合一致性的最后一块拼图
后端·架构
CopyCode7 小时前
用 AI 迁项目有多爽?我把 Webpack 迁 Vite 的全过程记下来了
前端·架构
美好世界7 小时前
Codex 源码导读:第五部分——事件出口与多入口适配
架构
初学AI的小高7 小时前
LangGraph断点恢复与幂等执行实战
后端·架构
美好世界7 小时前
Codex 源码导读:第四部分——上下文压缩与继续执行
架构
美好世界7 小时前
Codex 源码导读:第十部分——Session、Thread 持久化与 Memory
架构