flutter web(托管在 nodejs 中)在使用 setPathUrlStrategy 时无法手动导航到其他页面(从 url 中删除 #)

flutter web(hosted in nodejs) unable to navigate to other page manually when using setPathUrlStrategy (remove # from url)

我正在构建一个 flutter web 来分别为不同的页面提供服务,页面之间没有内部导航,用户在您手动输入 url 时单独访问页面。我使用 setPathUrlStrategy (url_strategy: ^0.2.0) 删除了 url 中的#。每个页面都会有各种路径查询参数,我使用 Uri.base.queryParameters["param1"] 来获取查询参数值。所有这些在我的开发本地主机上都运行良好。但是当部署到生产环境时,我使用 nodejs 来托管我的 flutter web 应用程序,如 https://blog.logrocket.com/flutter-web-app-node-js/ 中所述。网络只能加载登陆页面(例如 myweb.com/home),当我手动输入 url(例如 myweb.com/registration)时,我收到错误消息“无法获取/注册”

我已尝试按照此处所述添加 .htaccess(如下所示)(unable to navigate in flutter web by changing url after removing # from the url),但这根本没有帮助。

RewriteEngine on 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html?path= [NC,L,QSA]

我相信有某种 url 重写我需要在某个地方编码,在 flutter web 或托管 flutter web 的 nodejs 中?

那么我怎样才能让它工作?

这是托管 flutter web 应用程序的 nodejs 代码 (../build/web是flutter web release版本所在的文件夹)

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser'); 
var app = express();
  
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, '../build/web')));

var http = require('http');
var port = normalizePort('10810');
app.set('port', port);

var server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    return val;
  }

  if (port >= 0) {
    return port;
  }

  return false;
}
 

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  console.log('Listening on ' + bind);
}

flutter 网页代码:

 
import 'package:flutter/material.dart';
import 'package:get/get.dart'; 
import 'package:mycode/page/page_home.dart';
import 'package:mycode/page/page_reg.dart';
import 'package:mycode/page/page_status.dart';
import 'package:url_strategy/url_strategy.dart';
 

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  setPathUrlStrategy(); 
  runApp(const MyApp());
}
 

class MyApp extends StatelessWidget { 
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    String initRoute = PageReg.routeName; 
    return GetMaterialApp(
      navigatorKey: navigatorKey,
      debugShowCheckedModeBanner: false,
      title: 'EDDA Registration',
      initialRoute: PageHome.routeName,
      getPages: [
        GetPage(name: PageReg.routeName, page: () => PageReg()),
        GetPage(name: PageStatus.routeName, page: () => PageStatus()),
        GetPage(name: PageHome.routeName, page: () => PageHome()),
      ],
    ); 
  }
}

您的快递服务器的路由设置似乎不正确。当您尝试访问“/registration”时,您的快速服务器正在尝试进行路由而不是您的 Flutter/web 应用程序,因此您会收到 Cannot GET /registration 错误消息,我认为这也是 return正在处理 404 状态代码,因为它不存在。

最简单的解决方案是将来自您的快速服务器的所有 GET 请求设置为 return 网络应用程序并在其中处理路由。理想情况下,路由应该完成 server-side 但在这种情况下,您正试图在您的网络应用程序中处理它。

尝试在第 9 行之后添加此代码并重新启动您的 Express 应用程序,这将 return 您的 Fluter Web 应用程序在每次 GET 请求到您的 Express 服务器时,然后您就可以在您的 Web 应用程序中处理路由(记住也可以在您的 Flutter 网络应用中添加 404/routing not found 页面!)

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, '../build/web')));
app.get('*', (_, res) => {
  res.sendFile(path.resolve(__dirname, '../build/web/index.html'));
});