HarmonyOS 应用开发《掌上英语》第1篇:HarmonyOS 多模块工程实践:从零搭建多模块应用
HarmonyOS 多模块工程实践从零搭建多模块应用一、引言在大型 HarmonyOS 应用开发中合理的工程结构是保证代码可维护性、团队协作效率和编译性能的关键。本文以一款英语学习 App 为例深入剖析如何从零搭建一个包含 11 个模块的分层架构项目。该应用采用entry → features → commons → components四层架构共管理 11 个独立模块。通过清晰的模块边界和依赖规则实现了业务逻辑的高内聚低耦合。无论你是正在重构单体应用还是从零开始新项目本文的多模块工程实践都值得借鉴。二、模块架构概览2.1 四层架构设计我们的模块采用分层设计每一层有明确的职责和依赖方向product/entry → 应用入口层装配所有模块 features/ → 业务特征层homePage、minePage、topicPage commons/commonLib → 通用能力层工具库、模型、路由 components/ → 业务组件层8 个独立业务组件依赖规则上层可以依赖下层下层不可反向依赖上层。具体来说entry依赖features、commons、componentsfeatures依赖commons和componentscomponents可依赖commonscommons不依赖任何业务模块2.2 11 个模块清单层级模块名路径职责entryentry./product/entry应用入口、Ability、首页 Tab 装配featureshomePage./features/homePage首页相关页面featuresminePage./features/minePage个人中心相关页面featurestopicPage./features/topicPage专题学习相关页面commonscommonLib./commons/commonLib通用工具、模型、管理器componentsbase_select./components/base_select基础选择组件componentsselect_category./components/select_category分类选择组件componentsanswer_questions./components/answer_questions答题组件componentslogin_info./components/login_info登录信息组件componentsaggregated_payment./components/aggregated_payment聚合支付组件componentsfeedback./components/feedback反馈组件componentssearch./components/search搜索组件componentssearch_question./components/search_question搜索题目组件三、核心配置文件解析3.1 build-profile.json5 — 模块声明与依赖项目的灵魂文件build-profile.json5中声明了所有模块的路径映射{ modules: [ { name: entry, srcPath: ./product/entry }, { name: homePage, srcPath: ./features/homePage }, { name: minePage, srcPath: ./features/minePage }, { name: topicPage, srcPath: ./features/topicPage }, { name: commonLib, srcPath: ./commons/commonLib }, { name: base_select, srcPath: ./components/base_select }, { name: select_category, srcPath: ./components/select_category }, { name: answer_questions, srcPath: ./components/answer_questions }, { name: login_info, srcPath: ./components/login_info }, { name: aggregated_payment, srcPath: ./components/aggregated_payment }, { name: feedback, srcPath: ./components/feedback }, { name: search, srcPath: ./components/search }, { name: search_question, srcPath: ./components/search_question } ] }关键点name是模块的唯一标识后续在oh-package.json5中依赖时需要引用此名称srcPath指向模块源码目录entry模块放在./product/下与业务代码物理隔离只有entry模块配置了targets因为它需要生成最终的应用产物3.2 oh-package.json5 — 模块级依赖管理每个模块都有自己的oh-package.json5通过file:协议引用本地模块。应用级oh-package.json5根目录{ dependencies: { dayjs: 1.11.13, hw-agconnect/util-log: 1.0.0, aggregated_payment: file:./components/aggregated_payment } }entry 模块oh-package.json5装配所有模块{ name: entry, dependencies: { hw-agconnect/util-log: 1.0.0, homepage: file:../../features/homePage, topicpage: file:../../features/topicPage, minepage: file:../../features/minePage, commonlib: file:../../commons/commonLib, login_info: file:../../components/login_info, answer_questions: file:../../components/answer_questions, feedback: file:../../components/feedback } }commonLib 模块oh-package.json5{ name: commonlib, main: Index.ets, dependencies: { answer_questions: file:../../components/answer_questions } }依赖关系图entry ├── homePage (features) ├── topicPage (features) ├── minePage (features) ├── commonLib (commons) │ └── answer_questions (components) ├── login_info (components) ├── answer_questions (components) └── feedback (components)四、模块职责详解4.1 commonLib — 通用能力层commonLib是整个应用的工具箱它不依赖任何业务模块。主要提供以下能力工具类Logger日志、PreferenceUtil持久化、AudioPlayer语音播放、RouterModule路由管理数据模型WordCard单词卡片、BreakpointModel断点模型、BaseViewModel基类 ViewModel管理器NewWordManager生词管理、StatisticsManager统计、DashboardManager仪表盘UI 组件CommonHeader、TopBar、Banner4.2 features 层 — 业务特征模块三个 feature 模块分别对应底部 Tab 的三个页面homePage首页包含 FeaturedCourses推荐课程、MaterialDownload资料下载、ChapterPractice章节练习等topicPage专题学习页包含 CourseHomePage卡片翻转学习、AnswerQuestionsPage答题、WordCardPage单词卡片、DailyChallengePage每日挑战等minePage个人中心包含 MinePage我的、SetUpPage设置、PracticeRecords练习记录、DashboardPage仪表盘等每个 feature 模块通过Index.ets导出 Builder 函数供 entry 层装配使用。4.3 components 层 — 业务组件8 个业务组件模块是细粒度的功能单元可被 features 和 entry 层复用answer_questions答题引擎选择题、判断题、填空题base_select基础选择器单选、多选select_category分类选择器login_info登录信息管理aggregated_payment聚合支付支付宝、微信等feedback用户反馈search搜索功能search_question题目搜索4.4 entry — 应用装配入口entry 模块作为应用的总装车间负责初始化路由表在EntryAbility.onCreate()中调用RouterTable.routerInit()注册所有页面注册断点监听在Index.aboutToAppear()中调用registerBreakpointListener()加载主页面通过Navigation NavPathStack实现声明式路由// EntryAbility.etsexportdefaultclassEntryAbilityextendsUIAbility{onCreate():void{RouterTable.routerInit();// 初始化所有路由}onWindowStageCreate(windowStage:window.WindowStage):void{windowStage.loadContent(pages/Index,(err){...});}}// Index.ets — 应用根页面EntryComponentV2struct Index{aboutToAppear(){GlobalContextUtils.setUIContext(entry,this.getUIContext());this.mainVM.registerBreakpointListener(this.ctx.windowStage.getMainWindowSync());// 首次启动 → 隐私协议页否则 → 主页letisFirstLaunchPreferenceUtil.getInstance().get(PreferConstant.FIRST_LAUNCH,true);if(isFirstLaunch){RouterModule.replace({url:RouterMap.PRIVACY_AGREEMENT_PAGE});}else{RouterModule.replace({url:RouterMap.MAIN_PAGE});}}build(){Column(){Navigation(RouterModule.stack){}.hideNavBar(true).navDestination(this.pageMap).width(100%).height(100%);}}}五、最佳实践5.1 模块划分原则按业务边界拆分每个模块应该有一个清晰的业务边界。例如支付相关的逻辑全部封装在aggregated_payment中其他模块只需通过接口调用。避免循环依赖commonLib虽然依赖了answer_questions但这种依赖应有明确理由。一般情况下commons 层应该保持纯洁不依赖任何业务组件。控制模块粒度模块太多会增加构建和依赖管理的复杂度。8 个组件模块中有些如search和search_question可以考虑合并。5.2 依赖管理建议使用file:协议引用本地模块路径使用相对路径避免在多个模块中重复声明相同的三方依赖如dayjs将其提升到根oh-package.json5entry层应作为胶水代码只做装配不做业务5.3 编译优化技巧修改模块间接口时优先在Index.ets中做重导出而不是直接修改内部文件合理配置build-profile.json5中的buildOption开启严格模式确保代码质量buildOption: { strictMode: { caseSensitiveCheck: true, useNormalizedOHMUrl: true } }六、总结本文详细介绍了 HarmonyOS 多模块工程的四层架构设计从build-profile.json5的模块声明到oh-package.json5的依赖管理再到每个模块的具体职责。通过这种分层解耦的架构设计我们实现了更好的团队协作不同团队可以并行开发不同模块更高的代码复用率commonLib 和 components 模块可被多个 feature 复用更快的构建速度增量编译时只需重新编译变更的模块更清晰的架构边界依赖规则强制执行防止架构腐化在下一篇《ArkTS 模块化开发Index.ets 统一导出模式深度解析》中我们将深入探讨模块接口设计的最佳实践。