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的两种渲染模式
相关推荐
1024小神35 分钟前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛43 分钟前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee
AiFlutter1 小时前
Flutter通过 Coap发送组播
flutter
Y多了个想法1 小时前
RK3568 android11 适配敦泰触摸屏 FocalTech-ft5526
android·rk3568·触摸屏·tp·敦泰·focaltech·ft5526
NotesChapter3 小时前
Android吸顶效果,并有着ViewPager左右切换
android
_祝你今天愉快4 小时前
分析android :The binary version of its metadata is 1.8.0, expected version is 1.5.
android
暮志未晚Webgl4 小时前
109. UE5 GAS RPG 实现检查点的存档功能
android·java·ue5
麦田里的守望者江4 小时前
KMP 中的 expect 和 actual 声明
android·ios·kotlin
Dnelic-4 小时前
解决 Android 单元测试 No tests found for given includes:
android·junit·单元测试·问题记录·自学笔记
佛系小嘟嘟5 小时前
Android Studio不显示需要的tag日志解决办法《All logs entries are hidden by the filter》
android·ide·android studio