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的两种渲染模式
相关推荐
赏金术士8 小时前
Kotlin ViewModel
android·kotlin
vistaup9 小时前
kotlin 二维码实现高斯模糊
android·kotlin
愈努力俞幸运10 小时前
function calling与mcp
android·数据库·redis
阿巴斯甜11 小时前
LeakCanary
android
阿巴斯甜11 小时前
compose
android
阿巴斯甜11 小时前
Glide
android
-SOLO-11 小时前
使用Perfetto debug trace查看超时slice
android
阿巴斯甜11 小时前
Retrofit
android
阿巴斯甜11 小时前
OkHttp
android
阿巴斯甜12 小时前
Flow
android