FlutterWeb渲染模式及提速

背景

在使用Flutter Web开发的网站过程中,常常会遇到不同浏览器之间的兼容性问题。例如,在Google浏览器中动画和交互都非常流畅,但在360浏览器中却会出现卡顿现象;在Google浏览器中动态设置图标颜色正常显示,而在Safari浏览器中颜色会缺失变成黑色;甚至在某些电脑的Google浏览器中也会出现动画卡顿和页面报错的问题。

优化方案

这些问题的根源在于渲染模式的选择。将渲染模式从HTML改为CanvasKit后,大部分问题得以解决,动画变得流畅,画面也变得顺滑,图标显示正常,兼容性也得到了提升。

渲染模式

  • HTML渲染模式 :Flutter使用HTML的custom elementCSSCanvasSVG来渲染UI元素。
  • CanvasKit渲染模式 :Flutter将Skia编译成WebAssembly格式,并使用WebGL进行渲染。
HTML CanvasKit
命令行 --web-renderer html --web-renderer canvaskit
优点 体积更小 渲染性能强,多端一致
缺点 渲染性能差,跨端兼容差 体积相较HTML多2.5M

尽管CanvasKit模式提供了更流畅的体验,但它也带来了一些新的问题。

由CanvasKit引起的问题

图片跨域

报错描述:

Access to XMLHttpRequest at 'https://.../icon/setting_228.webp' from origin 'https://...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

在CanvasKit模式下,图片请求类型变为xhr,不支持跨域,导致跨域问题。解决方法是将图片放到与服务同域的目录下。

首次打开加载慢

首次加载CanvasKit模式的网站时,会下载大量文件,包括CanvasKit绘制引擎和字体。解决方法是将引擎和字体文件存放到自己的服务器,以加快下载速度。

  1. 引擎本地化:下载引擎文件并放到项目中,然后在运行或打包时指定本地路径。

    dart 复制代码
    --dart-define=FLUTTER_WEB_CANVASKIT_URL=assets/canvaskit/
  2. 字体本地化:下载字体文件并放到本地,替换构建后的main.dart.js中的字体路径。

字体需下载

Skia自绘引擎需要字体库支持,导致首次加载时出现字体乱码。解决方法是在pubspec.yaml中设置本地字体包。

main.dart.js 切片化

以上两步只是加快了下载速度,但所需要下载的内容大小没变,好在Flutter 官方提供 deferred as 关键字来实现 Widget 的懒加载,而 dart2js 在编译过程中可以将懒加载的 Widget 进行按需打包,这样的拆包机制叫做 Lazy Loading。借助 Lazy Loading,我们可以在路由表中使用 deferred 引入各个路由(页面),以此来达到业务代码拆离的目的。具体的代码请看这篇文章《JS 分片优化》,很详细。

试验拆分后,main.dart.js由8.5M缩减至5.5M。

加载时提示

为了解决首次加载时白屏的问题,可以在白屏时加个提示。

html 复制代码
html复制
<style>
    body {
          width: 100vw;
          height: 100vh;
          display: flex;
          justify-content: center;
          align-items: center;
      }
</style>
<div id="text">静态资源加载中...</div>
浏览器刷新后页面加载两次

刷新页面时会加载两次,是由于serviceWorker注册失败导致。解决方法是注释掉注册逻辑,直接调用loadMainDartJs()

路由包装url地址方式失效

在CanvasKit模式下,刷新后不会停留在当前页面。解决方法是在刷新时记录当前页面,并在初始化时还原。

最后

尽管CanvasKit模式在动画和交互体验上优于HTML模式,但其加载速度较慢。在内部使用的网站中,可以优先考虑交互体验。

参考

  1. Flutter web内网网站如何发布?解决外网下canvaskit.js和字体无法加载问题
  2. serviceWorker 服务器与浏览器之间的代理
  3. Flutter 开启web构建以及web的两种渲染模式
相关推荐
江上清风山间明月几秒前
一周掌握Flutter开发--9. 与原生交互(下)
flutter·交互·原生·methodchannel
GeniuswongAir6 分钟前
Flutter极速接入IM聊天功能并支持鸿蒙
flutter·华为·harmonyos
sayen17 分钟前
记录 flutter 文本内容展示过长优化
前端·flutter
勤劳打代码19 分钟前
剑拔弩张——焦点竞争引的发输入失效
flutter·客户端·设计
CYRUS STUDIO1 小时前
Unidbg Trace 反 OLLVM 控制流平坦化(fla)
android·汇编·算法·网络安全·逆向·ollvm
扫地的小何尚2 小时前
NVIDIA工业设施数字孪生中的机器人模拟
android·java·c++·链表·语言模型·机器人·gpu
顾林海4 小时前
深度解析ArrayList工作原理
android·java·面试
安静的海岸_AI4 小时前
Android端WIFI/流量共存技术方案
android
_一条咸鱼_4 小时前
Android Compose 框架进度指示器深入剖析(五十二)
android
张风捷特烈4 小时前
Flutter 伪 3D 绘制#02 | 地平面与透视
android·flutter