Flutter Web路径路由迁移Nginx部署嵌套路由异常排查
问题描述
将Flutter Web应用从哈希路由迁移至路径路由,通过usePathUrlStrategy();实现,搭配GoRouter框架,部署在Docker+Nginx环境中。本地调试时所有路由均正常,但部署后出现以下异常:
- 根路由
/、一级路由/tos、/privacy可正常访问 /deeplink/recipes/asdas这类嵌套路由返回200状态码,但实际加载的是index.html而非Flutter的JS文件- 移除
usePathUrlStrategy();切换回哈希路由后,所有路由恢复正常
浏览器控制台报错信息:
Exception while loading service worker: DOMException: Failed to register a ServiceWorker for scope ('https://mywebsite.com/deeplink/recipes/') with script ('https://mywebsite.com/deeplink/recipes/flutter_service_worker.js?v=3781291051'): The script has an unsupported MIME type ('text/html'). The script has an unsupported MIME type ('text/html'). Uncaught SyntaxError: Unexpected token '<' (at main.dart.js:1:1)
提供的配置代码
GoRouter配置
final GoRouter _goRouter = GoRouter(routes: [ GoRoute( path: '/', builder: (context, state) { return const MyHomePage(); }, ), GoRoute( path: "/tos", builder: (context, state) => const TermsOfServicePage()), GoRoute( path: "/privacy", builder: (context, state) => const PrivacyPolicyPage()), GoRoute( path: "/deeplink/recipes/:recipeId", builder: (context, state) { final String? recipeId = state.pathParameters['recipeId']; final String? language = state.uri.queryParameters['lang']; return RecipeSharedPage( recipeId: recipeId, langCode: language, ); }, ), ]);
Nginx配置
server { listen 80; server_name mywebsite.com www.mywebsite.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name mywebsite.com www.mywebsite.com; ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem; add_header Strict-Transport-Security "max-age=63072000; preload" always; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /assets/ { root /usr/share/nginx/html; try_files $uri $uri/ =404; } }
问题原因与解决方案
核心原因
问题出在静态资源路径解析错误:
当访问嵌套路由/deeplink/recipes/asdas时,浏览器会以当前路由路径为基准加载静态资源(比如main.dart.js、flutter_service_worker.js),也就是请求/deeplink/recipes/main.dart.js这类不存在的路径。而你的Nginx配置中,仅对/assets/路径做了精准文件匹配,其他所有路径都会命中try_files $uri $uri/ /index.html规则,导致这些资源请求被返回了index.html,进而出现MIME类型错误和语法解析失败。
修复方案
修改Nginx配置,优先匹配Flutter Web的核心静态资源,确保它们从根目录正确加载,而非基于当前路由路径查找。调整后的配置如下:
server { listen 80; server_name mywebsite.com www.mywebsite.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name mywebsite.com www.mywebsite.com; ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem; add_header Strict-Transport-Security "max-age=63072000; preload" always; # 优先匹配Flutter核心静态资源,直接返回文件 location ~* ^/(main\.dart\.js|flutter_service_worker\.js|manifest\.json|favicon\.ico)$ { root /usr/share/nginx/html; try_files $uri =404; } location /assets/ { root /usr/share/nginx/html; try_files $uri $uri/ =404; } # 其他所有路径,返回index.html交给Flutter路由处理 location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } }
关键说明
- 规则顺序:核心资源的匹配规则必须放在通用的
location /规则前面,否则会被后者覆盖,无法生效。 - 资源范围:如果你的项目还有其他根目录下的静态资源(如自定义图标、配置文件),可以直接添加到正则匹配列表中。
内容的提问来源于stack exchange,提问作者finisinfinitatis
相关产品推荐
相关产品推荐

