深度解析 | Flutter web 支持的最新进展

2020 年 8 月 7 日 谷歌开发者
作者 / Mariam Hasnany, Product Manager, Flutter


我们将通过这篇文章深入分享将 Flutter 引入 web 平台的最新进展,重点介绍我们为与 web 平台进行深度、原生集成所做的努力。

我们对 Flutter 的愿景是提供一个可移植的工具包,让您可以在任何屏幕上尽情绘制像素,打造美好的体验。正如我们不久前和大家分享的一样,我们在框架和 API 的选择上将应用置于中心位置,构建出了一个可以跨移动、桌面和嵌入式设备的分层架构,且不影响性能和品质。


Web 正是这项工作的核心。Flutter 的诞生离不开 Chrome 团队的不懈探索。它的灵感源自 web 的生产力和迭代开发模型,我们的许多工程师在构建浏览器引擎和网络标准方面都有多年的经验。我们之所以将网络浏览器作为目标,是因为它是互联网的 "心脏": 计算机历史上最普遍、最灵活、最广泛的应用模型。


多年以来,web 平台和 HTML DOM 在本质上相差无几。然而最近,随着 web 平台不断扩展,API 和功能越来越丰富,使得开发者得以接触到底层操作系统和硬件。从硬件加速的图形绘制Shell 集成PWA,从 Service Worker 到新的布局和绘制 API,对于复杂的应用甚至是在此基础之上布局的框架而言,web 都是一个越来越强大的目标平台。


  • 硬件加速的图形绘制
    https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API
  • Shell 集成
    https://w3c.github.io/manifest/
  • PWA
    https://web.dev/progressive-web-apps/
  • Service Worker
    https://developers.google.cn/web/fundamentals/primers/service-workers
  • 布局和绘制 API
    https://developer.mozilla.org/en-US/docs/Web/Houdini

Flutter 对 web 的支持不仅仅是对 DOM 的转译: 它充分利用这些全新的 API 集,既提供真正的 web 体验,又完整保留了 Flutter 的特色。


在这篇文章中,我们将详细介绍具体的实现过程,分享 Flutter 如何使用 web 来实现丰富的交互式体验,而无需重写现有 Flutter 代码。我们还会介绍无障碍功能和后端编译选择等内容,虽然初上手尝试 Flutter 的开发者们可能一时还用不到这些功能。



不只是 canvas 绘制


将 Flutter widget 绘制为 web 上的像素实际上意味着什么?

我们先来回顾一下 Flutter 的 web 架构。Flutter 是一个 多层系统 ,包含:
  • 用于为 widget、动画和手势等常见的习惯用法提供抽象的框架
  • 使用公开的系统 API 在目标设备上进行渲染的引擎

  • Flutter 的分层模型
    https://flutter.cn/docs/resources/technical-overview#layer-cakes-are-delicious

框架代码是用 Dart 编写的。我们将其与您自己的代码相结合,并在编译时应用摇树优化 (tree-shaking) 算法,以便只将您的应用使用到的代码下载到浏览器中。Flutter 采用响应式模型,根据状态变化渲染用户界面。Flutter 在每帧内构建 widget,执行布局,然后使用底层浏览器 API 绘制界面变化。


  • 使用摇树优化算法和延迟加载优化 Flutter web 应用性能
    https://medium.com/flutter/optimizing-performance-in-flutter-web-apps-with-tree-shaking-and-deferred-loading-535fbe3cd674

△ Flutter 的 web 架构是多层系统,框架位于浏览器引擎之上

默认情况下,web 模式使用标准的 HTML DOM 和 Canvas 技术。在这种模式下,引擎将每个生成的 Flutter 场景转换为 HTML、CSS 或 Canvas,并以 HTML 元素树的形式将帧渲染到页面上。


我们将这种方法称为 DomCanvas 后端。它以简洁的代码为我们提供了跨浏览器的最大兼容性,非常适合会话短暂、需要快速启动的应用。


尽管我们在 DomCanvas 的性能和保真度方面持续取得良好进展,但我们还在并行开发基于 CanvasKit 的后端,该后端使用 WebAssemblyWebGL 在浏览器中渲染 Skia 绘制命令。我们之所以开始尝试使用 CanvasKit,是因为 Skia 与 Flutter 移动和桌面端使用的图形引擎相同,而且不同于 HTML DOM 的是,它可以直接访问底层图形堆栈,从而实现与原生 Flutter 完全对等的性能。


  • CanvasKit
    https://skia.org/user/modules/canvaskit
  • WebAssembly
    https://webassembly.org/
  • WebGL
    https://www.khronos.org/webgl/


尽管 DomCanvas 的浏览器支持更广泛、代码更少、初始页面加载速度更快,但 CanvasKit 允许 Flutter 开发者采用新技术来构建图形密集型 web 应用。将来,其中一种方法的优势可能会变得势不可挡,但就目前而言,Flutter 可以让您选择最适合您所需用例的后端


  • 选择合适的渲染方案
    https://github.com/flutter/flutter/wiki/Experimental-flags-for-web-support#canvaskit-backend



在浏览器中提供原生的体验


要让 web 应用在浏览器中提供原生的体验,它必须支持各种浏览器中的惯用操作,包括原生的文本交互和滚动行为、后退/前进导航以及无障碍功能,所有这些都要在各种各样的设备和环境中拥有良好的性能。


文本渲染

构建 Flutter 的 web 支持时,我们面临的最大挑战之一就是开发一种专门用于文本布局的布局系统。为了对文本段落进行布局,Flutter 会创建一个 paragraph 对象并调用其 layout() 方法。由于 web 目前缺少直接的文本布局 API,因此我们通过触发 layout() 并观测框架中其他元素布局属性值的变化,来实现通过 DOM 对文本段落进行各种测量的目的。


  • Paragraph
    https://api.flutter.cn/flutter/dart-ui/Paragraph-class.html
  • layout() 方法
    https://api.flutter.cn/flutter/dart-ui/Paragraph/layout.html

可以想象,这些测量的成本开销十分之大,因此我们最近开始尝试使用 canvas API 来测量文本以改进两种后端方法。我们发现这些 API 可以将文本布局性能提高多达 6 倍,并且还解决了多行文本和文本溢出的一些问题。您可以使用发布 (Release) 模式选项来启用这些 canvas 文本改进。(截至 2020 年 7 月 30 日更新: master 渠道中的 canvas 文本测量功能已经默认启用,并将逐步推广至其他渠道。)


  • 使用 canvas 测量文本
    https://github.com/flutter/flutter/issues/33523
  • Web 支持中的实验性选项: 文本渲染性能改进
    https://github.com/flutter/flutter/wiki/Experimental-flags-for-web-support#text-rendering-performance-improvements


对于终端用户体验而言,快速、正确地渲染文本很重要,而能够在浏览器中与文本进行交互同样关键。现在,您可以通过使用 SelectableTextEditableText widget 在 Flutter web 应用里实现文本选择操作。不久之后,您还可以实现复制/粘贴文本、文本字段焦点处理、表单编辑等更好的文本编辑交互。

滚动

有两种方式可以使 Flutter web 应用更加自然: 滚动的性能和直观性。

无论是移动应用还是 web 应用,滚动性能都可以衡量一款应用是否存在 "卡顿" 问题。对于我们的渲染系统来说,滚动针对我们加载内容的方式和时机定义了一种特定的使用模式。过去一个季度我们把重点放在提高滚动性能上,通过 优化静态内容滚动 和添加 性能基准 ,来确保我们在未来不会遭遇性能回退。


  • 优化静态内容滚动
    https://github.com/flutter/engine/pull/17621
  • 性能基准
    https://docs.google.com/spreadsheets/d/10AXb-4ulJipM6ZtiieFEBXhmybB6-_gTV6HDQlgcQdA/edit#gid=2047450737


由于 Flutter 框架最初是为原生移动应用设计的,因此 Flutter 网络应用已经对移动浏览器的手势和滚动物理效果提供了很好的支持。桌面浏览器的滚动行为支持取决于我们在框架级别为 Flutter 桌面端所做的工作。到目前为止,我们已经能够使用鼠标和其他鼠标/滚轮事件来处理拖拽滚动,但键盘滚动支持依然有待添加。


导航

与原生应用不同,web 应用在浏览器中自带后退按钮。现在,浏览器后退按钮的行为与 Flutter 应用中的 Navigator.pop() 都相差无几。这意味着,当用户在浏览器中打开指向 Flutter web 应用的链接时,框架会将初始路径拆分成几个部分,并逐一加入导航堆栈中。


以 Flutter 目前的导航为例,您可以尝试从 google.com 跳转到 gallery.flutter.dev/#/demo/banner,然后点击浏览器的后退按钮。

△ 现在,浏览器的后退按钮会尝试匹配 Flutter 应用的后退按钮路由历史记录

您会发现,它不会按照预期带您回到 google.com,而是先返回网站的首页: gallery.flutter.dev。Flutter 会拆分初始 Gallery 应用的路径,将 gallery.flutter.dev 和 /demo/banner 页面都 push 进导航路径堆栈中,因此当浏览器后退按钮触发 Navigator.pop() 时,它会返回到 gallery.flutter.dev,因为应用内部的历史记录就是这样设置的。


我们一直在努力通过 Navigator 2.0 和新的 Router widget 改善 Flutter 在所有平台上的导航/路由功能。这不仅会使导航更具声明性和灵活性,还会改善路由历史记录在 Flutter web 应用中的作用方式。


  • Navigator 2.0

    http://flutter.dev/go/navigator-with-router

  • Router widget

    http://flutter.dev/go/router-and-widgetsapp-integration



实现无障碍功能


就设计而言,Flutter 通过构建独立于 RenderObject 树的 SemanticsNode 树来实现无障碍功能。Flutter 的无障碍功能系统目前是选择加入的,这意味着最终用户必须选择是否启用辅助技术。启用后,通过扫描渲染树以及合并表示屏幕上单个逻辑交互元素的语义节点来生成 SemanticsNode 树。


为了在 web 上实现此操作,我们又生成一个 DOM 树,它与作为 RenderObject 树的 DOM 树平行,并将标记、操作、标签和其他语义属性转换成 ARIA (Accessible Rich Internet Applications)。


每个 Flutter web 应用都可以实现无障碍功能。例如,当您启用屏幕阅读器辅助技术 (如适用于 iOS 和 macOS 的 VoiceOver),Flutter Gallery 应用就能提供无障碍体验。在按照屏幕阅读器的说明明确启用应用的无障碍功能后,您会看到应用生成了一个语义树。


  • 无障碍功能
    https://flutter.cn/docs/development/accessibility-and-localization/accessibility
  • VoiceOver
    https://www.apple.com/accessibility/mac/vision/
  • Flutter Gallery 应用
    https://gallery.flutter.cn/

△ 每个 Flutter web 应用都会向 VoiceOver 等无障碍工具公开一个语义树

Flutter web 的语义功能已经可以媲美当前 Flutter 语义系统的功能,但是我们需要添加自动化测试来确保不会出现回退。我们还需要支持一些复杂的功能,比如表格以及元素关系


  • 表格
    https://github.com/flutter/flutter/issues/45205
  • 元素关系
    https://developers.google.cn/web/fundamentals/accessibility/semantics-aria/aria-labels-and-relationships



Rive: Flutter web 的典型示例


Rive 是一款典型的富交互应用,它展示了 Flutter 对 web 的支持能力。Rive 目前发布了其重新编写的设计协作工具,该工具完全用 Flutter 构建。


Rive 是一个动画设计应用,帮助设计师和开发者创建高质量且可以轻松集成到任何平台的动画素材。为了同时提供流畅的实时界面和动画,Rive 需要在现代浏览器和其他平台上进行大量的图形渲染以及确保高性能的体验。


Rive 2 beta 版完全使用 Flutter 重写,因此也得以用同一个代码库提供 web 和桌面版本。其 web 版使用 CanvasKit 后端和 Skia 在两个平台上提供一致的体验。敬请关注 Rive 即将发布的技术博客文章,了解他们如何使用 Flutter 重建工具。目前,您可以注册试用其 beta 版 web 应用,名额有限,赶快行动吧。


  • Rive 2 beta
    https://blog.rive.app/announcing-rive-2/
  • 了解 Rive 2
    https://www.bilibili.com/video/BV1vp4y1q7cs/
  • 注册体验
    https://beta.rive.app/



总结


希望这篇文章能让您深入了解我们是如何充分利用 web 平台的特性来打造 Flutter 的。就在几年前,Flutter web 在质量和性能上还谈不上差强人意,但是随着新的 web 技术的引入和平台的不断进步,我们终于能够更好地利用底层设备的潜力。我们将紧跟 web 平台的发展脚步不断前进,继续朝着稳定版本的方向努力,不断改进对文本交互、滚动、导航和无障碍功能的支持。


想要构建 Flutter web 应用?从入门指南开始试试吧。如果您已着手构建了一些应用,欢迎通过 CodePen 或网址和我们分享您的作品!


  • 使用 Flutter 构建 web 应用
    https://flutter.cn/docs/get-started/web
  • CodePen
    https://codepen.io/pen/editor/flutter


推荐阅读






  点击屏末  | 访问 Flutter 开发者社区中文资源



登录查看更多
1

相关内容

HTML DOM是HTML Document Object Model(文档对象模型)的缩写,HTML DOM则是专门适用于HTML/XHTML的文档对象模型。熟悉软件开发的人员可以将HTML DOM理解为网页的API。它将网页中的各个元素都看作一个个对象,从而使网页中的元素也可以被计算机语言获取或者编辑。 例如Javascript就可以利用HTML DOM动态地修改网页。
最新《知识图谱:构建到应用》2020大综述论文,261页pdf
专知会员服务
282+阅读 · 2020年10月6日
专知会员服务
79+阅读 · 2020年9月28日
【2020新书】使用Kubernetes开发高级平台,519页pdf
专知会员服务
66+阅读 · 2020年9月19日
最新《深度多模态数据分析》综述论文,26页pdf
专知会员服务
295+阅读 · 2020年6月16日
【干货书】现代数据平台架构,636页pdf
专知会员服务
250+阅读 · 2020年6月15日
【电子书】Flutter实战305页PDF免费下载
专知会员服务
20+阅读 · 2019年11月7日
知识图谱本体结构构建论文合集
专知会员服务
102+阅读 · 2019年10月9日
使用ONNX+TensorRT部署人脸检测和关键点250fps
极市平台
34+阅读 · 2019年10月22日
微信小程序官方发布支持Python的自动化测试框架
Python程序员
8+阅读 · 2019年9月4日
重磅!Flutter 2019年最新进展和未来展望
前端之巅
4+阅读 · 2019年6月20日
美团:基于跨平台框架Flutter的动态化平台建设
前端之巅
14+阅读 · 2019年6月17日
硬核实践经验 - 企鹅辅导 RN 迁移及优化总结
IMWeb前端社区
5+阅读 · 2019年5月6日
从webview到flutter:详解iOS中的Web开发
前端之巅
5+阅读 · 2019年3月24日
软件推荐 | Flutter 开发的精美时间轴应用
开源中国
6+阅读 · 2019年1月4日
Arxiv
7+阅读 · 2020年9月17日
Learning to See Through Obstructions
Arxiv
7+阅读 · 2020年4月2日
Arxiv
7+阅读 · 2018年12月10日
Meta-Transfer Learning for Few-Shot Learning
Arxiv
7+阅读 · 2018年12月6日
Arxiv
135+阅读 · 2018年10月8日
Arxiv
7+阅读 · 2018年9月27日
Arxiv
3+阅读 · 2018年6月19日
VIP会员
相关VIP内容
最新《知识图谱:构建到应用》2020大综述论文,261页pdf
专知会员服务
282+阅读 · 2020年10月6日
专知会员服务
79+阅读 · 2020年9月28日
【2020新书】使用Kubernetes开发高级平台,519页pdf
专知会员服务
66+阅读 · 2020年9月19日
最新《深度多模态数据分析》综述论文,26页pdf
专知会员服务
295+阅读 · 2020年6月16日
【干货书】现代数据平台架构,636页pdf
专知会员服务
250+阅读 · 2020年6月15日
【电子书】Flutter实战305页PDF免费下载
专知会员服务
20+阅读 · 2019年11月7日
知识图谱本体结构构建论文合集
专知会员服务
102+阅读 · 2019年10月9日
相关资讯
使用ONNX+TensorRT部署人脸检测和关键点250fps
极市平台
34+阅读 · 2019年10月22日
微信小程序官方发布支持Python的自动化测试框架
Python程序员
8+阅读 · 2019年9月4日
重磅!Flutter 2019年最新进展和未来展望
前端之巅
4+阅读 · 2019年6月20日
美团:基于跨平台框架Flutter的动态化平台建设
前端之巅
14+阅读 · 2019年6月17日
硬核实践经验 - 企鹅辅导 RN 迁移及优化总结
IMWeb前端社区
5+阅读 · 2019年5月6日
从webview到flutter:详解iOS中的Web开发
前端之巅
5+阅读 · 2019年3月24日
软件推荐 | Flutter 开发的精美时间轴应用
开源中国
6+阅读 · 2019年1月4日
相关论文
Arxiv
7+阅读 · 2020年9月17日
Learning to See Through Obstructions
Arxiv
7+阅读 · 2020年4月2日
Arxiv
7+阅读 · 2018年12月10日
Meta-Transfer Learning for Few-Shot Learning
Arxiv
7+阅读 · 2018年12月6日
Arxiv
135+阅读 · 2018年10月8日
Arxiv
7+阅读 · 2018年9月27日
Arxiv
3+阅读 · 2018年6月19日
Top
微信扫码咨询专知VIP会员