去年底接了个项目,团队要在一个宿主App里同时跑三条业务线:用户中心、数据统计、还有每月至少两次的版本活动。最开始大家图省事,所有页面全塞在entry模块里,结果工程膨胀得厉害,随便改个活动页都要整个包重新编译,CI动不动就十几分钟。后来我花了一周时间把工程重构成基于Feature模块的架构,从那之后,每个业务小组各自维护一个独立模块,发版互不干扰,新增功能再也不用动主工程。
这个案例里的Feature模块,其实就是HarmonyOS应用工程里的独立功能模块,按常规习惯会命名为feature_xxx,它是动态化开发最顺手的一个武器。这篇文章就围绕这个"瑞士军刀"式的小案例展开,讲清楚它解决什么问题、怎么落地、以及我踩过的坑。无论你是刚接触HarmonyOS开发,还是已经在用多模块工程,这篇内容都能拿来直接参考。
1. 先说结论:Feature模块是什么,为什么要用它
1.1 一个真实的业务痛点
先回顾一下当时的问题。主工程里包含了登录、账单、统计、设置、活动、推送等所有功能,代码量到了一定程度之后,开始出现几类让人头疼的情况。
第一是编译慢。虽然DevEco Studio有增量编译,但模块内部的循环依赖一旦变多,改一处业务代码,连带编译的模块就会变多,一次调试构建从三分钟慢慢爬到了七八分钟,非常影响开发节奏。第二是协作冲突。多人同时改entry模块时,git提交冲突频繁,解决冲突的代价远超写代码本身。第三是动态化需求难以满足。业务方希望版本活动页可以单独更新,不用等主包发布,而动态化能力依赖的恰恰是把功能拆成独立模块,独立编译、独立交付。
我把这些痛点和团队的几个核心成员整理了一遍,最后得出一个结论:必须改成多模块工程。而Feature模块的引入,不只是改目录结构这么简单,它涉及依赖方向、路由通信、资源隔离、构建产物等一系列变化。
1.2 Feature模块、HAR、HSP三者之间的关系
HarmonyOS的工程里,默认会有一个entry模块作为应用入口,承担启动和全局初始化工作。而Feature模块按官方设计思路,是“按业务功能划分的独立模块”,比如feature_login、feature_statistics、feature_bill,每个模块可以包含自己的页面、服务、资源和逻辑代码。
但Feature模块本质上不是一个具体的东西,它可以通过两种工程形态来实现:
- HAR(HarmonyOS Ability Package):静态共享包,编译时打入宿主应用,类似于Android的Library。
- HSP(HarmonyOS Shared Package):动态共享包,运行时按需加载,支持独立升级和动态交付,这才是真正意义上的“动态化模块”。
所以在工程里创建Module时,如果选的是“HarmonyOS Shared Package”,那这个feature模块天然就是动态化的;如果选的是“Static Library”,那就是一个静态的feature模块,代码逻辑可以分离,但无法做到真正的按需动态加载。
这里有个很多人容易混淆的点:function模块(feature模块)不等于HSP,但工程实践里,我强烈建议用HSP去承载业务Feature模块。因为HSP支持动态加载——也就是应用市场可以只下发这个模块,不需要重新下载整个应用。对于高频更新、内容运营类的业务,这个能力太关键了。
1.3 动态化开发解决了什么问题
拆分之后,解决的不仅仅是编译时间问题,还打开了一个更大的可能性:模块级动态发布。具体来说有三个层面的收益。
第一,按需加载。用户只下载核心模块,辅助功能等到使用时再动态拉取,这直接减小了安装包的首包体积。比如统计报表这类低频功能,完全可以在用户点击时才加载对应HSP。
第二,独立交付。业务模块的迭代不再跟随应用主版本。活动页面需要临时上线时,只需独立构建并发布对应的HSP包,应用市场审核和发布范围都灵活很多。
第三,团队自治。每个Feature模块有明确的边界和负责人,模块间通过约定好的接口通信,不用关心对方内部的实现细节。编译、测试、发布都能做到一定程度的自治。
不过,动态化也不是越多越好。如果模块颗粒度太细,会导致工程碎片化,依赖关系复杂,反而增加维护成本。这个平衡点我在后面会详细说。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 物料准备与核心参数
2.1 工程环境要求
这个案例用的是HarmonyOS NEXT 5.0.x版本,开发工具是DevEco Studio 5.0及以上。要注意,NEXT版本不再兼容Android APK,所以工程里的API、SDK都要基于HarmonyOS自己的体系,这点和早期用API 9做双框架开发是不同的。
建议在一个
