如何手把手打造鸿蒙应用第三方库HAR构建、混淆与发布?

摘要:【学习目标】 基于PreferenceLibDemo工程,掌握HAR库debug、release两种构建模式,完成字节码HAR与源码HAR的配置与构建。 掌握ArkGuard源码混淆与字节码混淆的开启方法,规则配置,确保Preference
【学习目标】 基于PreferenceLibDemo工程,掌握HAR库debug、release两种构建模式,完成字节码HAR与源码HAR的配置与构建。 掌握ArkGuard源码混淆与字节码混淆的开启方法,规则配置,确保Preference工具库对外接口可用。 完成HAR包签名配置,遵循标准流程将HAR发布到OpenHarmony三方库中心仓,实现跨项目复用。 掌握混淆与发布过程中的常见问题排查方法,保障工具库稳定交付。 一、基础概念:HAR的核心形态与定位 1.1 HAR定义 HAR(HarmonyOS Archive)是鸿蒙生态的静态库模块,本质是可复用的代码/资源打包文件,包含ArkTS/JS代码、资源文件、配置文件等,可被HAP(应用包)、HSP(鸿蒙共享包)或其他HAR依赖引用,实现代码复用。 类比:HAR相当于前端的npm包、Android的aar包,是鸿蒙生态中标准化的「代码复用单元」。 1.2 HAR的三种产物形态(核心区分) 产物类型 构建模式 核心构成 适用场景 安全性 构建/集成效率 字节码HAR release(默认) 编译后的.abc字节码+资源 正式发布、对外提供SDK 高 构建慢/集成快 源码HAR debug(默认) 完整ArkTS/TS源码+资源 本地开发、调试、联调 低 构建快/集成慢 源码HAR(混淆) release 混淆后的JS中间码+资源 兼容旧版本环境 中 构建中/集成中 关键版本说明:从DevEco Studio NEXT Beta1(5.0.3.800)开始,release模式默认构建字节码HAR;若需构建源码HAR,需显式关闭byteCodeHar。 1.3 标准模块结构 本节内容基于上一节工程PreferenceLibDemopreferences模块实际目录结构如下,是HAR构建的基础: preferences/ ├─ build/ # 构建产物目录(自动生成) ├─ src/ │ ├─ main/ │ │ ├─ ets/ │ │ │ ├─ components/ # HAR库组件目录(按需保留/排除) │ │ │ ├─ utils/ # 核心工具类目录 │ │ │ │ ├─ PreferencesConfig.ets # 配置类 │ │ │ │ └─ PreferencesUtil.ets # 核心工具类 │ │ │ ├─ resources/ # HAR库资源目录 │ │ │ └─ module.json5 # 模块基础配置 │ ├─ ohosTest/ # 鸿蒙测试目录 │ └─ test/ # 单元测试目录 ├─ .gitignore # git忽略配置 ├─ build-profile.json5 # 构建、混淆核心配置文件 ├─ BuildProfile.ets # 构建配置辅助文件 ├─ consumer-rules.txt # 依赖方混淆规则文件 ├─ hvigor-config.json5 # 构建引擎的配置文件,定义开发态版本号、依赖插件的版本以及Hvigor相关能力的配置等 ├─ hvigorfile.ts # 构建脚本 ├─ Index.ets # HAR导出入口文件 ├─ obfuscation-rules.txt # 本模块混淆规则文件 └─ oh-package.json5 # 包信息、版本与依赖配置 1.4 preference模块构建静态包信息(oh-package.json5) { "name": "@happy/preferences", // 构建har包名 @作者/组织 + 模块名称 "version": "1.0.0", // 版本号 "description": "Preferences多实例池工具库,支持多文件隔离、静态+实例双调用、XML/GSV自动降级", // 描述信息 "main": "Index.ets", // 导出文件入口 "deviceTypes": [ // 支持的设备类型 "default", "phone", "tablet" ], "compatibleSdkVersion": "5.1.0(18)", // 最低兼容版本号 "author": "happy", // 作者 "license": "Apache-2.0", // 协议 "dependencies": {} // 依赖 } 重要提示 如果你要发布到第三方仓库,作者/组织名字必须通过组织管理审核通过才能用,否则发布har包会失败。 二、字节码HAR构建(release模式,主流发布形态) 默认产物是包含字节码的HAR包,其中包含abc字节码、资源文件、配置文件、readme、changelog声明文件、license证书文件,提升发布到ohpm中心仓产物的安全性。 2.1 核心特点 产物:编译后的.abc字节码 + 资源文件 + 配置文件(无原始源码) 核心优势:安全性最高(反编译难度大)、集成效率高(无需二次编译)、内存占用低 适用场景:开源库发布、对外SDK、正式商用 2.2 核心约束 工程需为Stage模型(API 10及以上),HAR模块类型为Static Library 工程级useNormalizedOHMUrl需设为true 字节码HAR的依赖需配置在自身oh-package.json5的dependencies/dynamicDependencies中 依赖名、import名、包名需完全一致(含大小写),否则集成时运行异常 HAR的compatibleSdkVersion不能大于集成工程的版本 修改oh-package.json5中的版本号后,必须先Clean Project再重新构建,否则版本不生效 三、ArkGuard 混淆配置表 3.1 混淆开关选项 混淆自定义选项名称 功能简述 混淆选项 关闭全局混淆 关闭所有混淆功能,不进行任何混淆 -disable-obfuscation 属性名称混淆 开启对象属性/变量名混淆 -enable-property-obfuscation 顶层作用域混淆 开启文件顶层变量/函数名混淆 -enable-toplevel-obfuscation 文件名混淆 开启构建产物文件名混淆 -enable-filename-obfuscation 导出名称混淆 开启export导出名称与属性混淆 -enable-export-obfuscation 代码压缩 精简代码格式,减小包体积 -compact 删除日志 自动删除代码中console.*打印方法 -remove-log 输出名称缓存 指定路径输出混淆映射表namecache.json -print-namecache filepath 复用名称缓存 复用已有的混淆名称缓存文件 -apply-namecache filepath 删除注释 编译时删除代码中的所有注释 -remove-comments 3.2 白名单保留选项(保证API正常调用) 保留自定义选项名称 功能简述 保留选项 保留属性名 不混淆指定的属性名称 -keep-property-name 保留全局名称 不混淆顶层作用域与导出元素名称 -keep-global-name 保留文件名 不混淆指定文件/文件夹名称 -keep-file-name 保留类型声明 读取.d.ts文件内容作为混淆白名单 -keep-dts 保留注释 保留声明文件中JsDoc文档注释 -keep-comments 保留全量名称 保留指定路径下所有名称不被混淆 -keep 3.3 通配符说明 名称类和路径类的保留选项支持通配符,可批量配置白名单 四、核心配置步骤 4.1 工程级配置(根目录build-profile.json5) 必须开启 useNormalizedOHMUrl:true // build-profile.json5 { "app": { "products": [ { "buildOption": { "strictMode": { "useNormalizedOHMUrl": true // 字节码HAR必需开启 } } } ] }, "modules": [{"name": "preferences", "srcPath": "./preferences"}] } 4.2 模块级配置(preference/build-profile.json5) byteCodeHar:true 开启字节码HAR,关闭字节码设置为false; ruleOptions.enable = true 开启混淆; { "apiType": "stageMode", "buildOption": { "arkOptions": { "byteCodeHar": true // 开启字节码HAR;关闭字节码设置为false }, "resOptions": { "copyCodeResource": { "enable": false } }, // 可选:自定义打包内容,匹配实际目录 "packingOptions": { "asset": { "include": [ ], "exclude": [ "./src/main/ets/components/**/*" // 排除到har包外 ] } } }, "buildOptionSet": [ { "name": "release",// 仅release模式生效 "arkOptions": { "obfuscation": { "ruleOptions": { "enable": true, // 开启混淆 "files": [ "./obfuscation-rules.txt" // 混淆规则文件 ] }, // consumerFiles中指定的混淆配置文件会在构建依赖这个library的工程或library时被应用 "consumerFiles": [ "./consumer-rules.txt" ] } } } ], "targets": [ { "name": "default" }, { "name": "ohosTest" } ] } 4.2.1 packingOptions 核心配置说明 include 定义需要打入HAR包的资源路径 支持通配符 **/* 表示递归匹配所有子目录文件 若留空则表示默认包含除exclude外的所有资源 exclude 优先级高于include 示例中排除了 components 目录下所有内容 被排除的资源不会出现在最终HAR包中 4.3 字节码混淆规则 obfuscation-rules.txt # ======================== # 混淆总开关 # ======================== -enable-bytecode-obfuscation # 开启字节码混淆(必须) -enable-property-obfuscation # 开启属性名混淆 # -enable-filename-obfuscation # 关闭:文件名混淆 -enable-toplevel-obfuscation # 开启顶层作用域混淆 # -enable-export-obfuscation # 关闭:export导出名称混淆 否则我们的har包其他应用无法使用 # ======================== # 代码优化 我们不需要 打包发布应用时可开启 # ======================== # -compact # 关闭:代码压缩 会变成一行 不利于其他开发人员查看接口 # -remove-log # 关闭:删除日志 # -remove-comments # 关闭:删除注释 我们做开源库注释给其他开发人员看的 -print-namecache ./namecache.json # 输出混淆映射表 # ======================== # 白名单:保留对外暴露的全局名称 # ======================== -keep-global-name PreferencesUtil -keep-global-name PreferencesOptions -keep-global-name StorageMode -keep-global-name ChangeCallback # ======================== # 白名单:保留对外暴露的方法名 # ======================== -keep-property-name getInstance -keep-property-name use -keep-property-name getCurrentInstance -keep-property-name getCurrentFileName -keep-property-name put -keep-property-name get -keep-property-name has -keep-property-name delete -keep-property-name onDataChange -keep-property-name offDataChange -keep-property-name removeAllListeners -keep-property-name deleteFile -keep-property-name destroy -keep-property-name destroyFile 4.4 consumer-rules.txt # 给依赖当前HAR的项目自动应用白名单规则 -keep-global-name PreferencesUtil -keep-global-name PreferencesOptions -keep-global-name StorageMode -keep-global-name ChangeCallback -keep-property-name getInstance -keep-property-name use -keep-property-name getCurrentInstance -keep-property-name getCurrentFileName -keep-property-name put -keep-property-name get -keep-property-name has -keep-property-name delete -keep-property-name onDataChange -keep-property-name offDataChange -keep-property-name removeAllListeners -keep-property-name deleteFile -keep-property-name destroy -keep-property-name destroyFile 4.5 执行构建 选中 preferences 模块; 点击顶部菜单栏 Build → Clean Project(清理旧构建产物); 点击右上角 Build Mode → 选择 release; 点击顶部菜单栏 Build → Make Module 'preferences'; 构建完成后,查看产物路径:preferences/build/default/outputs/default/preferences.har 我们要构建HAR工具包发布到第三方开源仓库供他人使用。因此导出元素混淆必须关闭,其他混淆开启即可,否则 HAP/HSP 依赖时会报导出错误。 本节内容中 # 为注释,去掉注释则开启对应功能。 BuildMode模式选择 解压HAR包 文件名没有混淆(开源便于其他开发人员查看)并且导出了全部的公共接口,其内部实现隐藏。 modules.abc:是工程中所有 .ets/.ts/.js文件编译后的字节码集合,包含应用逻辑和 UI 声明式代码,由鸿蒙运行时环境直接解析执行。 验证HAR包可用性 将har包导出到其他工程引用,所有接口、字段名称都可正常访问。 五、混淆效果与堆栈还原 5.1 混淆效果 字节码混淆完成后,会在工程 build 目录下build/default/.../release/obfuscation生成一系列混淆中间产物与映射文件。通过这些文件查看混淆结果、还原崩溃堆栈。 nameCache.json:混淆名称映射表,记录混淆前后类名、方法名、属性名的对应关系。 systemApiCache.json:系统API白名单文件,记录SDK标准接口名称,与这些名称重名的自定义元素不会被混淆。 obf 目录:存放混淆后的最终字节码文件modules.abc,开启调试配置后还会生成 modules.pa 文件。 origin 目录:存放混淆前的原始 modules.abc 文件,用于对比校验。 config.json:混淆配置记录文件,保存本次混淆使用的规则、白名单等信息。 5.2 报错堆栈还原 代码经过字节码混淆后,类名、方法名会被替换成无意义字符,程序崩溃时输出的堆栈信息无法直接对应源码,难以排查问题。 此时可使用 DevEco Studio 自带的 hstack 反混淆工具,通过混淆映射文件还原出原始源码堆栈。 反混淆还原需要两个关键文件: 对外发布开源库/SDK后,若需线上排查崩溃问题,必须本地备份好 编译生成的 sourceMaps.json 、混淆映射表 nameCache.json,建议直接备份整个 release 目录。 字节码HAR构建耗时相对更长(需将源码编译成二进制字节码),但集成到宿主工程时无需二次编译,可节省 50% 以上的编译时间。 5.3 代码体积优化 若构建时出现代码体积过大相关报错,可在 build-profile.json5 中添加以下配置: 默认值:若不配置,默认为 2000。 合法范围:配置值必须满足 1 ≤ maxFlowDepth ≤ 65535。 超限报错:若值超过 65535 "arkOptions": { "tscConfig": { "maxFlowDepth": 3000 } } 六、源码HAR 6.1 核心前提 无论debug还是release模式构建源码HAR,必须先关闭字节码HAR开关: { "buildOption": { "arkOptions": { "byteCodeHar": false // 核心:关闭字节码,生成源码HAR } } } 6.2 debug模式构建 6.2.1 核心特点 产物:完整、未混淆的ArkTS/TS源码 + 资源文件 + 配置文件 支持断点调试、热重载,开发效率高 仅用于本地开发、内部调试,不对外发布 6.2.2 配置与构建 模块级build-profile.json5中配置byteCodeHar: false 点击右上角Build Mode选择debug 点击Build → Clean Project清理工程 选中preference模块 → 点击Make Module preferences 构建完成后,得到包含完整.ets源码的HAR包 6.3 release模式构建 建议开启混淆,保护代码资产。 6.3.1 核心特点 产物:混淆后的JS中间码 + 资源文件(无原始源码) 安全性中等,兼容性强 使用场景:仅用于兼容不支持字节码的老旧开发环境 新版OpenHarmony 开源库发布不使用该格式 6.3.2 配置与构建 模块级配置文件中设置byteCodeHar: false 确保release模式下混淆配置已开启 混淆规则文件中必须注释字节码开关 -enable-bytecode-obfuscation(删除或者注释掉) 点击右上角Build Mode选择release 执行Clean Project清理整个项目中的编译产物 选中需要打包的模块文件,执行Make Module进行构建 得到混淆后的JS中间码形态HAR包 6.4 源码打包文件混淆后的效果 七、字节码HAR vs 源码HAR 核心对比 维度 字节码HAR(release) 源码HAR(debug) 源码HAR(release+混淆) 产物形态 .abc字节码 完整.ets源码 混淆JS中间码 调试支持 不支持 支持 不支持 安全性 极高 低 中 开源库发布 ✅ 标准格式 ❌ 不使用 ❌ 不使用 适用场景 正式发布/开源SDK 本地开发、内部调试 兼容旧版本环境 关于源码打包作为了解,本节我们还是以字节码为主,将配置内容调整到字节码以便接下来发布har包做好准备。 八、HAR共享包发布与跨项目使用 8.1 准备发布 注册登录 OpenHarmony 三方库中心仓账号,并完成实名认证,这是发布三方库的前提。 创建存放密钥的文件,示例在系统目录创建默认隐藏文件夹.ssh_ohpm,~/.ssh_ohpm/preferenceskey 为私钥文件路径。不要把密钥放在项目工程里提交到Git。 使用 ssh-keygen 工具生成加密密钥对,用于身份认证与安全发布。 终端执行命令生成密钥: ssh-keygen -m PEM -t RSA -b 4096 -f ~/.ssh_ohpm/preferenceskey 8.2 执行结果 公钥私钥存放在同一目录下,preferenceskey.pub 为公钥。 8.3 找到公钥(.pub) 8.4 配置公钥 用文本编辑器打开公钥,复制内容到OHPM后台认证管理中,提示添加成功。 8.5 必需文件(模块根目录) README.md:库介绍、使用说明、依赖方式 CHANGELOG.md:版本更新记录 LICENSE:开源许可协议文件 8.6 发布前注意 发布前必须重新Clean Project并构建,确保LICENSE文件打入HAR包,否则发布失败。 8.7 获取发布ID 8.8 发布命令 cd preferences ohpm config set key_path ~/.ssh_ohpm/preferenceskey ohpm config set publish_id 你的发布ID ohpm publish ./build/default/outputs/default/preferences.har 8.9 发布结果 发布HAR包成功 发布HAR包审核消息 8.10 跨项目使用 HAR发布并通过审核后,在其他项目直接安装,在之后的章节中如有需要用到preferences直接开启使用。 # 安装 ohpm install @happy/preferences # 卸载 ohpm uninstall @happy/preferences 九、内容总结 字节码HAR(release):开源库标准格式,安全高效,正式发布必须用它。 源码HAR(debug):纯源码,仅用于本地调试。 源码HAR(release):混淆JS中间码,仅用于兼容老旧环境,新版不用。 混淆仅在release模式生效,必须保留工具库对外接口。 签名+发布是开源库标准化流程,是SDK开发必备技能。 十、代码仓库 工程名称:PreferenceLibDemo 仓库地址:https://gitee.com/HarmonyOS-UI-Basics/harmony-os-ui-basics.git 十一、下节预告 下一节,我们将学习鸿蒙生态中 最轻量化的UI复用方案 。你将掌握 @Builder 组件内/全局双模式定义 、按值/按引用传参与刷新机制 @BuilderParam 插槽高级用法 ,并彻底搞懂 this指向在组件传递中的核心规则 ,快速实现UI片段高效复用,为后续封装可复用轻量UI元素做基础准备。