Web 渲染器
Flutter Web 提供了两种 构建模式 和两种 渲染器。构建模式是在构建应用时选择的,它决定了应用中可用的两种渲染器之一,以及如何选择渲染器。在应用启动时,渲染器会在运行时 (runtime) 被选择,这决定了用于渲染 UI 的 Web 技术。
两种构建模式是:默认模式和 WebAssembly 模式。
两种渲染器是:canvaskit
和 skwasm
。
渲染器
#在 Flutter 中渲染 UI 从框架中的 Widget 和 RenderObject 开始。一旦处理完成,RenderObject 会生成一个由多个 Layer 组成的 Scene
对象。随后,该 Scene 被传递给 Flutter 引擎,将其转换为像素。整个框架,包括所有的 widget 和自定义的应用代码,以及大部分引擎,都是用 Dart 编写的。然而,引擎中有很大一部分是用 C++ 编写的,其中包括 Skia 以及定制的 Flutter 引擎代码。关于如何编译 Dart 和 C++、使用哪种图形系统将 UI 转换为像素、如何在多个线程间分配工作负载等问题,
Web 上有多种可供选择的方案。
Flutter Web 并不提供所有可用的方案,而是仅提供了两种精心挑选的方案。
canvaskit
#使用 canvaskit
渲染器时,Dart 代码会被编译为 JavaScript,并且 UI 会在主线程中渲染到 WebGL 上。它兼容所有现代浏览器。该渲染器包含一个编译成 WebAssembly 的 Skia 副本,这会增加大约 1.5MB 的下载大小。
skwasm
#使用 skwasm
渲染器时,Dart 代码会被编译为 WebAssembly。此外,如果托管服务器满足 SharedArrayBuffer 安全要求,
Flutter 会使用一个专用的 web worker 将部分渲染工作转移到单独的线程上,以利用多核 CPU 的优势。该渲染器包含一个编译为 WebAssembly 的更精简的 Skia,增加大约 1.1MB 的下载大小。
构建模式
#默认构建模式
#使用 flutter run
和 flutter build web
命令时,如果不传递 --wasm
或传递 --no-wasm
,则会使用默认模式。此构建模式仅使用 canvaskit
渲染器。
WebAssembly 构建模式
#此模式通过在 flutter run
和 flutter build web
命令中传递 --wasm
标志启用。
在此模式下,skwasm
和 canvaskit
都可以使用。
skwasm
依赖 wasm 垃圾回收机制,而这一功能尚未被所有现代浏览器支持。因此,在运行时 (runtime),如果浏览器支持垃圾回收,Flutter 将选用 skwasm
,如果不支持,则会回退到 canvaskit
。这确保了在 WebAssembly 模式下编译的应用程序仍然能够在所有现代浏览器中运行。
--wasm
标志不适用于非 Web 平台。
在运行时 (runtime) 选择渲染器
#默认情况下,在 WebAssembly 模式下构建时,Flutter 会自动决定何时使用 skwasm
,以及何时回退到 canvaskit
。你可以通过传递配置对象给加载器来覆盖这一行为,具体步骤如下:
-
使用
--wasm
标志构建应用程序,以使应用能够使用skwasm
和canvaskit
渲染器。 -
按照 编写自定义
flutter_bootstrap.js
中的描述设置自定义 Web 应用初始化。 -
准备一个配置对象,将其
renderer
属性设置为"canvaskit"
或"skwasm"
。 -
将准备好的 config 对象作为新对象的
config
属性,传递给之前注入代码提供的_flutter.loader.load
方法。
示例:
<body>
<script>
{{flutter_js}}
{{flutter_build_config}}
// TODO: Replace this with your own code to determine which renderer to use.
const useCanvasKit = true;
const config = {
renderer: useCanvasKit ? "canvaskit" : "skwasm",
};
_flutter.loader.load({
config: config,
});
</script>
</body>
在调用 load
方法后,Web 渲染器就无法再次更改。因此,必须在调用 _flutter.loader.load
之前决定使用哪种渲染器。
如何选择合适的构建模式
#将 Dart 编译为 WebAssembly 伴随着一些新的要求,所有应用代码以及应用使用的插件和 package 都必须满足这些要求:
-
代码必须只使用新的 JS 互操作库
dart:js_interop
。旧的dart:js
、dart:js_util
和package:js
已不再支持。 -
使用 Web API 的代码必须使用新的
package:web
而不是dart:html
。 -
WebAssembly 实现了 Dart 的数值类型
int
和double
,其行为与 Dart VM 完全一致。在 JavaScript 中,这些类型是使用 JS 的Number
类型进行模拟的。你的代码可能无意或故意依赖于 JS 中的数值行为。如果是这样,这部分代码需要更新,以确保与 Dart VM 的行为一致。
总体建议可以总结如下:
-
如果你的应用依赖于尚未支持 WebAssembly 的插件和 package,那就选择默认模式。
-
如果你的应用代码和 package 与 WebAssembly 兼容,并且应用性能非常重要,那就选择 WebAssembly 模式。
skwasm
相较于canvaskit
在应用启动时间和帧性能方面有明显优势。skwasm
性能优势在多线程模式下尤为显著,因此请考虑配置服务器以满足 SharedArrayBuffer 安全要求。
示例
#在 Chrome 浏览器中使用默认构建模式运行:
flutter run -d chrome
使用默认构建模式构建你的应用以进行发布:
flutter build web
使用 WebAssembly 模式构建你的应用以进行发布:
flutter build web --wasm
使用默认构建模式运行你的应用以进行性能分析:
flutter run -d chrome --profile
除非另有说明,本文档之所提及适用于 Flutter 的最新稳定版本,本页面最后更新时间: 2024-10-15。 查看文档源码 或者 为本页面内容提出建议。