支持 WebAssembly (Wasm)

上次更新时间:2024 年 3 月 13 日

Flutter 和 Dart 团队很高兴在为 Web 构建应用程序时添加 WebAssembly 作为编译目标。

Dart 和 Flutter 的 WebAssembly 支持开发仍在进行中,这可能会导致频繁的更改。请访问此页面以获取最新更新。

背景

要运行已编译为 Wasm 的 Flutter 应用,您需要一个支持 WasmGC 的浏览器。Wasm 标准计划添加 WasmGC,以帮助像 Dart 这样的垃圾回收语言以高效的方式执行代码。

Chromium 和 V8 在 Chromium 119 中发布了对 WasmGC 的稳定支持。请注意,iOS 上的 Chrome 使用 WebKit,它尚未 支持 WasmGC。Firefox 宣布在 Firefox 120 中稳定支持 WasmGC,但目前由于 已知限制 而无法正常工作。

试用

要试用使用 Wasm 的预构建 Flutter Web 应用,请查看 Material 3 WasmGC 预览演示

要在自己的应用中体验 Wasm,请执行以下步骤。

切换到 Flutter beta 频道并升级

Wasm 编译可在 beta 频道(首选)或 main 的最新版本上使用。

如需详细了解 Flutter 版本发布频道以及如何切换到 beta 频道,请查看 Flutter wiki

然后,为确保您运行的是最新版本,请运行 flutter upgrade

要验证您的 Flutter 安装是否支持 Wasm,请运行 flutter build web --help

在输出的底部,您应该会找到实验性 Wasm 选项,例如

Experimental options
    --wasm                       Compile to WebAssembly rather than JavaScript.
                                 See https://fluttercn.cn/wasm for more information.
    --[no-]strip-wasm            Whether to strip the resulting wasm file of static symbol names.
                                 (defaults to on)

选择一个(简单的)Flutter Web 应用程序

尝试默认模板 示例应用,或选择任何已迁移为 兼容 Wasm 的 Flutter 应用程序。

修改 index.html

在使用 Wasm 构建之前,您需要修改应用的 web/index.html 文件中的引导逻辑。

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="UTF-8">
  <title>Flutter web app</title>
  <script src="flutter.js"></script>
</head>
<body>
  <script>
    {{flutter_build_config}}
    _flutter.loader.load();
  </script>
</body>
</html>

此功能正在开发中。当前语法 (flutter.js{{flutter_build_config}}_flutter.loader.load()) 是 betamain 频道中的临时解决方案,但将在即将发布的稳定版本中替换为实际语法。敬请期待!

运行 flutter build web --wasm

要使用 Wasm 构建 Web 应用程序,请将 --wasm 标志添加到现有的 flutter build web 命令中。

flutter build web --wasm

该命令会将输出发送到相对于包根目录的 build/web 目录。

使用 HTTP 服务器在本地提供输出

如果您尚未安装本地 HTTP 服务器,可以使用 dhttpd 软件包

flutter pub global activate dhttpd

然后切换到 build/web 目录并使用特殊标头运行服务器

$ cd build/web
$ dhttpd '--headers=Cross-Origin-Embedder-Policy=credentialless;Cross-Origin-Opener-Policy=same-origin'
Server started on port 8080

在浏览器中加载

截至 2024 年 3 月 13 日,只有基于 Chromium 的浏览器(版本 119 或更高版本)才能运行 Flutter/Wasm 内容。

如果已配置的浏览器符合要求,请在浏览器中打开 localhost:8080 以查看应用。

如果应用程序未加载

  1. 查看开发者控制台中的错误。
  2. 使用典型的 JavaScript 输出验证成功构建。

已知限制

Wasm 支持目前存在一些限制。以下列表涵盖了一些常见问题。

Chrome 119 或更高版本

在浏览器中加载中所述,要运行已编译为 Wasm 的 Flutter Web 应用,请使用Chrome 119 或更高版本

一些早期版本支持启用特定标志的 WasmGC,但一旦该功能稳定,WasmGC 编码就会发生变化。为了确保兼容性,请运行最新版本的 Flutter main 频道和最新版本的 Chrome。

  • 为什么不用 Firefox?Firefox 版本 120 及更高版本以前能够运行 Flutter/Wasm,但它们目前遇到一个错误,阻止了与 Wasm 的兼容性。
  • 为什么不用 Safari?Safari 还不支持 WasmGC;此错误跟踪了他们的实现工作。

需要 JS 互操作才能访问浏览器和 JS API

为了支持编译为 Wasm,Dart 已改变它启用与浏览器和 JavaScript API 的互操作的方式。这种改变阻止了使用 dart:htmlpackage:js 的 Dart 代码编译为 Wasm。

相反,Dart 现在提供了围绕静态 JS 互操作构建的新型轻量级互操作解决方案

Dart 和 Flutter 团队拥有的大多数软件包已迁移为与 Flutter 中的 Wasm 支持兼容,例如 package:url_launcher。要了解如何将软件包和应用程序迁移到新解决方案,请查看 JS 互操作文档和 package:web 迁移指南

要检查 Wasm 构建是否因 API 不兼容而失败,请查看错误输出。这些错误通常在构建调用后立即返回。与 API 相关的错误应类似于以下内容

Target dart2wasm failed: Exception: ../../../../.pub-cache/hosted/pub.dev/url_launcher_web-2.0.16/lib/url_launcher_web.dart:6:8: Error: Dart library 'dart:html' is not available on this platform.
import 'dart:html' as html;
       ^
Context: The unavailable library 'dart:html' is imported through these packages:

    web_plugin_registrant.dart => package:url_launcher_web => dart:html
    web_plugin_registrant.dart => package:url_launcher_web => package:flutter_web_plugins => dart:html
    web_plugin_registrant.dart => package:flutter_web_plugins => dart:html

仅构建支持

目前,flutter runDevTools 均不支持 Wasm。

了解更多信息

查看 Flutter 的 现有 Web 支持。Flutter 和 Dart Wasm 支持的工作仍在继续。完成后,现有的 Flutter Web 应用程序无需太多工作即可支持 Wasm。

如果您想了解更多信息,请观看我们团队在 Wasm I/O 2023 上的演讲:Flutter、Dart 和 WasmGC:Web 应用程序的新模型

要关注 Flutter 和 Dart WebAssembly 工作的最新变化,请重新访问 flutter.dev/wasm