☰
HarmonyOS HAR 共享库发布:Module 配置全解析与避坑指南
2026/10/7 15:51:55 网站建设 项目流程

如果你已经写过几个 HarmonyOS 应用,大概率迟早会遇到这个需求:想把某个通用能力沉淀成一个 HAR,发到 OpenHarmony 三方库中心仓,让更多项目直接ohpm install就能用。这个事听起来只是“打包上传”,真正动手才会发现,坑几乎全埋在 Module 配置里。

我第一次发布共享库时,就栽在oh-package.json5上。包的name少了个作用域前缀,校验直接打回;后来version写重复,又被中心仓拒收;最头疼的一次是main字段指向了./Index.ets,但产物里根本没这个文件。前前后后折腾了大半天,最后把所有配置项整理成一份可抄的清单,再发布就再也没有返工过。

这篇送给所有准备发三方库的同行,也算是《精通 HarmonyOS NEXT:鸿蒙 App 开发入门与项目化实战》的读者福利。我们会把“能跑的应用”这一层先放一边,专门聊聊把 Module 变成可发布共享库时,到底要配哪些项、为什么配这些项、以及最容易在哪个环节被中心仓的自动校验卡住。

1. 先搞清楚:你要发布的到底是哪种“共享库”

HarmonyOS 工程里的“共享库”是个容易混的概念,因为官方给出来的形态至少有三种:HAR、HSP、源码共享库。同样是新建一个 Module,选错类型,后面所有配置全是白费。

**HAR(Harmony Archive)**是静态共享包。你把代码、资源、配置打成.har文件,调用方在编译阶段把它合入自己的 HAP。对使用方来说,这个库最终会变成应用的一部分,不涉及运行时加载,也不需要关心动态更新。对发布方来说,中心仓对 HAR 的审核和解析支持也是最成熟的。

**HSP(Harmony Shared Package)**是动态共享包,也叫共享应用包。它和 HAR 的最大区别是运行时按需加载,适合多个模块共享同一份代码、按需分发更新的场景。听起来灵活,但代价是使用方的工程结构必须支持 HSP 的依赖方式。发一个三方库出去,要求每个使用方都得配合做动态拆包设计,这对大部分场景来说太沉重了。除非你明确知道自己的库要服务大型应用的动态拆包,否则别把 HSP 作为发到中心仓的默认形态。

源码共享库则是把源码直接发布到 ohpm 源上。中心仓里也能见到这类库,使用方安装后由自己的工程参与编译。好处是源码可读、调试方便;坏处是没有产物体积优势,而且如果源码里用了不规范的相对路径引用,使用方一编译就炸,排查成本比 HAR 高得多。

所以,从中心仓接受度和调用方友好度来看,发布 HAR 是最稳的选择。这也是下文所有配置的主线。

还有一句要提醒:工程的 SDK 版本标记。HarmonyOS NEXT 的 SDK 版本号写作5.0.0(12),括号里的 12 就是 API Level。如果你的库用到了 API 12 才加入的能力,建议在build-profile.json5里提前把版本定了:

"products": [ { "name": "default", "compileSdkVersion": "5.0.0(12)", "compatibleSdkVersion": "5.0.0(12)" } ]

先把 SDK 版本对齐,后面构建时就不会突然冒出 “SDK version not compatible” 的问题。从中心仓生态看,API 12+ 也是当前三方库的主力区间。

2. Module 配置这盘棋:先把每个文件的职责认清楚

发布共享库,说穿了就是“把一个 Module 从应用工程里拆出来,单独构建、单独校验”。痛点通常不在代码本身,而是临时翻一堆配置文件、不知道应该动哪个。

先给一张职责地图,后面逐个讲:

文件管什么和发布的关系
oh-package.json5包名、版本、入口、依赖中心仓校验第一优先级
module.json5Module 类型、设备形态type 写错,产物直接不对
build-profile.json5SDK 版本、构建目标决定兼容性
Index.ets对外导出main字段指向它
README.md/LICENSE/CHANGELOG.md面向使用方人工审核时会看

2.1 新建一个可发布的 HAR Module

在 DevEco Studio 里,右键工程 -> New -> Module,选择Static Library。生成出来的模块名默认带lib前缀,比如libdemo。新建之后第一件事,打开模块内的module.json5,确认"type": "har"。

这一步看着简单,但坑就在这里:如果你新建时选了 Shared Library,module.json5里的 type 会是shared,后续构建出来的是.hsp而不是.har,拿到中心仓去校验,完全不是同一个物种。

另外,模块名最好只用小写字母和数字,别用驼峰、别用中文。模块名会出现在构建路径、产物文件名以及oh-package.json5的默认 name 里,名字越规整,后面越省事。

2.2 module.json5:别把 entry 的字段复制过来

很多人在配共享库时,第一反应是把 entry 模块的module.json5整段复制过来。这是后续报错的高频来源。作为应用模块,entry 里有abilities、pages、mainElement这些应用描述字段,它们对 HAR 模块毫无意义。强行保留,轻则构建告警,重则把产物打成一个不伦不类的“应用包”。

一个能用于发布的最小共享库module.json5长这样:

{ "module": { "name": "demo", "type": "har", "deviceTypes": [ "phone", "tablet", "2in1" ] } }

deviceTypes按需填写。如果库是纯逻辑库,不涉及设备差异,写常见的三类即可。如果库里面用了特定设备才有的 API,建议别在 module 层卡设备,而是在文档里写明适配范围,把选择权留给使用方。

2.3 build-profile.json5 与 SDK 版本

模块自己的build-profile.json5只负责构建目标,不需要写签名信息:

{ "apiType": "stageMode", "buildOption": {}, "targets": [ { "name": "default" } ] }

如果你的库需要自定义 ArkTS 编译选项,可以加在buildOption.arkOptions下。但发布三方库我建议保持默认,因为使用方用的是他们自己的编译环境,你在这边压掉一个告警,到对方那边可能变成编译错误。库的代码越“人畜无害”越好。

SDK 版本统一在工程根目录的build-profile.json5里配置。发布到 OpenHarmony 三方库中心仓时,runtimeOS 选HarmonyOS还是OpenHarmony,取决于目标设备。如果库主要在华为 1+8+N 设备上用,写"runtimeOS": "HarmonyOS"没问题;如果重点是开源鸿蒙的产线设备,可能需要改成"runtimeOS": "OpenHarmony"。这个没法一刀切,但先搞清楚自己的目标用户,能少走弯路。

3. oh-package.json5 才是中心仓校验的“身份证”

如果说module.json5管的是“这个模块在工程里怎么构建”,那么oh-package.json5管的就是“这个包在中心仓里叫什么、怎么被安装”。发布校验第一轮扫的就是它。

一个能过审的配置示例:

{ "modelVersion": "5.0.0", "name": "@demo/richtext", "version": "1.0.0", "description": "A lightweight rich text component for HarmonyOS", "main": "./Index.ets", "author": "demo", "license": "Apache-2.0", "keywords": [ "harmonyos", "ohos", "richtext" ], "repository": "https://gitee.com/demo/richtext", "dependencies": {}, "devDependencies": { "@ohos/hypium": "1.0.18" } }

3.1 name 字段:唯一性和作用域前缀

name是中心仓对所有包做索引的主键,一个名字只能说只能用一次。如果你在中心仓里搜到同名库,哪怕不是你的,你也没法发第二份。所以强烈建议用@scope/name格式。scope 是你自己的账号或组织名,例如@demo/richtext。

命名规则上有几条硬性红线:

  • 只允许小写字母、数字、-、_、.;
  • 不能以.、_开头;
  • 不能包含中文或空格;
  • 长度建议控制在 50 个字符内,虽然中心仓给了 214 字符上限,但名字越长越难记。

不少人第一次发布失败,就是在本地开心地用MyLib或my_lib这种名字,到中心仓校验时被打回。

3.2 version 字段:语义化版本和重复发布

version必须严格遵循 semver 规范,也就是X.Y.Z。中心仓支持预发布版本,例如1.0.0-beta.1、2.1.0-rc.0,但格式上有讲究:预发布标识只能由字母数字和连字符组成,不能乱写。

最关键的是,同一个name下的同一个version不能重复发布。1.0.0发过了,即使你只是想覆盖修复,也不能再发一次1.0.0,必须改成1.0.1。中心仓这么设计,是为了保证使用方锁定的版本是稳定内容。谁也不想一个ohpm install之后,代码“悄悄”变了。

3.3 main 字段:入口文件决定别人怎么 import

main字段指定库的入口。对 ArkTS 库来说,最常见的写法是:

"main": "./Index.ets"

也可以省略前面的./,写成"Index.ets",但为了风格统一,我带./。

这里有个容易踩的坑:入口文件名的大小写。DevEco Studio 默认生成的是Index.ets,首字母大写。如果你把 main 写成./index.ets,本地构建可能不报错,但中心仓校验用“文件精确匹配”的办法找入口,大小写不一致就报main entry not found。

入口文件的主体不应该是业务逻辑,而是导出聚合:

export { default as RichText } from './src/main/ets/components/RichText'; export { RichTextModel } from './src/main/ets/models/RichTextModel'; export type { RichTextOptions } from './src/main/ets/models/RichTextOptions';

这样调用方就能统一导入:

import { RichText, RichTextModel } from '@demo/richtext';

3.4 author、license、description、keywords

author建议写成名字 <邮箱>的格式,例如"author": "demo <demo@example.com>"。中心仓页面会展示作者信息,审核人员也能找到人。不推荐留空。

license必须写 SPDX 标准许可证标识,常见的有MIT、Apache-2.0、BSD-3-Clause。不要写“请查看仓库”或者自创许可证名。自动审核扫到非 SPDX 标识会直接拦截。

description控制在两三句话内,说明“这个库解决什么问题”。它是搜索结果里的主体展示,写得含糊的库,用户连点进去的欲望都没有。

keywords是数组,建议至少包含harmonyos和ohos,再加两三个功能关键词。它影响中心仓搜索命中率,属于低成本高收益的字段。

3.5 dependencies 与 devDependencies 的边界

这两个字段决定别人安装你的库时,还需要额外下载什么。

"dependencies": { "@other/foo": "^2.0.0" }, "devDependencies": { "@ohos/hypium": "1.0.18" }

dependencies里的包会随你的库一起被安装解析。如果运行时不需要的包被放进这里,只是增加安装体积,还容易触发依赖冲突。凡是只在单测里用的,统统放devDependencies。

另外要严防一种写法:本地路径依赖。

"dependencies": { "@local/common": "file:../common" }

这种写法在本地联调非常香,但发布出去就是深坑。别人的机器上根本不存在../common,安装阶段直接报依赖缺失。要发布,就必须改成中心仓可解析的真实版本号,或者把通用部分拆成一个独立发布的包再引用。

3.6 容易被忽略的其他字段

  • repository:不是必填,但强烈建议写。审核和用户都需要知道源码在哪。
  • type:一般情况下不用写,DevEco 会自动处理。
  • typings:ArkTS 库通常不需要手动配,编译过程会自动生成声明文件。
  • changelog字段:部分工具链会支持,但我更推荐直接维护一个CHANGELOG.md,在中心仓页面展示更清晰。

4. 构建产物与本地验证:上传前最后一关

配置写得再漂亮,最终交付的是一个.har文件。很多人觉得“配置没问题就一定能过”,结果构建出来的产物根本没有入口,或者包里混入了奇怪的东西。所以上传前,建议按下面这套流程走一遍,总耗时不超过十分钟。

4.1 Make Module,找到正确的 .har

打开 DevEco Studio,确定当前选中的模块是共享库模块,然后菜单栏执行Build -> Make Module。构建成功以后,产物路径通常是:

libdemo/build/default/outputs/default/libdemo.har

注意,Make Module 的对象是模块名。如果工程里不小心选中了 entry,构建出来的就不是 har,而是 hap。所以构建完先看路径,路径最后一级是outputs/default,文件后缀是.har,基本就对了。

4.2 解压产物,检查三件事

.har是标准 zip 包,用压缩软件打开后,建议先找三个东西:

  1. Index.ets或编译后的Index.js/Index.d.ts:确认入口在不在,文件名和 main 字段是否一致;
  2. module.json:确认里面的 type 是不是har;
  3. oh-package.json:确认 name 和 version 是不是这次要发布的版本。

如果解压后看到resources目录,说明资源被打进去了,这是正常的。如果看到abilities、pages这类文件,就怀疑是不是把 entry 的东西打进来了,赶紧检查模块边界。

4.3 本地 ohpm 安装测试

产物本地自测,是发布前最有价值的一步。最省事的做法,在测试工程里执行:

ohpm install /path/to/libdemo.har

安装成功后,写一行 import 代码,编译运行。能跑通,说明这个 HAR 被外部工程消费时是闭合的;跑不通,至少不用把问题丢到中心仓审核那边才暴露。

更保险的做法是新建一个空工程,专门用来“消费”待发布的库。这样能排除测试工程里已有资源对其它包的干扰。我见过很多情况:库在自己的 demo 工程里跑得好好的,换到空工程一编译就报错,原因往往是依赖了 demo 工程里某个没有发布的本地模块。

4.4 一套可以直接抄的 Module 配置清单

把前面讲过的关键配置综合成一张检查表,发布前逐项核对:

检查项推荐结果说明
Module 类型harmodule.json5的 type 字段
SDK 版本5.0.0(12) 或兼容版本compileSdkVersion/compatibleSdkVersion
包名@scope/name小写、全局唯一
版本号1.0.0 起,semver不能重复发布
入口./Index.ets文件存在、大小写一致
许可证Apache-2.0 / MITSPDX 标准
运行时依赖可解析的 ohpm 版本禁止 file: 路径
文档README、CHANGELOG、LICENSE至少 README 要规范

5. 发布时常见的 Module 配置报错与排查实录

这一节基本是从我踩过的坑里总结出来的,大概率也是你马上要遇到的。

5.1 高频错误速查表

报错或现象原因解决方案
Invalid package namename 含大写、中文或特殊字符改成小写字母、数字、-、_、.
Version already exists相同版本号重复发布升版本,如 1.0.0 -> 1.0.1
main entry not foundmain 写错路径或文件名大小写不一致改成 ./Index.ets 并核对文件
license is requiredlicense 缺失填 SPDX 标准标识
Dependency not founddependencies 里用了 file: 路径或私有源改成中心仓可解析版本
Package name conflictscope/name 已被占用换 scope 或换库名
Version too low新版本号低于已发布版本使用更高版本号
产物是 hap 而不是 har构建时选中了 entry 模块先选中共享库模块再 Make

其中,Version too low是我遇到最多的报错。一个人维护多个项目时,配置模板不小心复制了旧版本号,自己还没发现。中心仓会做一次版本递增校验,低于或等于线上版本直接被拒。

5.2 发布命令为什么总是静默失败

你可能会遇到这种情况:本地构建一切正常,配置看起来也对,但执行发布命令时,命令行输出只有一句 “publish failed”。这种静默失败,十有八九是 ohpm 源和凭据没配置对。

发布前,我建议先执行:

ohpm config get registry

确认当前源指向的是你打算发布的三方库中心仓。如果之前一直在做应用内依赖开发,源地址很可能还停留在某个测试源或私有源。账号 token 也要重新登录刷新。这个检查做一次,能省掉反复试错的痛苦。

6. 发布之后:版本迭代与维护中的真实体会

HAR 上传成功只是开始。我自己维护过几个库,最深的体会是:Module 配置能保证你“进得了门”,但后续的版本管理决定这个库“活不活”。

每次发版前,务必同步三个文件:oh-package.json5、CHANGELOG.md、README.md。版本号改了,CHANGELOG 要把新增内容和破坏性变更写清楚,README 里的安装命令、API 示例也要跟着更新。中心仓的人工审核看一遍就懂,你的库是认真维护还是随手扔上去的。

升级版本要克制。库刚发布时,很多使用者会按^或~的范围依赖自动获取小版本。你发一个含有破坏性变更的1.1.0,可能让一堆人的项目在静默更新后编译失败。破坏性变更要么放在主版本号,要么在 CHANGELOG 里加粗提醒。

还有一条:别在三方库里依赖其它未发布的私有产物。这个在前面讲file:依赖时说过,但值得再说一次。你在自己工程里联调得再爽,只要依赖在中心仓解析不到,使用者就装不上。宁可把通用部分拆成一个真正发布出去的包,再通过版本号引用回来。

最后分享一个我保留到现在的习惯:每次发布前,在新工程里ohpm install最新版本并编译跑通。这套动作从第一次踩坑后就再没断过,成本五分钟,却能挡住大部分低级错误。库的发布考验的不是炫技,而是把一个模块当成公共交付物去校验的耐心。能把这套 Module 配置吃透,后面再发多少库,都只是复制粘贴的体力活。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询