Flutter Feature-First架构如何整合多个独立功能到同一页面
核心结论先给
你对Feature-First架构的依赖规则存在认知偏差,把首页作为独立shell_home模块放在features目录下才是合规方案,放到shared目录是错误做法。
先明确架构规则的边界
你之前认为新建home作为独立feature会违反依赖原则,本质是搞错了规则的适用范围:
- 架构禁止的是平级业务feature之间产生直接依赖:比如
posts模块直接导入stories模块的内部组件、调用内部逻辑,这种耦合会导致后续迭代改一个模块牵连另一个,是明确违规的。 - 专门负责页面组装、路由分发、全局布局的壳层模块(比如根容器、底部Tab框架、首页feed壳)不属于业务feature范畴,它的定位就是上层组装器,天然允许依赖下层的各个独立业务feature,完全符合依赖单向向下的原则,不存在违规问题。
为什么不建议把首页放到shared目录
shared/common目录的职责边界非常明确:只存放无任何业务属性的通用可复用资源,比如通用按钮组件、网络请求基类、全局主题配置、基础工具方法、公共无业务实体类,这类资源不绑定任何具体产品场景,所有模块都可以无负担调用。
而首页是强业务属性的页面:它要决定feed流里放哪些模块、模块排序、滚动联动逻辑、模块间的交互响应规则,这些都是和产品需求强绑定的业务逻辑。把这类代码塞到shared目录,会直接污染共享目录的职责,后续会有越来越多带业务属性的代码往shared里堆,最后共享目录变成耦合重灾区,完全失去拆分的意义。
推荐的落地目录结构
以类Instagram的feed首页为例,目录拆分可以参考如下结构:
lib/ ├── features/ // 所有业务模块+壳层模块统一放在该目录 │ ├── shell_home/ // 首页专属壳层模块,仅做组装,不写具体业务逻辑 │ │ ├── presentation/ │ │ │ ├── pages/ │ │ │ │ └── home_feed_page.dart // 首页容器页,负责排版组装各业务模块组件 │ │ │ └── widgets/ // 首页专属布局组件,比如多模块滚动容器、顶部吸顶栏 │ │ └── home_feed_controller.dart // 仅处理壳层逻辑:比如滚动联动、模块间事件转发 │ ├── posts/ // 独立帖子业务模块,不依赖任何其他业务模块 │ │ ├── data/ │ │ ├── domain/ │ │ └── presentation/ │ │ └── exports.dart // 仅对外暴露可公共复用的组件/方法,内部实现全部私有 │ │ └── widgets/ │ │ └── post_feed_list.dart // 帖子模块对外暴露的feed列表组件 │ ├── stories/ // 独立故事业务模块,无跨业务依赖 │ │ ├── data/ │ │ ├── domain/ │ │ └── presentation/ │ │ └── exports.dart │ │ └── widgets/ │ │ └── story_bar.dart // 故事模块对外暴露的顶部故事栏组件 │ └── user_profile/ // 其他独立业务模块 ├── shared/ // 纯通用无业务属性共享资源 │ ├── data/ │ ├── domain/ │ └── presentation/ │ └── widgets/ // 通用骨架屏、通用按钮、通用刷新组件等无业务组件 └── main.dart
组装时的避坑规则
- 每个业务模块只通过
exports.dart对外暴露明确设计为可复用的公共入口,模块内部的子组件、实现逻辑全部设为私有,禁止外部模块导入内部文件。 - 壳层模块只负责把各个业务模块暴露的公共组件按产品要求排版组合,不要在壳层里硬编码业务逻辑。如果出现跨模块交互(比如点击故事条跳转到对应作者的帖子列表),通过全局状态管理、事件回调、事件总线等松耦合方式通信,不要直接调用对方模块的内部方法。
- 如果后续要在首页新增功能入口(比如直播、推荐关注),只需要在壳层模块引入对应新业务模块的公共组件即可,原有posts、stories模块完全不需要修改,符合开闭原则。
特殊情况处理:如果你抽象的「多模块垂直滚动容器」是无业务属性的,后续多个页面都要复用,可以把这个纯容器组件抽到shared里,但具体往容器里塞哪些业务组件、塞的顺序、业务交互判断,必须放在对应壳层模块实现,绝对不能在shared组件里写业务判断逻辑。
内容的提问来源于stack exchange,提问作者thisisyusub
相关产品推荐
相关产品推荐

