搜索
您的当前位置:首页正文

初识Flutter web

来源:二三娱乐

前言 笔者最近了解了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 web 新增index.html 等

运行项目命令: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'])
  • 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项目。

Flutter web项目编译产物

参考学习网址


了解更多iOS及相关新技术,请关注我们的公众号:

Top