flutter打包web\nginx\docker运行子路由访问404问题解决
下面是我问deepseek时的问题deepseek给了我一些思路,虽然没有解决问题,但是直接让我缩小了问题的排查范围,可以的。
一,问题描述
下面是我问deepseek时的问题
背景情况:我在使用flutter编写web应用
1,使用GoRoute进行path路由的管理
final GoRouter _router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
name: 'goods',
// Optional, add name to your routes. Allows you navigate by name instead of path
path: '/goods',
builder: (context, state) => GoodsPage(),
),
GoRoute(
name: 'pay',
path: '/pay',
builder: (context, state) => PayPage(),
),
GoRoute(
name: 'home',
path: '/',
builder: (context, state) => PayPage(),
),
],
);
2,使用flutter build web --web-renderer canvaskit --base-href /goods-front/ --no-tree-shake-icons --dart-define=ENV=prod命令进行flutter build打包
3,然后使用如下的dockerfile进行docker镜像打包
FROM nginx:stable-alpine
COPY build/web /usr/share/nginx/html/goods-front
EXPOSE 80
出现了问题,问题如下
使用docker在本地运行时,http://localhost/goods-front/正常显示
但是在http://localhost/goods-front/goods、http://localhost/goods-front/pay报错404不存在
如果,直接使用flutter在web端运行http://localhost/goods、http://localhost/pay、http://localhost/页面正常显示
仔细思考一下,给我找出出现404错误的原因
deepseek给了我一些思路,虽然没有解决问题,但是直接让我缩小了问题的排查范围,可以的
二,问题定位:
通过网络查询资料以及Ai问答,大致排查出是nginx中路由选择有问题
我的web程序本身有一个顶级子路由/goods-front/,并且这个是以文件夹的形式存放在nginx中,当我们访问次级路由时,例如:/goods-front/pay、/goods-front/goods时,它因为try_files等的匹配问题,没有找到具体的地址从而报错404,因此我们把nginx配置进行修改正确即可
location /goods-front {
root /usr/share/nginx/html;
try_files $uri $uri/ /goods-front/index.html;
}
上面就是我修改后的nginx.conf配置
1,location /goods-front {
这个是修改后的顶级子路由,当我们访问
http://localhost:80/goods-front
http://localhost:80/goods-front/
都可以匹配正常该逻辑
2,root /usr/share/nginx/html;
是该逻辑下的文件目录,这里我没有直接选定/usr/share/nginx/html/goods-front
3,try_files $uri $uri/ /goods-front/index.html
是进行匹配时的优先级顺序(先是路由、之后是目录、最后是index.html),这个比较关键
差不多相当于高考报志愿这么个意思,从一志愿一直找到最后一个志愿,如果其中有满足要求的,那恭喜你考上了,找到最后一个都没有,那不好意思,清华落榜生就是你了!(引用文案)
三,解决方案:
1,main.dart中的路由代码
void main() {
usePathUrlStrategy();
Global.init().then((e) => runApp(MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: _router,
);
}
}
final GoRouter _router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
name: 'goods',
// Optional, add name to your routes. Allows you navigate by name instead of path
path: '/goods',
builder: (context, state) => GoodsPage(),
),
GoRoute(
name: 'pay',
path: '/pay',
builder: (context, state) => PayPage(),
),
GoRoute(
name: 'home',
path: '/',
builder: (context, state) => PayPage(),
),
],
);
2,flutter打包命令,注意其中的子路由( /goods-front/)
flutter build web --web-renderer canvaskit --base-href /goods-front/ --no-tree-shake-icons --dart-define=ENV=prod --pwa-strategy=offline-first --release
3,nginx.conf配置
server {
listen 80;
server_name localhost;
# 使用 root 指令,路径自动拼接 location 前缀
location /goods-front {
root /usr/share/nginx/html;
try_files $uri $uri/ /goods-front/index.html;
}
}
4,Dockerfile打包配置
FROM nginx:stable-alpine
COPY build/web /usr/share/nginx/html/goods-front
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
5,我自己编写的打包脚本
# 这个是flutter打包web资源的命令
# 注意要在这里添加顶级子路由的命名/goods-front/
flutter build web --web-renderer canvaskit --base-href /goods-front/ --no-tree-shake-icons --dart-define=ENV=prod --pwa-strategy=offline-first --release
repository_name="xxxxxx/goods-front"
version="V2.1.3"
# 提取日期时间中的各部分(此处假设date命令输出格式符合预期,如需调整可修改对应位置的参数)
year=$(date +%Y)
month=$(date +%m)
day=$(date +%d)
hour=$(date +%H)
minute=$(date +%M)
second=$(date +%S)
# 组合成 yyyymmddHHMMss 格式
formatted_time="${year}${month}${day}-${hour}-${minute}${second}"
image_name="${repository_name}:${version}-${formatted_time}"
# 进行docker打包,注意平台选择否则会出现运行问题
docker build --platform=linux/amd64 -t "${image_name}" .
docker push "${image_name}"
# 显示镜像名称
echo "image_name: ${image_name}"
我自己按照上述配置就可以正常切换路由显示页面了
四,参考链接
1,(nginx官网try_files文档)[http://nginx.org/en/docs/http/ngx_http_core_module.html#try_files]
2,(深入理解Nginx try_files:用途、使用场景、注意事项和示例)(https://blog.csdn.net/u010260632/article/details/139177618)
3,(Nginx 报404问题,如何解决)[https://blog.csdn.net/Bean_ph/article/details/121373102]
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)