Flutter中Go_Router+Firebase Hosting的DeepLink兼容问题求助
兼容GoRouter DeepLink与Firebase Hosting Web访问的解决方案
你的问题核心是带#的链接在APP里路由不匹配,去掉#后Web端Firebase返回404,下面分两步解决,确保两端都正常工作:
一、修复APP端带#的DeepLink路由问题
当APP收到带#的DeepLink时,GoRouter拿到的location是完整的scheme/host/#/firstScreen/...,但你的路由配置是基于/firstScreen/...的,所以得先把多余的前缀砍掉,只留#后面的路由部分。
两种处理方式:
1. 用GoRouter的redirect自动处理
初始化GoRouter时加个redirect逻辑,自动提取有效路由:
final router = GoRouter( initialLocation: '/', redirect: (context, state) { final rawLocation = state.location; // 检查是否包含#,拆分出后面的路由路径 if (rawLocation.contains('#')) { final validRoute = rawLocation.split('#').last; // 如果拆分后是空的,跳首页,否则用提取出的路由 return validRoute.isNotEmpty ? validRoute : '/'; } return null; // 不需要重定向,用原路径 }, routes: [ // 你的路由配置,比如: GoRoute( path: '/firstScreen', builder: (context, state) => const FirstScreen(), routes: [ GoRoute( path: 'secondScreen', builder: (context, state) { final targetId = state.uri.queryParameters['id']; return SecondScreen(targetId: targetId); }, ), ], ), ], );
2. 在DeepLink监听里预处理(比如用app_links/firebase_dynamic_links)
如果你是通过第三方库监听DeepLink的,拿到链接后先解析再跳转:
// 以app_links为例 AppLinks().uriLinkStream.listen((Uri uri) { String targetRoute; if (uri.fragment.isNotEmpty) { // 带#的链接,取fragment部分 targetRoute = uri.fragment; } else { // 不带#的链接,直接取path targetRoute = uri.path; } // 确保路由以/开头,避免错误 if (!targetRoute.startsWith('/')) { targetRoute = '/$targetRoute'; } router.go(targetRoute); });
这样处理后,不管链接带不带#,APP都能正确匹配路由。
二、修复Firebase Hosting无#路径的404问题
用setPathUrlStrategy()去掉#后,Web端的路由是真实路径(比如/firstScreen/secondScreen),Firebase Hosting默认会去找这个路径下的静态文件,找不到就返回404。解决办法是配置重写规则,让所有请求都指向Flutter的index.html。
修改firebase.json
打开项目根目录的firebase.json,在hosting里加rewrites规则:
{ "hosting": { "public": "build/web", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "rewrites": [ { "source": "**", "destination": "/index.html" } ] } }
这个规则的意思是:所有请求路径(**匹配任意路径)都转到index.html,让Flutter单页应用自己处理路由,不会再出现404。
配置完重新部署:
firebase deploy --only hosting
三、最终兼容方案
- Web端保留PathUrlStrategy:用
setPathUrlStrategy()去掉URL中的#,配合Firebase的重写规则解决404。 - APP端兼容两种链接格式:不管接收到的链接带不带
#,都提取出正确的路由路径传给GoRouter。
这样就能同时满足:
- 未装APP的设备点击链接,跳转到Web端对应页面(无#路径,正常访问)。
- 已装APP的设备点击链接,APP启动后正确匹配路由。
内容的提问来源于stack exchange,提问作者foseja
相关产品推荐
相关产品推荐

