前言 笔者最近了解了Flutter web相关的内容,本文会分享创建Flutter web项目、Flutter web项目预览,Flutter web项目和Flutter mobile(Flutter Android/iOS)项目的差别、搭建简易Dart服务器(解决跨域问题)、上线Flutter web项目相关内容。
一、创建Flutter web 项目
准备Flutter web 环境
更新本地环境为 beta channel最新版。(dev channel 也可以)
flutter channel beta
flutter upgrade
Flutter有如下4个channel:
flutter channel
Flutter channels:
beta
* dev
master
stable
Flutter 官方建议使用 stable 的channel。
master 是当前最新的channel;
dev 是当前最新的充分测试后的channel;
beta是每个月Flutter官方调整选出来的最好的dev的channel,并提升为beta channel;
stable是Flutter 认为是当前最稳定的channel。
开启项目支持Flutter web
flutter config --enable-web
如果想在当前已有项目Flutter mobile项目的基础上,添加Flutter web支持,可 cd 到 Flutter mobile 项目目录下,添加Flutter web支持。
新建Flutter web项目
如果之前没有创建过Flutter 项目,新建一个Flutter web项目可以使用如下命令。
flutter create 项目名(小写)
如:flutter create qi_flutter_web_demo
现有项目生成Flutter web 相关文件
如果之前创建过Flutter 项目,想现有项目生成web文件夹及index.html等文件可使用如下命令。
flutter create .
运行项目命令:flutter run -d chrome
遇到问题:运行失败
运行失败报错如下:
wangyongwangdeiMac:qi_flutter_page wangyongwang$ flutter run -d chrome
this source!
Downloading Web SDK... 1.1s
Launching lib/main.dart on Chrome in debug mode...
Error compiling dartdevc module:qi_flutter_page|lib/main_web_entrypoint.ddc.js
packages/qi_flutter_page/main_web_entrypoint.dart:9:18: Error: Too few positional arguments:
1 required, 0 given.
entrypoint.main();
^
AssetNotFoundException: qi_flutter_page|lib/main_web_entrypoint.ddc.js
Failed after 23.3s
Building application for the web... 33.5s
Failed to build application for the Web.
猜测原因:访问网址.不可达
Document not found继续看这段报错,可以发现Flutter web 项目的main 方法中不能有参数。
packages/qi_flutter_page/main_web_entrypoint.dart:9:18: Error: Too few
positional arguments: 1 required, 0 given.
entrypoint.main();
^AssetNotFoundException: qi_flutter_page|lib/main_web_entrypoint.ddc.js
Failed after 22.9s
问题在于main方法中参数
运行Flutter web 项目的时候,main方法中不能有参数。
void main(List<String> args) {
}
// 删除main方法名中的参数后,可以正常运行。
void main() {
}
Flutter web 项目预览
Flutter web 项目预览
上周和同事CH聊天学到的内容:Flutter web项目显示的网页的特点:
显示网页源代码的时候,可以网页发现显示的内容是html的body 中嵌套的main.dart.js。
显示页面源文件 页面源文件二、Flutter web 项目预览
运行Flutter web项目 默认会在Chrome浏览器中显示,不过在本机的Safari 浏览器中及模拟器中的浏览器中输入相应的网址,也可以显示相应的视图。
Flutter web 项目预览三、Flutter web项目 与 Flutter mobile 项目的不同
笔者在把现有Flutter mobile项目,直接支持Flutter web 的过程中遇到了网络请求报异常的问题,另外简单测试了2个三方库的在Flutter web项目中的体现。
HttpClient() 不能用于Flutter web 项目
try {
HttpClient client = HttpClient();
} catch (e) {
print('捕获异常:$e');
}
捕获异常:NoSuchMethodError: invalid member on null: 'indexOf'
import 'dart:html' as html;
html.HttpRequest.request(url).then((responseValue) {
});
三方库支持情况
笔者这里举2个自己使用过的2个三方库,shared_preferences、url_launcher均支持 Flutter web 项目。
下列代码对于Flutter web 项目中仍然支持打开加载url的窗口。
String soUrl =
if (await canLaunch(soUrl)) {
await launch(soUrl);
}
由如下代码及相应结果可知,shared_preferences 也支持 Flutter web 项目。
void _incrementCounter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int counter = (prefs.getInt('counter') ?? 0) + 1;
print('Pressed $counter times.');
await prefs.setInt('counter', counter);
}
ListTile2
Pressed 1 times.
ListTile2
Pressed 2 times.
ListTile2
Pressed 3 times.
ListTile2
Pressed 4 times.
ListTile2
Pressed 5 times.
如下图所示:
url_launcher shared_preferences sqflite四、简易Dart服务器
使用如下代码,可以本地启动一个Dart服务。
main() async {
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 9988);
await for (var request in server) {
request.response
..headers.contentType = ContentType('text', 'plain', charset: 'utf-8')
..write('Hello Dart! 你好Dart')
..close();
}
}
简易Dart 服务器示意
跨域问题
跨域问题描述
笔者使用Flutter web项目 请求服务端资源的时候遇到了跨域问题。
Flutter web项目跨域现象图现象图如下:
Flutter web项目跨域问题出现当前跨域问题的原因是端口号不同,访问Flutter web 的url 和 请求服务端资源的url的 端口号
不同。
请求的响应头中设置可跨域的origin,解决跨域问题
设置跨域的url 有2种设置方式:
- 1.设置一个或多个url;
- 如:request.response
..headers
.add('Access-Control-Allow-Origin', request.headers['origin'])
- 如:request.response
- 2.设置跨域的值为*;
..headers.add('Access-Control-Allow-Origin', '*')
注意:如果在本地测试使用,可以使用第二种方式,直接了当。但是一般线上的话最好使用第一种方式设置是否可以跨域请求。因为设置是否可以跨域,算是服务器在响应浏览器请求数据时的一种保护策略。
其中重点是在响应头中添加可以跨域的请求域。
如'Access-Control-Allow-Origin'可以指定特定的url,使url能够跨域请求。
如有需要指定允许多个url进行跨域请求。可以根据请求的origin的值,判断是否要做跨域响应头的处理。
main() async {
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 9988);
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 9988);
await for (var request in server) {
var accessControlAllowOrigin = [
'http://localhost:63062',
'http://localhost:55355'
];
if (request.headers['origin'] != null) {
for (String tempAllowOrigin in accessControlAllowOrigin) {
if (request.headers['origin'].first.contains(tempAllowOrigin)) {
request.response
..headers
.add('Access-Control-Allow-Origin', request.headers['origin'])
// ..headers.add('Access-Control-Allow-Origin', '*')
..headers.contentType =
ContentType('text', 'plain', charset: 'utf-8')
..write('Hello Dart! 你好Dart 跨域')
..close();
}
}
} else {
request.response
..headers.contentType = ContentType('text', 'plain', charset: 'utf-8')
..write('Hello Dart! 你好Dart 不需要跨域')
..close();
}
}
}
解决跨域问题
笔者在上边说明了处理运行Flutter web项目的时候,处理本地服务端接口和Flutter web项目运行网址出现跨域问题的处理方式。(其实对于编译后的Flutter web项目的产物直接放到自己的服务端项目的的静态文件目录下的时候,不会出现上述问题)
有时候我们的请求内容可能就需要跨域去请求数据,而且对方如果也不便添加相应的跨域响应头。此时,可使用Nginx 做反向代理来处理跨域问题。
Nginx 反向代理解决远端跨域问题
server {
listen 9080;
server_name localhost;
location ~ /columns/Qtest {
proxy_pass
}
}
本地Flutter web 项目跨域访问TesterHome Qtest测试之道
Nginx 配置反向代理及rewrite访问路径可实现访问远端文件不跨域。
location / {
proxy_pass
}
location ~ /api/qiwuzhoukanWeb {
rewrite /api/qiwuzhoukanWeb /;
proxy_pass
}
本地Flutter web 项目跨域访问奇舞周刊
五、Flutter web 项目上线
flutter build web
会在项目的build 目录中生成相应的资源文件及html 和js文件,把相关文件放置到服务端静态文件目录下即可。实现上线Flutter web项目。
参考学习网址
了解更多iOS及相关新技术,请关注我们的公众号: