资源管理最佳实践:多模块资源复用策略

一、引言
在多模块 HarmonyOS 应用中,资源管理是一个容易被忽视但至关重要的问题。资源放哪儿?怎么引用?暗色模式怎么覆盖?跨模块怎么复用?这些问题如果处理不当,会导致资源冗余、引用混乱和包体积膨胀。
本文以一个包含 11 个模块的英语学习 App 为案例,系统分析其资源管理策略,涵盖目录结构、引用路径、暗色模式适配和跨模块资源复用方案。
二、多模块资源目录结构
本项目采用"通用资源集中 + 特有资源分散"的策略。每个模块的 resources/ 目录结构统一遵循 HarmonyOS 标准:
模块名/
src/main/resources/
base/ # 基础资源(默认主题)
element/ # 资源定义(颜色、字号、字符串等)
color.json
float.json
string.json
media/ # 图片资源
ic_back.png
ic_search.png
dark/ # 暗色模式覆盖
media/
ic_back.png
2.1 commonLib:通用资源的集散地
commons/commonLib 作为底层公共库,存放被所有模块共享的资源:
commons/commonLib/src/main/resources/
base/
element/
color.json # 基础色值定义
float.json # 字号/间距定义
string.json # 字符串定义
media/
banner1.png
ic_back.png # 通用返回按钮
ic_filled.svg # SVG 图标
ic_more.png
ic_upload.png
dark/
media/
ic_back.png # 暗色模式下的返回按钮(白色版本)
2.2 feature 模块:业务特色资源
每个 feature 模块拥有自己的资源目录,存放该业务特有的资源。以 homePage 为例:
features/homePage/src/main/resources/
base/
element/
color.json
float.json # 包含 50+ 自定义间距/字号
string.json # 业务相关字符串
media/
ic_avatar.png
ic_back.png
ic_search.png
ic_home.svg
ic_star.svg
ic_mic.svg
...
dark/
media/
ic_back.png
ic_delete.png
minePage 和 topicPage 类似,各自维护自己的资源集。
2.3 component 模块:自包含资源
组件模块为了保持独立性,也包含自己的资源。以 search 组件为例:
components/search/src/main/resources/
base/
element/
float.json
string.json
media/
ic_back.png
ic_delete.svg
dark/
media/
ic_back.png
三、资源引用路径分析
3.1 $r 引用语法
HarmonyOS 使用 $r() 函数引用资源,语法为:
typescript
$r('app.type.name') // 引用本模块或依赖模块的应用资源
$r('sys.type.name') // 引用系统资源
$r('har.type.name') // 引用 HAR 包资源(特殊场景)
3.2 应用资源 vs 系统资源
在主要页面中,应用资源和系统资源混合使用:
typescript
// product/entry/src/main/ets/pages/MainEntry.ets
.fontSize($r('sys.float.Caption_M')) // 系统字号
.fontColor($r('sys.color.icon_secondary')) // 系统颜色
.fontColor($r('app.color.icon_bg_blue')) // 应用自定义颜色
// features/minePage/src/main/ets/views/MinePage.ets
.backgroundColor($r('sys.color.comp_background_list_card')) // 系统色
.backgroundColor($r('sys.color.background_secondary')) // 系统色
.fontSize($r('sys.float.Title_M')) // 系统字号
.width($r('app.float.vp_16')) // 应用间距
.height($r('app.float.vp_16'))
选择策略:
- 系统资源优先 :
sys.color.*、sys.float.*等系统预置资源,自动适配深色模式和不同设备 - 应用资源补充 :
app.color.*、app.float.*用于自定义业务需求
3.3 常见资源引用示例
| 资源类型 | 引用方式 | 典型场景 |
|---|---|---|
| 系统颜色 | $r('sys.color.background_secondary') |
页面背景色 |
| 系统字号 | $r('sys.float.Title_M') |
标题字号 |
| 系统圆角 | $r('sys.float.corner_radius_level10') |
卡片圆角 |
| 应用颜色 | $r('app.color.icon_bg_blue') |
品牌色 |
| 应用间距 | $r('app.float.vp_16') |
布局间距 |
| 应用图片 | $r('app.media.ic_search') |
图标 |
| 应用字符串 | $r('app.string.page_show') |
页面文案 |
四、暗色模式资源覆盖
4.1 覆盖机制
HarmonyOS 的暗色模式通过 resources/dark/ 目录实现。系统在切换到深色模式时,自动加载 dark/ 目录下的同名资源覆盖 base/ 目录中的资源。
以返回按钮图标为例:
# 亮色模式
resources/base/media/ic_back.png → 深色图标
# 暗色模式
resources/dark/media/ic_back.png → 白色/浅色图标
4.2 项目中使用了 dark 覆盖的模块
几乎所有模块都提供了暗色模式的图标覆盖:
| 模块 | 覆盖的资源 | 路径 |
|---|---|---|
| commonLib | ic_back.png | commons/commonLib/src/main/resources/dark/media/ic_back.png |
| homePage | ic_back.png, ic_delete.png | features/homePage/src/main/resources/dark/media/ |
| minePage | ic_back.png, iconRight.png, person.png, star.svg | features/minePage/src/main/resources/dark/media/ |
| topicPage | ic_back.png, ic_share.svg | features/topicPage/src/main/resources/dark/media/ |
| search | ic_back.png | components/search/src/main/resources/dark/media/ |
4.3 最佳实践
1. 图标必须覆盖
带有透明背景的图标在深色模式下会"消失",因此需要提供高亮版本。
2. 颜色无需覆盖
使用 $r('sys.color.*') 系统颜色的场景,系统会自动切换色值,无需在 dark/ 中定义。
3. 图片资源考虑 9-patch
对于需要拉伸的背景图,使用 9-patch 格式(.9.png),暗色模式提供对应的暗色版本。
4. SVG 优先
SVG 图标更小、支持主题色继承,优先使用 .svg 格式。项目中 ic_filled.svg、ic_star.svg、ic_home.svg 等均为 SVG 格式。
五、跨模块资源引用限制与解决方案
5.1 核心限制
HarmonyOS 的 HAR 包之间存在资源引用限制:一个 HAR 包不能直接引用另一个 HAR 包的资源 。也就是说,在 base_select 组件中无法通过 $r('app.media.xxx') 引用 homePage 模块中的图片。
5.2 项目中的解决方案
本项目采用了多层分工的策略来解决这个问题:
第一层:通用资源放在 commonLib
commonLib 被所有模块依赖,放在其中的资源对所有模块可见:
json5
// commons/commonLib/src/main/resources/base/media/
// 以下资源对所有依赖 commonLib 的模块可见
banner1.png
ic_back.png
ic_filled.svg
ic_more.png
ic_upload.png
所有 feature 模块和 entry 模块都依赖 commonLib:
json5
// features/homePage/oh-package.json5
{
"dependencies": {
"commonlib": "file:../../commons/commonLib"
}
}
因此,在任何页面中都可以引用:
typescript
Image($r('app.media.ic_back')) // commonLib 中的资源
第二层:特有资源放在模块内
各模块特有的资源存放在自己模块内,不对外暴露。例如 homePage 特有的 ic_home.svg 只能被 homePage 模块中的页面引用。
第三层:entry 层资源的特殊地位
product/entry 作为应用入口模块,拥有访问所有模块资源的能力,因此一些需要在全局引用的资源可以放在 entry 层。
5.3 资源冲突处理
当多个模块定义了同名资源时,最后构建的模块覆盖前面的。为了避免冲突:
- 命名约定 :资源名使用模块前缀,如
homePage使用ic_home.svg、minePage使用icon_msg.png - commonLib 优先:通用资源优先定义在 commonLib 中,避免重复
- 系统资源优先 :能用
$r('sys.color.*')的,尽量不创建自定义资源
5.4 实际引用示例分析
从 MinePage 的源码可以观察资源的混合使用模式:
typescript
// 系统资源(深色模式自动适配)
.fontSize($r('sys.float.Title_M'))
.fontColor($r('sys.color.font_primary'))
.backgroundColor($r('sys.color.comp_background_list_card'))
.borderRadius($r('sys.float.corner_radius_level10'))
// 应用资源(自定义业务)
Image($r('app.media.iconRight'))
Image($r('app.media.icon_practice'))
.width($r('app.float.vp_16'))
.height($r('app.float.vp_16'))
.margin({ left: $r('app.float.vp_12') })
这种混合使用模式确保了:
- 系统资源:自适应深色模式、字体缩放等系统设置
- 应用资源:满足业务特定的视觉需求
六、资源管理的工程化建议
6.1 float.json 的合理使用
本项目各模块的 float.json 中定义了大量的间距值:
json
{
"float": [
{ "name": "vp_2", "value": "2vp" },
{ "name": "vp_4", "value": "4vp" },
{ "name": "vp_8", "value": "8vp" },
// ... 从 2vp 到 300vp 共 50+ 个间距定义
]
}
建议:
- 只定义业务中实际用到的值,不必全覆盖
- 使用语义化的命名(如
vp_card_padding)替代纯数字命名 - 跨模块复用的间距定义在 commonLib 中
6.2 资源去重策略
定期使用工具扫描各模块的 media/ 目录,识别重复资源:
- 同样的
ic_back.png出现在了 5 个模块中 → 应该移到 commonLib - 只在一个模块中使用的资源 → 保留在模块内
- 资源只增不减 → 建立资源评审机制
6.3 SVG 优先原则
本项目同时使用了 .png 和 .svg 格式。SVG 的优势:
- 文件小(通常为 PNG 的 1/5 ~ 1/10)
- 无损缩放,适合多分辨率适配
- 支持颜色继承,部分场景下暗色模式无需额外资源
建议新资源优先使用 SVG 格式,仅复杂照片类资源使用 PNG。
七、总结
多模块资源管理需要遵循以下核心原则:
- 集中共享:通用资源集中在 commonLib,被所有模块依赖
- 分散自治:模块特有资源放在模块内,不对外暴露
- 系统优先 :优先使用
sys.*系统资源,减少自定义资源 - 暗色覆盖 :只覆盖
media/资源,颜色通过系统资源自适应 - 命名防冲突:使用模块前缀或语义化命名,避免同名覆盖
通过合理的资源分层和管理,11 个模块的庞大工程保持了资源的清晰可维护,既避免了冗余,又实现了跨模块复用。
八、参考源码路径
| 文件 | 路径 |
|---|---|
| commonLib 资源目录 | d:\HarmonyOS\WorkSpace\Exam1.0.4\commons\commonLib\src\main\resources\ |
| homePage 资源目录 | d:\HarmonyOS\WorkSpace\Exam1.0.4\features\homePage\src\main\resources\ |
| minePage 资源目录 | d:\HarmonyOS\WorkSpace\Exam1.0.4\features\minePage\src\main\resources\ |
| topicPage 资源目录 | d:\HarmonyOS\WorkSpace\Exam1.0.4\features\topicPage\src\main\resources\ |
| search 组件资源目录 | d:\HarmonyOS\WorkSpace\Exam1.0.4\components\search\src\main\resources\ |
| MainEntry 资源引用 | d:\HarmonyOS\WorkSpace\Exam1.0.4\product\entry\src\main\ets\pages\MainEntry.ets |
| MinePage 资源引用 | d:\HarmonyOS\WorkSpace\Exam1.0.4\features\minePage\src\main\ets\views\MinePage.ets |