Flutter web 应用初始化
自定义 Flutter 应用在 Web 上的初始化方式。
此页面详细介绍了 Flutter web 应用的初始化过程以及如何对其进行自定义。
引导程序
#flutter build web 命令会在构建输出目录 (build/web) 中生成一个名为 flutter_bootstrap.js 的脚本。此文件包含初始化和运行 Flutter 应用所需的 JavaScript 代码。您可以通过在 Flutter 应用的 web 子目录中的 index.html 文件中放置一个 async-script 标签来使用此脚本
<html>
<body>
<script src="flutter_bootstrap.js" async></script>
</body>
</html>
或者,您可以通过将模板标记 {{flutter_bootstrap_js}} 插入到 index.html 文件中来内联 flutter_bootstrap.js 文件的全部内容
<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.js 或 index.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 文件如下所示
{{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(默认值)允许在支持时进行多线程渲染,从而提高性能。
示例用法
#_flutter.loader.load({
config: {
renderer: 'skwasm',
forceSingleThreadedSkwasm: true,
},
});
示例:基于 URL 查询参数自定义 Flutter 配置
#以下示例显示了一个自定义 flutter_bootstrap.js,它允许用户通过在网站的 URL 中提供 renderer 查询参数(例如 ?renderer=skwasm)来选择渲染器
{{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 应用 对象。在多视图模式下,可以使用addView和removeView方法从宿主应用管理应用视图。要了解更多信息,请查看 嵌入模式。
示例:显示进度指示器
#为了向您的应用的最终用户提供初始化过程中的反馈,请使用提供的钩子来更新 DOM
{{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 文件中的以下行来修复此问题
var serviceWorkerVersion = null;