组件库封装与发布——从代码复用到生态共享的完整链路
文章目录

每日一句正能量
最高级的养生,不在于昂贵补品或剧烈运动,而在于少虑、少怨、少悔。
不为未发生的事过度焦虑。不对已发生的不公反复抱怨。不让过去的错误持续消耗当下。身体的损耗,大多源于内心的消耗。情绪干净了,身体自然通透。
摘要
在 HarmonyOS 应用开发的规模化进程中,组件库的封装与发布是实现代码复用、提升团队协作效率、构建技术生态的关键环节。本文系统梳理 HAR(Harmony Archive)与 HSP(Harmony Shared Package)两种共享包的技术差异与选型策略,深入讲解组件库的标准目录结构、封装规范与导出约定,详细演示从组件开发、oh-package.json5 配置、必备文件准备到 OHPM 中心仓发布的完整流程。结合语义化版本管理、多环境发布策略与 CI/CD 自动化流水线,提供一套可复制、可落地的企业级组件库治理方案,助力开发者从"写代码"迈向"建生态"。
一、组件库封装的技术背景与核心价值
1.1 为什么需要组件库
在前序文章(第一百七十八至一百八十篇)中,我们深入探讨了插槽机制、渲染控制与组件复用等 ArkUI 核心技术。这些技术解决的是"单个应用内部"的组件化问题,但当团队规模扩大、项目数量增多时,跨项目、跨团队的代码复用需求便浮出水面。每个项目重复编写相同的按钮组件、网络请求封装、主题配置,不仅造成严重的资源浪费,更导致不同项目的 UI 风格割裂、技术债务累积。
组件库的本质是将高频复用的代码、资源、配置沉淀为标准化的共享包,通过依赖管理工具(OHPM)分发到各个项目中。它实现了三个层面的价值跃迁:
- 代码层面:消除重复代码,统一技术实现标准
- 设计层面:保障跨项目 UI/UX 一致性,维护品牌视觉规范
- 生态层面:将内部能力对外开放,构建技术影响力与开发者生态
1.2 HarmonyOS 共享包体系概览
HarmonyOS 提供了两种共享包机制,分别对应不同的复用层级与发布范围:
| 维度 | HAR(Harmony Archive) | HSP(Harmony Shared Package) |
|---|---|---|
| 加载方式 | 编译时静态拷贝 | 运行时动态加载 |
| 发布范围 | 中心仓 / 私仓 / 本地文件 | 仅限应用内,随 App 一起发布 |
| 状态共享 | 各模块实例独立 | 全局共享同一实例 |
| 包体积影响 | 多模块引用导致多份拷贝 | 运行时仅一份,显著减小体积 |
| pages 声明 | 不支持(可用命名路由) | 支持 |
| 适用场景 | 三方库、二方库、工具类 | 应用内公共模块、状态共享 |
二、HAR 与 HSP 选型决策
2.1 选型决策树

选型口诀:对外发布用 HAR,内部共享用 HSP;要共享状态用 HSP,纯工具类用 HAR。
选择 HAR 的场景:
- 需要发布到 OpenHarmony 三方库中心仓,供全网开发者使用
- 需要发布到公司内部的 OHPM 私仓,供团队内其他应用依赖
- 封装的是纯工具类、UI 组件库,不涉及跨模块状态共享
- 需要被多个独立应用引用,每个应用拥有独立的组件实例
选择 HSP 的场景:
- 应用内多个 HAP 模块需要共享同一份代码和资源
- 需要跨模块共享状态(如全局主题、用户会话)
- 关注应用包体积,希望避免 HAR 多份拷贝导致的膨胀
- 功能模块按需加载(动态特性模块)
2.2 规格能力对比
| 规格能力 | HAP | HAR | HSP |
|---|---|---|---|
| 声明 UIAbility / ExtensionAbility | ✓ | ✗ | ✗ |
| 声明 pages 页面 | ✓ | ✗(可用命名路由) | ✓ |
| 包含资源文件与 .so 文件 | ✓ | ✓ | ✓ |
| 依赖其他 HAR | ✓ | ✓ | ✓ |
| 依赖其他 HSP | ✓ | ✓ | ✓ |
| 独立安装运行 | ✓ | ✗ | ✗ |
| 发布到 OHPM 中心仓 | — | ✓ | ✗ |
重要约束:HAR 不支持引用 AppScope 目录中的资源,编译时 AppScope 内容不会打包到 HAR 中;HAR 不支持循环依赖,也不支持依赖传递。
三、组件库封装规范与目录结构
3.1 标准目录结构设计
一个规范的企业级组件库应具备清晰的目录层次,便于维护、扩展和按需引入。

@myorg/harmony-ui-kit/ # 组件库根目录
├── src/main/ets/
│ ├── components/ # UI 组件目录
│ │ ├── Button/
│ │ │ ├── MyButton.ets # 按钮组件实现
│ │ │ └── MyButtonModel.ets # 按钮数据模型
│ │ ├── Card/
│ │ │ ├── MyCard.ets
│ │ │ └── MyCardTypes.ets
│ │ ├── Input/
│ │ │ └── MyInput.ets
│ │ └── List/
│ │ └── MyList.ets
│ ├── utils/ # 工具函数
│ │ ├── DateUtil.ets
│ │ ├── Network.ets
│ │ └── Validator.ets
│ ├── themes/ # 主题配置
│ │ ├── Colors.ets
│ │ ├── Typography.ets
│ │ └── Spacing.ets
│ └── Index.ets # 统一出口文件
├── src/main/resources/
│ └── base/
│ ├── media/ # 图标、图片资源
│ ├── string/ # 多语言文本
│ └── color/ # 颜色资源
├── oh-package.json5 # 包元数据配置
├── module.json5 # 模块配置
├── build-profile.json5 # 编译构建配置
├── README.md # 使用文档(必填)
├── CHANGELOG.md # 版本变更记录(必填)
└── LICENSE # 开源协议(必填)
3.2 统一导出规范(Index.ets)
组件库必须提供统一的出口文件,遵循"按需导入、命名清晰"的原则:
// src/main/ets/Index.ets
// UI 组件导出
export { MyButton } from './components/Button/MyButton'
export { MyButtonModel } from './components/Button/MyButtonModel'
export { MyCard } from './components/Card/MyCard'
export { MyCardProps } from './components/Card/MyCardTypes'
export { MyInput } from './components/Input/MyInput'
export { MyList } from './components/List/MyList'
// 工具函数导出
export { DateUtil } from './utils/DateUtil'
export { NetworkClient } from './utils/Network'
export { FormValidator } from './utils/Validator'
// 主题配置导出
export { ThemeColors } from './themes/Colors'
export { ThemeTypography } from './themes/Typography'
export { ThemeSpacing } from './themes/Spacing'
3.3 命名约定与代码规范
| 规范项 | 推荐做法 | 示例 |
|---|---|---|
| 包名 | @组织名/包名 格式 |
@myorg/ui-kit |
| 组件名 | PascalCase,带组织前缀避免冲突 | MyButton、MyCard |
| 模型名 | PascalCase + 后缀 | ArticleModel、UserProfile |
| 工具函数 | camelCase,语义化命名 | formatDate()、validatePhone() |
| 主题常量 | UPPER_SNAKE_CASE | PRIMARY_COLOR、FONT_SIZE_LARGE |
| 资源文件 | 小写 + 下划线分隔 | ic_button_primary.png |
四、oh-package.json5 配置详解
oh-package.json5 是组件库的"身份证",包含了包的元数据、入口文件、依赖关系等关键信息。以下是一个生产级组件库的完整配置示例:
{
"name": "@myorg/harmony-ui-kit",
"version": "1.2.0",
"description": "企业级 HarmonyOS UI 组件库,提供按钮、卡片、输入框、列表等高频组件及主题系统",
"main": "src/main/ets/Index.ets",
"author": "MyOrg Tech Team <tech@myorg.com>",
"license": "Apache-2.0",
"keywords": [
"harmonyos",
"arkui",
"ui-components",
"design-system"
],
"homepage": "https://github.com/myorg/harmony-ui-kit",
"repository": {
"type": "git",
"url": "https://github.com/myorg/harmony-ui-kit.git"
},
"bugs": {
"url": "https://github.com/myorg/harmony-ui-kit/issues"
},
"engines": {
"harmony": ">=5.0.0"
},
"dependencies": {
"@ohos/lottie": "^2.0.0",
"@ohos/pulltorefresh": "^1.1.0"
},
"devDependencies": {
"@types/node": "^20.0.0"
},
"types": "src/main/ets/Index.d.ts",
"files": [
"src/main/ets/**",
"src/main/resources/**",
"README.md",
"CHANGELOG.md",
"LICENSE"
]
}
必填字段说明:
| 字段 | 说明 | 注意事项 |
|---|---|---|
name |
包唯一标识 | 遵循 @组织名/包名 格式,全局唯一 |
version |
语义化版本号 | 格式 MAJOR.MINOR.PATCH,发布后不可修改 |
main |
入口文件路径 | 指向 Index.ets 统一出口 |
license |
开源协议 | 推荐 Apache-2.0 或 MIT,需与 LICENSE 文件一致 |
关键约束:所有直接依赖必须在模块级
oh-package.json5中声明完整,不能依赖工程级配置。否则外部项目引用时会出现依赖缺失错误。
五、组件库实战:封装企业级 UI 组件库
5.1 创建库模块
在 DevEco Studio 中,通过 File > New > Module > Static Library 创建 HAR 模块。若需创建 HSP,则选择 Shared Library。
5.2 封装核心组件
以下是一个遵循插槽机制与渲染控制最佳实践的按钮组件封装示例:
// src/main/ets/components/Button/MyButton.ets
@Component
export struct MyButton {
// 按钮类型
@Prop type: 'primary' | 'secondary' | 'danger' | 'ghost' = 'primary'
// 按钮尺寸
@Prop size: 'small' | 'medium' | 'large' = 'medium'
// 是否禁用
@Prop disabled: boolean = false
// 是否加载中
@Prop loading: boolean = false
// 按钮文本
@Prop text: string = ''
// 点击回调
onClick?: () => void
// 插槽:自定义内容(优先级高于 text)
@Builder
defaultContent() {
if (this.loading) {
Row({ space: 6 }) {
LoadingProgress()
.width(16)
.height(16)
.color(this.getTextColor())
Text('加载中...')
.fontSize(this.getFontSize())
.fontColor(this.getTextColor())
}
} else {
Text(this.text)
.fontSize(this.getFontSize())
.fontColor(this.getTextColor())
.fontWeight(FontWeight.Medium)
}
}
@BuilderParam contentBuilder: () => void = this.defaultContent
private getBgColor(): ResourceColor {
if (this.disabled) return '#E0E0E0'
switch (this.type) {
case 'primary': return '#1976D2'
case 'secondary': return '#E3F2FD'
case 'danger': return '#F44336'
case 'ghost': return 'transparent'
default: return '#1976D2'
}
}
private getTextColor(): ResourceColor {
if (this.disabled) return '#9E9E9E'
switch (this.type) {
case 'primary': return Color.White
case 'secondary': return '#1976D2'
case 'danger': return Color.White
case 'ghost': return '#1976D2'
default: return Color.White
}
}
private getFontSize(): number {
switch (this.size) {
case 'small': return 12
case 'medium': return 14
case 'large': return 16
default: return 14
}
}
private getHeight(): number {
switch (this.size) {
case 'small': return 28
case 'medium': return 36
case 'large': return 44
default: return 36
}
}
build() {
Button() {
this.contentBuilder()
}
.width('100%')
.height(this.getHeight())
.backgroundColor(this.getBgColor())
.enabled(!this.disabled && !this.loading)
.onClick(() => {
if (this.onClick && !this.loading) {
this.onClick()
}
})
}
}
5.3 主题系统设计
组件库应提供统一的主题系统,支持颜色、字体、间距的集中管理,并预留扩展接口:
// src/main/ets/themes/Colors.ets
export class ThemeColors {
// 品牌色
static readonly PRIMARY: ResourceColor = '#1976D2'
static readonly PRIMARY_LIGHT: ResourceColor = '#E3F2FD'
static readonly PRIMARY_DARK: ResourceColor = '#0D47A1'
// 功能色
static readonly SUCCESS: ResourceColor = '#4CAF50'
static readonly WARNING: ResourceColor = '#FF9800'
static readonly ERROR: ResourceColor = '#F44336'
static readonly INFO: ResourceColor = '#2196F3'
// 中性色
static readonly TEXT_PRIMARY: ResourceColor = '#212121'
static readonly TEXT_SECONDARY: ResourceColor = '#757575'
static readonly TEXT_DISABLED: ResourceColor = '#BDBDBD'
static readonly BORDER: ResourceColor = '#E0E0E0'
static readonly BACKGROUND: ResourceColor = '#F5F5F5'
static readonly SURFACE: ResourceColor = '#FFFFFF'
// 暗黑模式适配(预留)
static readonly DARK_BACKGROUND: ResourceColor = '#121212'
static readonly DARK_SURFACE: ResourceColor = '#1E1E1E'
static readonly DARK_TEXT_PRIMARY: ResourceColor = '#FFFFFF'
}
// src/main/ets/themes/Spacing.ets
export class ThemeSpacing {
static readonly XS: number = 4
static readonly SM: number = 8
static readonly MD: number = 16
static readonly LG: number = 24
static readonly XL: number = 32
static readonly XXL: number = 48
}
六、发布到 OHPM 中心仓的完整流程
6.1 发布流程全景

6.2 步骤详解
步骤一:账号与组织准备
前往 OpenHarmony 三方库中心仓(ohpm.openharmony.cn)注册账号并完成实名认证。若需以组织名义发布,在"组织管理"中新增组织,包名需遵循 @组织名/包名 格式。
步骤二:生成并配置密钥
OHPM 使用 RSA 公私钥校验发布权限,仅支持 PEM 格式。生成密钥时必须输入密码(密码不能为空):
# 生成 4096 位 RSA 密钥对
ssh-keygen -m PEM -t RSA -b 4096 -f ~/.ssh_ohpm/mykey
# 配置私钥路径
ohpm config set key_path ~/.ssh_ohpm/mykey
# 登录中心仓官网获取发布码,并配置
ohpm config set publish_id your_publish_id
步骤三:上传公钥
登录中心仓官网,进入「个人中心」-「认证管理」,新增 OHPM 公钥,将 mykey.pub 的内容粘贴保存。
步骤四:准备必备文件
库模块根目录下必须包含以下三个文件,且内容不能为空:
README.md:包含包的介绍、安装命令和基本使用示例CHANGELOG.md:填写每个版本的变更记录LICENSE:真实的许可证全文(推荐 Apache-2.0)
步骤五:Release 模式构建
# 务必使用 Release 模式构建,避免 Debug 包中包含源码导致泄露
# 在 DevEco Studio 中:Build > Make Module <模块名>
# 或在命令行中:
hvigorw --mode module -p module=library@default -p product=default assembleHar
安全警告:请务必使用 Release 模式构建,避免使用 Debug 模式,因为 Debug 包中会含有源码,存在代码泄露风险。
步骤六:执行发布
# 发布 HAR 包
ohpm publish ./library/build/default/outputs/default/library.har
# 发布时需输入生成密钥时设置的密码
步骤七:等待审核
发布成功后,中心仓会发送"创建上架审核单成功"通知。审核通过后,其他开发者即可通过 ohpm install @myorg/harmony-ui-kit 安装使用。
6.3 发布到私有仓库
对于企业内部组件库,可搭建 OHPM 私仓(基于 Verdaccio)进行发布:
# 1. 搭建 Verdaccio 私仓
npm i -g verdaccio
verdaccio
# 2. 配置私有 registry
ohpm config set registry http://localhost:4873
# 3. 登录私仓
ohpm login
# 4. 发布
ohpm publish ./library.har
七、版本管理与迭代策略
7.1 语义化版本规范
组件库的版本号必须遵循语义化版本(Semantic Versioning)规范:MAJOR.MINOR.PATCH。
| 版本位 | 递增条件 | 示例 |
|---|---|---|
| MAJOR | 存在不兼容的 API 变更 | 1.x.x → 2.0.0 |
| MINOR | 新增向下兼容的功能 | 1.1.x → 1.2.0 |
| PATCH | 修复向下兼容的问题 | 1.1.1 → 1.1.2 |
关键约束:版本号一旦发布并审核通过,该特定名称及版本号将被永久占用,无法再次使用。后续迭代必须递增版本号。
7.2 版本迭代流程

v1.0.0 → 初始发布,包含基础组件
v1.1.0 → 新增 MyTable 组件,新增暗黑模式支持
v1.1.1 → 修复 MyButton 在 disabled 状态下的颜色异常
v1.2.0 → 新增 MyForm 表单组件,优化主题系统
v2.0.0 → 重构主题 API(Breaking Change),移除废弃组件
7.3 多环境发布策略
| 环境 | 发布目标 | 使用方式 | 适用阶段 |
|---|---|---|---|
| 开发环境 | 本地文件 | ohpm install ./modules/shared |
本地联调 |
| 测试环境 | 私有 Registry | ohpm install @myorg/ui-kit@beta |
集成测试 |
| 生产环境 | OHPM 中心仓 | ohpm install @myorg/ui-kit |
正式发布 |
八、CI/CD 自动化发布流水线
8.1 GitLab CI 配置示例
# .gitlab-ci.yml
stages:
- build
- test
- publish
variables:
HAR_MODULE: "library"
OHPM_REGISTRY: "https://ohpm.openharmony.cn"
# 编译阶段
build_har:
stage: build
image: harmonyos/build-env:latest
script:
- hvigorw --mode module -p module=$HAR_MODULE@default -p product=default assembleHar
artifacts:
paths:
- library/build/default/outputs/default/*.har
expire_in: 1 hour
# 测试阶段
unit_test:
stage: test
image: harmonyos/build-env:latest
script:
- ohpm install
- hvigorw test
only:
- merge_requests
- main
# 发布阶段(仅 main 分支且 tag 触发)
publish_ohpm:
stage: publish
image: harmonyos/build-env:latest
script:
- ohpm config set key_path $OHPM_KEY_PATH
- ohpm config set publish_id $OHPM_PUBLISH_ID
- ohpm publish library/build/default/outputs/default/library.har
only:
- tags
when: manual # 需要手动确认发布
8.2 GitHub Actions 配置示例
# .github/workflows/publish.yml
name: Publish to OHPM
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup HarmonyOS SDK
uses: harmonyos/setup-sdk@v1
with:
api-version: '12'
- name: Install dependencies
run: ohpm install
- name: Build HAR (Release)
run: |
hvigorw --mode module -p module=library@default -p product=default assembleHar
- name: Publish to OHPM
env:
OHPM_KEY_PATH: ${{ secrets.OHPM_KEY_PATH }}
OHPM_PUBLISH_ID: ${{ secrets.OHPM_PUBLISH_ID }}
run: |
ohpm config set key_path $OHPM_KEY_PATH
ohpm config set publish_id $OHPM_PUBLISH_ID
ohpm publish library/build/default/outputs/default/library.har
九、最佳实践与避坑指南
9.1 十大最佳实践
- 统一命名空间:包名使用
@组织名/包名格式,组件名带前缀避免全局冲突 - 完整依赖声明:所有直接依赖必须在模块级
oh-package.json5中声明,不可依赖工程级配置 - Release 模式构建:发布前务必切换为 Release 模式,防止源码泄露
- 三文件必备:README.md、CHANGELOG.md、LICENSE 必须存在且内容非空
- 语义化版本:严格遵循 MAJOR.MINOR.PATCH 规范,版本号一旦发布不可复用
- 统一出口管理:通过
Index.ets集中导出,避免外部直接引用内部文件路径 - 主题系统预留:组件库应提供主题配置接口,支持颜色、字体、间距的自定义
- 插槽机制应用:复杂组件预留
@BuilderParam插槽,提升组件扩展性 - 性能优化内建:列表组件内置
@Reusable标记,遵循渲染控制最佳实践 - 文档即代码:README 中提供完整的安装命令、使用示例和 API 说明
9.2 常见错误与解决方案
| 错误现象 | 根本原因 | 解决方案 |
|---|---|---|
ohpm install 找不到依赖 |
依赖仅在工程级声明 | 在模块级 oh-package.json5 中补全依赖 |
| 发布审核被拒 | README/CHANGELOG/LICENSE 为空 | 补充完整内容后重新提交 |
| HAR 中资源引用失败 | 引用了 AppScope 资源 | HAR 不支持 AppScope,资源应放在模块内 |
| 多模块引用后包体积膨胀 | 使用 HAR 而非 HSP | 应用内共享场景改用 HSP |
| 版本号冲突无法发布 | 该版本已存在 | 递增版本号后重新发布 |
| 私钥密码错误 | 生成密钥时未输入密码 | 重新生成带密码的密钥对 |
十、总结
本文从 HarmonyOS 共享包体系出发,系统解析了 HAR 与 HSP 的技术差异与选型策略,深入讲解了组件库的标准目录结构、封装规范、oh-package.json5 配置及统一导出约定。通过完整的发布流程演示——从密钥生成、必备文件准备到 Release 模式构建与 OHPM 中心仓上架——帮助开发者掌握组件库从开发到生态共享的全链路技术。结合语义化版本管理、多环境发布策略与 CI/CD 自动化流水线,提供了一套可复制、可落地的企业级组件库治理方案。
组件库不仅是代码复用的载体,更是技术团队能力沉淀与生态影响力建设的核心抓手。掌握组件库封装与发布的完整技能链,是每一位 HarmonyOS 开发者从"写代码"迈向"建生态"的必经之路。
转载自:https://blog.csdn.net/u014727709/article/details/163540974
欢迎 👍点赞✍评论⭐收藏,欢迎指正
更多推荐


所有评论(0)