跳到主内容

Flutter web 应用初始化

自定义 Flutter 应用在 Web 上的初始化方式。

此页面详细介绍了 Flutter web 应用的初始化过程以及如何对其进行自定义。

引导程序

#

flutter build web 命令会在构建输出目录 (build/web) 中生成一个名为 flutter_bootstrap.js 的脚本。此文件包含初始化和运行 Flutter 应用所需的 JavaScript 代码。您可以通过在 Flutter 应用的 web 子目录中的 index.html 文件中放置一个 async-script 标签来使用此脚本

html
<html>
  <body>
    <script src="flutter_bootstrap.js" async></script>
  </body>
</html>

或者,您可以通过将模板标记 {{flutter_bootstrap_js}} 插入到 index.html 文件中来内联 flutter_bootstrap.js 文件的全部内容

html
<html>
  <body>
    <script>
      {{flutter_bootstrap_js}}
    </script>
  </body>
</html>

在构建步骤期间将 index.html 文件复制到输出目录 (build/web) 时,{{flutter_bootstrap_js}} 标记将被 flutter_bootstrap.js 文件的内容替换。

自定义初始化

#

默认情况下,flutter build web 会生成一个执行 Flutter 应用简单初始化的 flutter_bootstrap.js 文件。但是,在某些情况下,您可能有理由自定义此初始化过程,例如

  • 为您的应用设置自定义 Flutter 配置。
  • 更改 Flutter 服务工作程序的设置。
  • 编写在启动过程的不同阶段运行的自定义 JavaScript 代码。

要编写自己的自定义引导逻辑,而不是使用构建步骤生成的默认脚本,您可以将 flutter_bootstrap.js 文件放在项目的 web 子目录中,该文件将被复制并代替构建步骤生成的默认脚本。此文件也经过模板处理,您可以插入几个构建步骤在将 flutter_bootstrap.js 文件复制到输出目录时会替换的特殊标记。下表列出了构建步骤将在 flutter_bootstrap.jsindex.html 文件中替换的标记

标记替换为
{{flutter_js}} 使 _flutter.loader 对象在 _flutter.loader 全局变量中可用的 JavaScript 代码。(有关更多详细信息,请参阅下面的 _flutter.loader.load() API 部分。)
{{flutter_build_config}} 一个 JavaScript 语句,用于设置构建过程生成的元数据,该元数据向 FlutterLoader 提供启动应用程序所需的信息。
{{flutter_service_worker_version}} 表示服务工作程序构建版本的唯一数字,可以将其作为服务工作程序配置的一部分传递(有关更多信息,请参阅下面的“常见警告”)。
{{flutter_bootstrap_js}} 如上所述,这将直接将 flutter_bootstrap.js 文件的内容内联到 index.html 文件中。请注意,此标记只能在 index.html 中使用,而不能在 flutter_bootstrap.js 文件本身中使用。

编写自定义引导脚本

#

任何自定义 flutter_bootstrap.js 脚本都需要三个组件才能成功启动 Flutter 应用

  • 一个 {{flutter_js}} 标记,以使 _flutter.loader 可用。
  • 一个 {{flutter_build_config}} 标记,它向 FlutterLoader 提供有关构建的信息,以便启动您的应用。
  • _flutter.loader.load() 的调用,它实际上启动了该应用。

最基本的 flutter_bootstrap.js 文件如下所示

js
{{flutter_js}}
{{flutter_build_config}}

_flutter.loader.load();

自定义 Flutter 加载器

#

_flutter.loader.load() JavaScript API 可以使用可选参数调用,以自定义初始化行为

名称描述JS 类型
config 您的应用的 Flutter 配置。 对象
onEntrypointLoaded 当引擎准备好进行初始化时调用的函数。它接收一个 engineInitializer 对象作为其唯一参数。 函数

config 参数是一个对象,可以包含以下可选字段

名称描述Dart 类型
assetBase 应用 assets 目录的基本 URL。当 Flutter 从与实际 Web 应用不同的域或子目录加载时,添加此项。当您将 Flutter web 嵌入到另一个应用中,或将其资源部署到 CDN 时,您可能需要此项。 字符串
canvasKitBaseUrl 下载 canvaskit.wasm 的基本 URL。 字符串
canvasKitVariant 要下载的 CanvasKit 变体。您的选项包括

1. auto:下载对浏览器而言最佳的变体。此选项默认为此值。
2. full:下载可在所有浏览器中使用的 CanvasKit 的完整变体。
3. chromium:下载使用 Chromium 兼容 API 的 CanvasKit 的较小变体。警告:除非您计划仅使用基于 Chromium 的浏览器,否则不要使用 chromium 选项。
字符串
canvasKitForceCpuOnly 当设置为 true 时,强制 CanvasKit 中的 CPU 仅渲染(引擎不会使用 WebGL)。 布尔值
canvasKitMaximumSurfaces CanvasKit 渲染器可以使用的最大重叠曲面数。 双精度浮点数
debugShowSemanticNodes 如果为 true,Flutter 会在屏幕上可见地渲染语义树(用于调试)。 布尔值
entrypointBaseUrl Flutter 应用的入口点的基本 URL。默认为“/”。 字符串
hostElement Flutter 渲染应用的 HTML 元素。如果未设置,Flutter web 将接管整个页面。 HtmlElement
renderer 指定当前 Flutter 应用的 Web 渲染器,可以是 "canvaskit""skwasm" 字符串
forceSingleThreadedSkwasm 强制 Skia WASM 渲染器以单线程模式运行,以实现兼容性。 布尔值

forceSingleThreadedSkwasm

#

一个布尔标志,用于强制 Skia WebAssembly (skwasm) 渲染器以 单线程模式 运行。如果

  • 您的环境不支持多线程 WASM(例如,SharedArrayBuffer 不可用或缺少必需的安全标头)。
  • 您希望获得最大的浏览器兼容性。
  • 使用 false(默认值)允许在支持时进行多线程渲染,从而提高性能。

示例用法

#
js
_flutter.loader.load({
  config: {
    renderer: 'skwasm',
    forceSingleThreadedSkwasm: true,
  },
});

示例:基于 URL 查询参数自定义 Flutter 配置

#

以下示例显示了一个自定义 flutter_bootstrap.js,它允许用户通过在网站的 URL 中提供 renderer 查询参数(例如 ?renderer=skwasm)来选择渲染器

js
{{flutter_js}}
{{flutter_build_config}}

const searchParams = new URLSearchParams(window.location.search);
const renderer = searchParams.get('renderer');
const userConfig = renderer ? {'renderer': renderer} : {};
_flutter.loader.load({
  config: userConfig,
});

此脚本评估页面的 URLSearchParams,以确定用户是否传递了 renderer 查询参数,然后更改 Flutter 应用的用户配置。

onEntrypointLoaded 回调

#

您还可以将 onEntrypointLoaded 回调传递到 load API,以便在初始化过程的不同阶段执行自定义逻辑。初始化过程分为以下阶段

加载入口点脚本

load 函数在初始化服务工作程序并由浏览器下载和运行 main.dart.js 入口点后调用 onEntrypointLoaded 回调。Flutter 还在开发期间的每次热重启时调用 onEntrypointLoaded

初始化 Flutter 引擎

onEntrypointLoaded 回调接收一个 引擎初始化器 对象作为其唯一参数。使用引擎初始化器的 initializeEngine() 函数设置运行时配置,例如 multiViewEnabled: true,并启动 Flutter web 引擎。

运行应用

initializeEngine() 函数返回一个 Promise,该 Promise 会解析为 应用运行器 对象。应用运行器具有一个名为 runApp() 的方法,该方法运行 Flutter 应用。

将视图添加到(或从)应用中

runApp() 方法返回一个 flutter 应用 对象。在多视图模式下,可以使用 addViewremoveView 方法从宿主应用管理应用视图。要了解更多信息,请查看 嵌入模式

示例:显示进度指示器

#

为了向您的应用的最终用户提供初始化过程中的反馈,请使用提供的钩子来更新 DOM

js
{{flutter_js}}
{{flutter_build_config}}

const loading = document.createElement('div');
document.body.appendChild(loading);
loading.textContent = "Loading Entrypoint...";
_flutter.loader.load({
  onEntrypointLoaded: async function(engineInitializer) {
    loading.textContent = "Initializing engine...";
    const appRunner = await engineInitializer.initializeEngine();

    loading.textContent = "Running app...";
    await appRunner.runApp();
  }
});

常见警告

#

如果您遇到类似以下内容的警告

Warning: In index.html:37: Local variable for "serviceWorkerVersion" is deprecated.
Use "" template token instead.

您可以通过删除 web/index.html 文件中的以下行来修复此问题

web/index.html
html
var serviceWorkerVersion = null;