详细介绍Flutter for Web环境配置、项目分析、构建开发流程
详细介绍Flutter for Web环境定义、项目分析、构建开发流程。
前言
在上海举行的谷歌开发者大会(GDD)上,Google Flutter团队宣布正式发布Flutter版本。这是 Flutter 迄今为止最大的版本更新,此外还提供了超过 1,500 个 PR 和实时通话支持。除了新的 Dart 版本 C 之外,我更关心的重要 Flutter For Web 更新是:开发团队已成功将之前独立的 Flutter for Web 集成到主 Flutter 存储库中。
在此之前,我们先来了解一下Flutter For Web是什么。自发布以来,Flutter 团队一直在发布 Flutter For Web 的预览版本。官方的解释是:Flutter For Web 支持是 Flutter 的代码兼容实现,它使用基于标准的 Web 技术进行渲染:HTML、CSS 和 JavaScript。借助在线支持,您可以将用 Dart 编写的现有 Flutter 代码组装成可嵌入到浏览器中并部署到任何 Web 服务器的客户端体验。您无需浏览器扩展即可使用所有 Flutter 功能。
与 Flutter For Mobile 不同,Flutter For Web 的技术框架如下:
从上图可以看到,在 Framework 层面,Flutter 基本相同,但在应用层面,Flutter For Web 依靠 Dart2JS 来转换浏览器可以识别的元素,并使用 DOM、Canvas 和 CSS 的组合将它们呈现给用户。最终的目标是为用户提供高质量、高性能的用户体验。对于开发人员来说,Dart 优化的 JavaScript 编译器将 Flutter 核心和框架与您的应用程序一起编译成可以部署到任何 Web 服务器的简化源文件。该源文件包含HTML文件、JS文件和一些资源。类文件。所有的dart文件最终都会编译成一个文件。
首次发布时,Flutter For Web 支持位于单独的 git 中:。
如果您要开发在线项目,则必须单独提交在线项目支持。 yaml配置如下:
这会导致什么问题?你的 Flutter 代码是基于 Flutter 主库来编写的,所有以 Flutter 开头的库都会被引入,比如:
import 'package:flutter/';
这里你需要呈现以 Flutter_web 开头的库,比如:
tuo 'package : flutter_web/';
这会导致你写的代码无法直接在web上运行。如果需要运行它,则需要复制它并进行更改。
在刚刚发布的Release版本中,Flutter For Web被集成到Flutter主项目中。原来的flutter_web项目已经废弃,从预览版改为技术预览版。这样做的好处是不需要实现单独的在线图书馆。当然,谷歌特别提醒,该技术的预览版尚未达到alpha版本,不建议在生产环境中使用。如果您想提出 Flutter 问题,建议在标题中包含 web 标签。
新版本的Flutter For Web项目和Flutter项目基本一致。
因为我们非常看好Flutter For Web的方向,所以我们率先研究了Flutter For Web的特性和可行性。我们经历了一些坑,正式公布了 Flutter For Web 开发的几个需求,接下来我们将从正式的需求开发角度来探讨 Flutter For Web。
需求分析
在补丁的预览版本中,其支持的元素和功能可能不是特别完整,这可能会导致某些功能无法实现,所以我们需要分析Flutter For Web当前的功能或者组件是否能够支持我们的需求,我们首先分析我们的需求。我们需要的不是简单的屏幕页面,而是包含图像、列表、文本、富文本、输入框、单选框和复选框的页面。 、按钮、下载框、网页请求、页面跳转、与客户端jsbride交互等功能并包含6个页面的完整需求(具体功能可参见现在直播客户端注销账号页面)。这样的需求基本上就是对客户网站的完整需求了。
环境设置
这里不再推荐老式的flutter_web项目,而是直接用最新的flutter主项目创建。首先,您需要运行“flutter Upgrade”命令将您的Flutter版本升级到上述版本。我这里用的是master版本,已经更新到master版本了。在这里截图一下我的配置:
然后运行“flutter config --enable-web”命令启用Web支持,然后就可以运行“flutter devices”命令了。如果出现“chrome”设备,则表示您的环境已配置。
按照官方说明,如果没有,可以用flutter doctor 检查一下你的配置。如果提示“CHR-OME_EXECUTABLE not set”,则需要在环境变量中设置CHROME_EXECUTABLE就可以了。
之后,您可以通过运行当前项目命令“flutter run -d chrome”来启动Web应用程序。如果您当前没有任何其他硬件,则无需配置 chrome。这个命令的好处是,如果你当前不是一个Web应用程序,flutter会提示你创建一个:
这时候,你可以运行“flutter create”命令。添加Web环境的命令:
这一次就够了,然后就可以运行run命令了,它会自动翻译成Web应用程序,然后启动Chrome:
你会看到已经启动成功了,并且会提示您使用“R”功能热支持重启。这里是命令行界面按R,不是在编辑区。
控制台有以下输出:
??? ???? ???? ???? ???? ???? ???? ???? ????警告:Flutter 对构建 Web 应用程序的支持还处于实验阶段。
更多信息:
https://github.com/flutter/flutter/issues/34082。
??? ???? ???? ??? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ? ????
注意这个提示:至少在这个问题得到解决之前,Flutter for Web 仍将保持实验状态,甚至可能更长时间。
Flutter For Web 项目分析
好,我们来分析一下这里的 Flutter 项目。
我们先分析一下Flutter Web项目,见下图:
重点分析项目的三个文件夹:
.vscode:该文件夹是vscode创建项目时自动创建的。为什么?我提到它是因为有一个名为 .稍后将分析该文件。
lib:这是编写 dart 代码的主要区域。在这里你可以像移动 Flutter 项目一样编写 dart 代码。我们的项目目录由页面、实用程序、小部件等组成,下面是一个自动生成的文件。
web:这是主 Web 目录。该目录主要包含和文件。但如果你需要例如资源文件、js文件等网页资源,我们的资源文件夹就是用来存放图片资源的。
这里重点关注项目的五个文件,
:为什么会提到自动生成的文件呢?首先,我们来看看这个文件的内容。
{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: "version": "", "configurations": [ { "name": "Dart", "program": "lib/", "request": "launch", "type": "dart" } ] }
这个文件注意到它的名字是Päättikka is lib/,可以在这里指定。如果不小心设置为bin/,就会报错。
:该文件主要是flutter项目配置文件。与移动项目的flutter相比,尚不支持插件。该项目依赖于flutter_web。
在 Web 下:
import 'package:flutter_web_ui/' as ui; import 'package:logout_account/' as app; main() async { await ui.webOnlyInitializePlatform(); (); }
此文件是启动整个 Web 应用程序的起点。这是调用平台初始化任务的地方,然后调用应用程序的整个主体来调用lib的main方法来启动页面。在
lib 下:
void main() =< runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: '注销账户', theme: ThemeData( primarySwatch: , ), home: MyHomePage(title: '注销账户'), ); } }
这与移动设备的 flutter 相同。主要方法是启动应用程序,启动MaterialApp并加载小部件。
网下:
>!DOCTYPE html< >html lang="en"< >head< >meta charset="UTF-8"< >title<注销账户>/title< >script defer type="application/javascript"<>/script< >/head< >body< >/body< >/html<
这里就更简单了。这是一个简单的 html 文件。该 html 提供了一个名为你会注意到,新创建的项目中并没有这个js文件,那么这个文件是从哪里来的呢?这其实是项目自动生成的一个js文件。我们稍后会对此进行分析。我们不建议在此html文件中创建元素、css样式等,但您可以将js文件上传到其中。如果你想在dart中调用js文件方法,请记住加载顺序。
从上面的分析应该知道,这里的开发其实是比较简单的。如果不需要部署任何js,可以直接在lib下开发自己的功能。如果你想引入一些第三方js库或者实现一些其他js方法,你可以在web目录下开发并部署。如果你想自己嵌入element和css样式,你会发现这是不可能的,但如果你想嵌入html页面,我们稍后会教你如何做。
如何构建
开发完成后,我们需要发布生产文件,那么需要发布哪些文件呢?我们来分析一下Flutter For Web的架构和产品。启动上述调试后,会在.dart_tool文件夹下创建一个build文件夹,其中包含生成的中间体。
由于需要支持热重载,所以debug模式下会创建多个JS文件。我们可以在页面上传的资源中看到这一点:
可以看到,这个页面加载了大量的js、html等文件。
那如果我们要发布的话,还需要那么多文件吗?如果是这样的话,就会给出版商带来很大的负担,因为要发送的文件很多。根据官方说明,我们使用“flutter build web”命令来构建并查看发布产品。
运行此命令后,将在项目构建目录中创建一个 web 文件夹,而不是 dart_tool 文件夹。该文件夹的内容如下:
该Web 目录包含一个文件夹和三个文件。分析下面的文件夹和文件。
资源:资源文件夹。打开后会发现这里存放的是web目录的资源文件,也就是说这个需要发布。系统会自动为您创建两个文件。在线使用时必须下载这两个文件。目前尚未找到保护方法。建议添加它们。否则会出现404错误。在某些服务器上可能会发生这种情况。触发跳转并可以抛出异常。
:与在线目录相同。它是整个 Web 应用程序的网关,必须发布。
:
这里使用 dart2js 将 dart 编写的 flutter 代码生成 js,以便于加载。你写的flutter ui风格、dart运动逻辑等都会被转换为js输出到这个文件然后上传。最后在webview中渲染渲染。所以这就是为什么一开始就说不用写css样式了,因为这里不识别。 .map:这是一个js地图文件,不需要发布。主要用于出现错误时方便定位。
之后,我们将所有文件从这里复制到我们的网络服务器。
Package & Plugin
Flutter团队一直声称Flutter For Web暂时不支持插件系统。自 - 以来,此功能已不再受支持。但这仅仅意味着不支持特定于平台的扩展调用。这并不意味着您不能使用 yaml 来配置一些纯 dart 包。因此,您仍然可以在 yaml 中部署外部包,例如fish-redux等。支持。最近dio也支持了网页版,可以直接参考使用。
如何开发
关于如何关注Flutter For Web的开发已经讲了很多。 Flutter For Web 开发与 Flutter For Mobile 开发基本相同。所有逻辑都可以用Dart来实现。您可以使用任何控件,甚至可以使用不同的模式控件。 Flutter官方这里有更详细的教程。这里不需要详细解释,可以参考官网的教程。但由于生态不完善,我们不可避免的要参考第三方或者一些特殊的网络相关逻辑,所以dart和js的交互是必要的。我们期望最好的交互方式肯定是Plugin方式,但由于不支持,所以如果需要的话,你将不得不使用代码与JS交互。
HTML
其实Flutter For Web最终是编译成html和js才能工作的,所以我们需要一些html相关的功能,比如document、ua、cookie等。Flutter有一个专门的“dart:html”库,它您可以导入并使用。
比如导航实现:
import 'dart:html'; /** * @description: 跳转某个 weburl * @param {url} */ navigation(String url){ document.window.location.href = url; }
比如cookie获取实现:
import 'dart:html'; Map _readCookie(String cookies) { var cookies = document.cookie; var cookie = Map(); (';').forEach((e) { var k = ('='); if (k < 0) { cookie[((0, k)).trim()] = ((k + 1)).trim(); } }); return cookie; }
JavaScript
Flutter For Web其实是想用一个完美的dart来进行Web应用开发,但是目前还有很多第三种- 市场上的派对网络插件,例如统计数据。等等,现在还没有dart版本,所以我们必须使用datr和js播放器来互相调用。 Flutter还提供了“dart:js”库,可以导入该库与JS交互。
JS交互中一个非常重要的概念就是上下文。我们需要让这个上下文与js交互。可以向js方法传递参数,甚至可以返回js参数等。比如下面的代码:
import 'dart:js' as js; /** * @description: 从 dart 里面 直接调用 js 方法 * @param {method} 方法名 * @param {[List args]} 可选参数 * @return: */ calljsmethod(String method,[List args]){ (method,args); } /** * @description: 从 dart 里面 直接调用 js 方法 并且传递一个 callback 过去 以便于回调 * @param {method} 方法名 * @param {callback} 回调函数 * @param {[List args]} 可选参数 * @return: */ calljswithcallback(String method,Function callback,[List args]){ (method,[(callback),args]); } /** * @description: 将 dart 方法设置成 js 方法 以供调用 * @param {functioname} 设置的函数名称 js 那边调用 * @param {callback} 设置的函数 * @return: */ setjsmethod(String functioname,Function callback){ print("setjsmethod ${functioname}"); [functioname] = callback; }
网络相关
网络请求一直是应用开发的关键功能,Flutter开发中最常用的dio插件目前最新版本已经可以支持网络了。我们可以直接使用slide来发出Web请求,也可以通过“package:http/”库发出Web请求。
doRequest(String url, Function success, {body, Function error}) { if (!isEmpty(body)) { url += "?data=${(body)}"; } print("url is $url"); (url).then((resp) { print('Response status: ${} Response body: ${}'); String bodyString = ; Map data = JsonDecoder().convert(bodyString); print('data is $data'); if ( == 200) { success(, data); } else { if (error != null) { error(, ); } else { print('error is null not callback'); } } }).catchError(( ) { print("catch some error ${ }"); if (error != null) { error(-10001, ""); } }).timeout((Duration(seconds: 15))); }
这里我没有使用Completer来实现,而是直接使用了一个比较简单的回调,也可以进行封装。
性能
性能是测量技术最重要的指标。 Flutter For Web 目前只是技术预览版。当局也承认存在性能问题。 Flutter For Web 目前是单页面应用程序。不过目前浏览器尚不支持,其渲染方式采用Canvas加原生Dom进行渲染。这实际上会导致一些性能问题,例如轻松超过 100 万,而初始加载时间太慢,就像在画布上绘图一样。可能会导致性能问题。
以如下项目为例:
该项目原本是一个 Flutter For Mobile 电商项目,原作者并没有做任何 Web 兼容。但我们可以直接在网上组装并使用。这也说明了Flutter的强大。一个代码可以在多个终端上运行。
由于这个项目页面比较复杂,并且有图片列表,所以我们用这个项目来测试Flutter的列表性能。如果你有兴趣,可以自己尝试一下。
这是PC端的信息。 PC端初始下载速度稍慢,但在可以接受的范围内。移动端很慢,延迟超过2S,但这还不是最关键的。我们测试中最关键的是基于小米9这样的旗舰手机,在滚动列表的时候,帧率只有十几,非常卡顿,导致体验非常不好,所以官方给出了后期还要优化性能。
问题
当然,最大的问题是Flutter For Web还没有发布,官方团队也没有发布计划和时机,这让Flutter For Web的未来充满了不确定性。第二是性能问题。目前的 Flutter For Web 形式存在很多性能问题,但该版本的性能比之前的版本要好得多。我们期待官方最终的优化。最后是生态问题。目前 Flutter For Web 的生态并不完善。我们希望官方能够尽快发布Release版本,然后希望社区能够完善整个生态。
后记
一个代码适用于多个终端。在 Flutter 中,我们真正看到了机会,并最终看到了伟大前端技术的曙光。
作者:王薇薇,腾讯高级工程师
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。