FFCA Routing 是 FFCA monorepo 中配置导航的工作流。模式与代码形态位于插件根目录的 references/ffca/navigation.md 和 references/code_templates/presentation_templates.md,在接线路由前应先阅读。
核心约束 功能相互隔离,因此功能不能知晓应用的全局路由表,从不导入应用路由或其他功能的路由。导航是应用层注入的依赖:应用决定接下来发生什么,功能只检测何时需要导航。
选择注入模式 浅层部件树:在模块上使用回调。模块构造函数接收类型化回调(如 onProductTapped、onCheckoutStarted),由应用提供。 深层部件树:定义导航接口。在功能表示层包中定义普通 Dart 类,持有全部导航动作,在模块中要求它并通过 Provider.value 提供给子树,深层部件随后用 context.read<CartNavigation>().onProductTapped(id) 调用,无需属性逐层传递。 无论选择哪种,模块边界上的回调都是编译期安全的跨功能契约。
使用 go_router_builder 在应用层接线路由 应用定义 @TypedGoRoute 与 GoRouteData 类,实例化功能模块并把回调接到类型化路由导航。两条硬性规则:不使用字符串路径,应使用生成的路由类(如 ProductDetailRoute(id: id).go(context)),而非 context.push('/product/123');功能不得导入应用路由配置或其他功能的路由类。
拆分路由表但保持单一库 go_router_builder 会把同一库中所有 @TypedGoRoute 收集到一个生成的 $appRoutes;声明在独立库中的路由会被静默遗漏,构建成功但路由不存在。因此每个功能的路由文件须以 part of 'routes.dart'; 加入同一库:routes.dart 保存全部导入、part 指令与根路由,各功能文件为 part,另有生成的 routes.g.dart。
延迟导入放在路由表中 由于所有导入集中在 routes.dart,每个功能的 deferred as 前缀也放在那里,使代码在首次需要该路由时才获取。存在子功能 barrel 时导入它而非整个包。需注意:延迟包不能同时通过非延迟路径从应用可达,否则分块不会拆分且无提示;在仅 iOS/Android 应用上此为信息性说明,AOT 快照包含整个程序。
深链接与 $extra 模式 每个屏幕必须仅凭 URL 参数重建。$extra 是易失优化,在浏览器刷新、进程死亡和冷启动深链接时丢失,因此路由将其声明为可空,Bloc 视其为可选:存在时立即发出 Loaded,否则按 id 获取并显示加载状态。
可视化扩展点 功能可声明一个自己并不拥有的部件插槽,由应用填充,正如它为自己不拥有的目的地声明回调。
Add-to-app 模块是带显式依赖的自包含入口点,可直接作为 FlutterEngine 的根部件实例化,而非放在 GoRouteData.build() 内;模块代码相同,仅回调目标改变。