flutter web(托管在nodejs中)使用setPathUrlStrategy时无法手动导航到其他页面(从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),当我手动输入网址(例如myweb.com/registration)时,我收到错误“无法获取/注册”
我尝试添加到.htaccess(如下)如此处所述(无法在 flutter web 中导航通过在从 url 中删除 # 后更改 url),但这根本没有帮助。
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html?path=$1 [NC,L,QSA]
我相信我需要在 flutter web 或托管 flutter web 的 Nodejs 中的某个地方进行某种 url 重写?
那么我怎样才能做到这一点呢?
这是托管 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 web代码:
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()),
],
);
}
}
I am building a flutter web to serve different pages individually, no internal navigation among pages, users access the page individually as you manually type in the url. I removed the # in url using setPathUrlStrategy (url_strategy: ^0.2.0). Each page will have various query parameters to the path and I use Uri.base.queryParameters["param1"] to grab the query parameters value. All these are working fine on my development localhost. But when deploy to production, I use nodejs to host my flutter web app as described in https://blog.logrocket.com/flutter-web-app-node-js/ . The web only able to load the landing page(e.g myweb.com/home), when I manually enter the url (e.g myweb.com/registration), I received error "Cannot GET /registration"
I have tried add in .htaccess (as below) as described here (unable to navigate in flutter web by changing url after removing # from the url) but that doesn't help at all.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html?path=$1 [NC,L,QSA]
I believe there is some kind of url rewrite I need to code at somewhere, in flutter web or in the nodejs that hosting the flutter web?
so how can I make this work?
here is the nodejs code to host the flutter web app
(../build/web is the folder where the release version of flutter web)
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 web code:
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()),
],
);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的 Express 服务器的路由似乎未正确设置。当您尝试访问“/registration”时,您的 Express 服务器正在尝试执行路由而不是 Flutter/web 应用程序,因此您会收到
Cannot GET /registration
错误消息,我认为该消息也将是返回 404 状态代码,因为它不存在。最简单的解决方案是设置来自 Express 服务器的所有 GET 请求以返回 Web 应用程序并处理其中的路由。理想情况下,路由应该在服务器端完成,但在这种情况下,您尝试在 Web 应用程序中处理它。
尝试在第 9 行后添加此代码并重新启动您的 Express 应用程序,这将在每个 GET 请求上将您的 Fluter Web 应用程序返回到 Express 服务器,然后您可以在 Web 应用程序中处理路由(请记住添加 404/路由未找到页面)也在您的 Flutter Web 应用程序中!)
It appears as though your express server's routing has not been set up correctly. When you are trying to reach '/registration', your express server is attempting to do the routing rather than your Flutter/web app hence you get the
Cannot GET /registration
error message which I assume will also be returning a 404 status code as it doesn't exist.The easiest solution would be to set all GET requests from your express server to return the web app and handle the routing within that. Ideally, routing should be done server-side but in this case, you're attempting to handle it within your web app.
Try adding this code after line 9 and restart your express app, this will return your Fluter web app on every GET request to your express server and then you can handle the routing within your web app (remember to add a 404/routing not found page within your Flutter web app too!)