HarmonyOS 鸿蒙Next中多 HAP/HSP 模块间 Resources 资源覆盖与合并优先级:为什么 icon 被替换了?
HarmonyOS 鸿蒙Next中多 HAP/HSP 模块间 Resources 资源覆盖与合并优先级:为什么 icon 被替换了? 项目采用多模块架构(entry + 2 个 HAR + 1 个 HSP),在资源管理上遇到了以下问题:
- 图标被替换:entry 模块的 resources/base/media/app_icon.png 是 A 图标,但某个 HAR 模块也定义了同名的 app_icon.png,最终安装后应用图标变成了 HAR 里的版本
- 字符串取错值:多个模块都定义了 $string:app_name,有的模块显示的是 entry 的值,有的模块显示的是 HAR 的值,行为不一致
- HSP 资源不生效:HSP 模块中定义了 $color:primary_color,但在 entry 中引用时取到的是 entry 自己的值,HSP 的值被忽略了
- overlay 机制不清楚:听说有资源 overlay 机制可以覆盖系统资源,但文档描述模糊,不知道优先级如何
更多关于HarmonyOS 鸿蒙Next中多 HAP/HSP 模块间 Resources 资源覆盖与合并优先级:为什么 icon 被替换了?的实战教程也可以访问 https://www.itying.com/category-93-b0.html
尊敬的开发者,您好,
【背景知识】
资源访问优先级由资源加载机制和模块依赖关系共同决定。系统按照以下顺序查找同名资源(优先级从高到低):
- 当前模块资源:当前代码所在模块的资源目录(如 entry/src/main/resources/base)。
- 直接依赖模块:当前模块直接在 module.json5 中声明的依赖模块。
- 传递依赖模块:直接依赖模块的依赖(即间接依赖)。
- 公共模块(Common):通常作为基础库被所有模块依赖的公共资源。
例如在 dependencies 里面有多个依赖库:
{
"dependencies": {
"a": "file:../a",
"b": "file:../b",
"c": "file:../c"
}
}
则优先级为当前模块entry -> a -> b -> c
【解决方案】
资源重名,会按照优先级进行覆盖,在编译构建HAP时,DevEco Studio会从HAP模块及依赖的模块中收集资源文件,如果不同模块下的资源文件出现重名冲突时,DevEco Studio会按照以下优先级进行覆盖(优先级由高到低):
- AppScope(仅API9的Stage模型支持)。
- HAP包自身模块。
- 依赖的HAR模块,如果依赖的多个HAR之间有资源冲突,会按照依赖顺序进行覆盖(依赖顺序在前的优先级较高)。 例如下方示例中dayjs和lottie中包含同名文件时,会优先使用dayjs中的资源。
// oh-package.json5
{
"dependencies": {
"dayjs": "^1.10.4",
"lottie": "^2.0.0"
}
}
另外如果在AppScope/HAP模块/HAR模块的国际化目录中配置了资源,在相同的国际化限定词下,合并的优先级也遵循上述规则。同时,国际化限定词中配置的优先级高于在base中的配置。如:在AppScope的base中配置了资源字段,在HAR模块的en_US中配置了同样的资源字段,则在en_US的使用场景中,会更优先使用HAR模块中配置的资源字段。关于HSP 资源不生效是因为构建时会将 HSP 的资源配置合并到 HAP 中,但运行时 HAP 无法直接访问 HSP 的资源文件,如果需要使用 HSP 资源可以参考:访问跨HAP/HSP包资源
因此,对于不同模板中资源名冲突这种情况,应当:
-
避免命名冲突。
-
公共资源使用唯一命名(如 common_icon.png)。
-
模块特定资源使用模块前缀(如 a_icon.png)。
-
将公共资源放在专门的 common 模块,避免在多个模块重复定义。
-
使用 module.json5 的 exclude 字段排除不需要的资源。
"resources": { "exclude": ["media/icon.png"] // 排除特定资源 }
参考文档:导出资源。
更多关于HarmonyOS 鸿蒙Next中多 HAP/HSP 模块间 Resources 资源覆盖与合并优先级:为什么 icon 被替换了?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
一、问题现象
在多模块 HarmonyOS 工程中,如果 HAP、HAR、公共模块或依赖库中存在名称相同的资源文件,构建时可能会出现资源被覆盖的情况。最终生效的资源并不是随机决定的,而是由模块自身资源、依赖关系以及资源限定目录共同决定。
二、资源生效规则
构建 HAP 时,DevEco Studio 会收集当前模块及其依赖模块中的资源,并按照优先级进行合并。当多个位置存在同名资源时,优先级较高的资源会覆盖优先级较低的资源。
整体优先级通常可以理解为:
AppScope > HAP 当前模块 > 依赖的 HAR 模块
其中,AppScope 资源仅在 API 9 Stage 模型下支持。
对于多个 HAR 依赖之间的资源冲突,则会根据依赖声明顺序判断优先级。声明越靠前,优先级越高。
例如:
{
"dependencies": {
"dayjs": "^1.10.4",
"lottie": "^2.0.0"
}
}
如果 dayjs 和 lottie 中存在同名资源,则会优先使用 dayjs 中的资源。
同理,如果依赖关系如下:
{
"dependencies": {
"a": "file:../a",
"b": "file:../b",
"c": "file:../c"
}
}
资源优先级可以理解为:
entry 模块 > a > b > c
三、国际化资源的优先级
如果资源配置在国际化目录中,还需要结合限定词进行判断。在相同限定词场景下,资源仍然按照模块优先级进行合并。
但需要注意的是,限定词目录中的资源优先级高于 base 目录中的资源。
例如,AppScope/base 中配置了某个资源字段,而某个 HAR 模块的 en_US 目录中配置了同名字段,那么在 en_US 环境下,会优先使用 HAR 模块 en_US 目录中的资源。
四、HSP 资源访问说明
HSP 的资源在构建阶段会参与合并,但运行时 HAP 不能直接访问 HSP 内部的资源文件。因此,如果业务中需要使用 HSP 中的资源,应按照跨 HAP/HSP 包资源访问方式进行处理,而不能直接按普通 HAP 或 HAR 资源的访问方式使用。
五、推荐处理方式
为了避免不同模板或模块之间出现资源冲突,建议从命名和资源归属两方面进行规范:
-
避免多个模块使用完全相同的资源名称。
-
公共资源统一添加公共前缀,例如:
common_icon.png
common_bg_login.png
- 模块私有资源添加模块标识,例如:
user_icon.png
order_empty.png
a_icon.png
-
将通用资源集中放入独立的
common模块,避免多个模块重复维护同一份资源。 -
对于不需要参与打包的资源,可以在
module.json5中通过exclude排除:
"resources": {
"exclude": ["media/icon.png"]
}
六、总结
资源重名时,最终生效结果主要取决于模块优先级、依赖声明顺序以及资源限定词目录。为了减少构建期覆盖带来的不确定性,建议在项目初期就制定统一的资源命名规范,并将公共资源集中管理。
学习了
资源匹配
应用使用某资源时,系统会根据当前设备状态优先从相匹配的限定词目录中寻找该资源。只有当resources目录中没有与设备状态匹配的限定词目录,或者在限定词目录中找不到该资源时,才会去base目录中查找。rawfile是原始文件目录,不会根据设备状态去匹配不同的资源。
限定词目录与设备状态的匹配规则
- 在为设备匹配对应的资源文件时,限定词目录匹配的优先级从高到低依次为:移动国家码和移动网络码 > 区域(可选组合:语言、语言_文字、语言_国家或地区、语言_文字_国家或地区)> 横竖屏 > 设备类型 > 颜色模式 > 屏幕密度。
- 如果限定词目录中包含移动国家码和移动网络码、语言、文字、横竖屏、设备类型、颜色模式限定词,则对应限定词的取值必须与当前的设备状态完全一致,该目录才能够参与设备的资源匹配。例如,限定词目录“zh_CN-car-ldpi”不能参与“en_US”设备的资源匹配。
- 如果存在多个屏幕密度限定词目录,则优先向上匹配最接近的屏幕密度限定词目录,否则向下匹配最为接近的屏幕密度限定词目录。例如,假设存在限定词目录“xldpi”和“xxldpi”,设备屏幕密度为“xxldpi”,则会匹配“xxldpi”限定词目录。
应用界面加载资源规则,更多请参考国际化和本地化文档。
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/resource-categories-and-access-V5
多模块工程里,资源名冲突最好当成设计问题处理,不要依赖构建合并时的偶然优先级。尤其是 app_icon、app_name、primary_color 这种通用名称,在 entry、HAR、HSP 中重复很容易出现你看到的覆盖和取值不一致。
建议规范如下:
- entry 只放应用级资源,比如图标、应用名、全局主题 token。
- HAR/HSP 资源加模块前缀,例如 order_icon_xxx、pay_color_primary,避免和 entry 同名。
- 公共组件不要引用 app_name、app_icon 这类应用级资源,改成由宿主传入。
- HSP 的资源尽量在 HSP 自己的组件内部消费,跨模块引用时要明确模块边界和依赖关系。
- overlay 机制不要用来解决业务模块资源冲突,它更偏资源替换/定制场景。
简单说,模块化项目要靠命名空间和资源职责划分来避免覆盖,而不是靠同名资源比较优先级。
他这个取值定义就是要求不要同名,
这类问题建议先把“资源归属”和“资源名称”拆开看:
-
$r(‘app.xxx.name’) 最终对应的是一个 Resource 描述对象,里面包含 bundleName、moduleName 和资源 id。跨 entry/HAR/HSP 复用同一个资源名不是稳定契约;不同模块代码里生成的 Resource 归属可能不同,运行时再按资源对象或资源名取值,就容易出现“同名但来源不一致”的现象。
-
HAR 会随依赖方一起参与编译/打包,公共库里不要放 app_icon、app_name、primary_color 这类通用名,尤其不要和 entry 同名。建议给每个库资源加模块前缀,例如 lib_user_app_name、hsp_player_primary_color。
-
应用图标、应用名称这类入口级元信息只在 entry 的配置和 entry 资源里维护。库模块如果需要默认图标或文案,应使用库私有资源名,再由 entry 显式决定是否引用。
-
HSP 是独立共享包,entry 中写 $r(‘app.color.primary_color’) 不应期待自动解析到 HSP 的同名资源。HSP 组件内部使用自己的资源;如果 entry 需要使用 HSP 资源,建议由 HSP 导出 Resource 常量或接口,调用方直接传 Resource,避免靠同名覆盖。
-
overlay 不是普通业务模块之间的资源覆盖机制。公开能力是对声明为 overlay module 的模块进行启停和查询;普通 HAR/HSP 的资源冲突不建议用 overlay 解决。
排查建议:全仓搜索 app_icon、app_name、primary_color 等同名资源,先把公共库里的通用资源名全部重命名;清理构建缓存后重新安装;再确认 entry 的图标和应用名称只引用 entry 自己的资源。这样比依赖合并顺序稳定。
嗯,支持一下。。
期待解决
在HarmonyOS Next中,HSP共享包的资源优先级高于HAP模块。当HAP与HSP存在同名icon资源时,编译合并阶段HSP资源会覆盖HAP中的同名项,因此图标被替换。若多个HAP间同名,则feature模块优先级高于entry模块。需检查各模块resources下重复的同名文件。
HarmonyOS 多模块资源合并遵循“高优先级覆盖低优先级”的规则,默认顺序为:AppScope > entry 模块 > HSP > HAR。
-
icon 被 HAR 替换
按此规则,entry 的app_icon.png优先级高于 HAR,理论上不会被覆盖。若实际被替换,说明该 HAR 可能被配置为 resource overlay(资源叠加)模块,或项目在 AppScope/其他更高优先级位置也定义了同名资源。overlay 机制会主动覆盖低优先级资源,优先级最高。 -
字符串取不到统一值
资源解析遵循“模块内优先”。各模块在自身代码中引用$string:app_name时,会先解析本模块的同名资源;若本模块没有,才向上查找依赖模块。因此 entry 页面取 entry 的值,HAR 页面取 HAR 的值,表现出不一致,这是正常行为。 -
HSP 资源不生效
entry 中已定义了primary_color,优先级高于 HSP,所以 entry 引用时仍然使用自己的值。若要使用 HSP 的值,需在 entry 中删除同名资源。 -
overlay 机制
它是编译期资源覆盖机制,通过构建配置指定某个模块作为 overlay,其资源会覆盖常规优先级中的同名资源,用于适配不同设备或定制场景。

