自定义 Web 应用程序初始化

您可以使用 flutter.js 提供的 _flutter.loader JavaScript API,自定义 Flutter 应用程序在 Web 上的初始化方式。此 API 可用于在 CSS 中显示加载指示器、根据条件阻止应用程序加载,或在显示应用程序之前等待用户按下按钮。

初始化过程分为以下阶段

加载入口点脚本
获取 main.dart.js 脚本并初始化服务工作者。
初始化 Flutter 引擎
通过下载必需的资源(例如资产、字体和 CanvasKit)来初始化 Flutter 的 Web 引擎。
运行应用程序
为您的 Flutter 应用程序准备 DOM 并运行它。

此页面展示了如何在初始化过程的每个阶段自定义行为。

开始

默认情况下,flutter create 命令生成的 index.html 文件包含一个脚本标记,该标记从 flutter.js 文件中调用 loadEntrypoint

<html>
  <head>
    <!-- ... -->
    <script src="flutter.js" defer></script>
  </head>
  <body>
    <script>
      window.addEventListener('load', function (ev) {
        // Download main.dart.js
        _flutter.loader.loadEntrypoint({
          serviceWorker: {
            serviceWorkerVersion: serviceWorkerVersion,
          },
          onEntrypointLoaded: async function(engineInitializer) {
            // Initialize the Flutter engine
            let appRunner = await engineInitializer.initializeEngine();
            // Run the app
            await appRunner.runApp();
          }
        });
      });
    </script>
  </body>
</html>

当 Service Worker 初始化,并且浏览器已下载并运行 main.dart.js 入口点后,loadEntrypoint 函数会调用 onEntrypointLoaded 回调。在开发过程中,Flutter 还会在每次热重启时调用 onEntrypointLoaded

onEntrypointLoaded 回调接收一个引擎初始化器对象作为其唯一参数。使用引擎初始化器设置运行时配置,并启动 Flutter Web 引擎。

initializeEngine() 函数返回一个 Promise,该 Promise 使用应用运行器对象进行解析。应用运行器有一个方法 runApp(),用于运行 Flutter 应用。

自定义 Web 应用初始化

在本部分中,了解如何自定义应用初始化的每个阶段。

加载入口点

loadEntrypoint 方法接受以下参数

名称 说明 JS 类型
entrypointUrl Flutter 应用入口点的 URL。默认为 "main.dart.js" 字符串
onEntrypointLoaded 引擎准备就绪时调用的函数。接收一个 engineInitializer 对象作为其唯一参数。 函数
serviceWorker flutter_service_worker.js 加载器的配置。(如果未设置,则不会使用 Service Worker。) 对象

serviceWorker JavaScript 对象接受以下属性

名称 说明 JS 类型
serviceWorkerUrl Service Worker JS 文件的 URL。serviceWorkerVersion 会附加到 URL。默认为 "flutter_service_worker.js?v=" 字符串
serviceWorkerVersion index.html 文件中传递构建过程设置的serviceWorkerVersion 变量 字符串
timeoutMillis Service Worker 加载的超时值。默认为 4000 数字

初始化引擎

Flutter 3.7.0 开始,你可以使用 initializeEngine 方法通过一个简单的 JavaScript 对象配置 Flutter Web 引擎的几个运行时选项。

你可以添加以下任何可选参数

名称 说明 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)。 bool
canvasKitMaximumSurfaces CanvasKit 渲染器可以使用的最大叠加曲面数。 double
debugShowSemanticNodes 如果 true,Flutter 会在屏幕上明显地渲染语义树(用于调试)。 bool
hostElement Flutter 将应用程序渲染到的 HTML 元素。未设置时,Flutter Web 将接管整个页面。 HtmlElement
renderer 指定当前 Flutter 应用程序的Web 渲染器,可以是 "canvaskit""html" 字符串

引擎配置示例

initializeEngine 方法允许你将上面描述的任何配置参数传递给你的 Flutter 应用程序。

考虑以下示例。

你的 Flutter 应用应使用 id="flutter_app" 定位 HTML 元素,并使用 canvaskit 渲染器。生成的 JavaScript 代码类似于以下内容

onEntrypointLoaded: async function(engineInitializer) {
  let appRunner = await engineInitializer.initializeEngine({
    hostElement: document.querySelector("#flutter_app"),
    renderer: "canvaskit"
  });
  appRunner.runApp();
}

有关每个参数的更详细说明,请参阅 Web 引擎 configuration.dart 文件的“运行时参数”文档部分。

跳过此步骤

你可以调用 autoStart() 来使用其默认配置初始化引擎,然后在初始化完成后立即启动应用,而不是在引擎初始化器上调用 initializeEngine()(然后在应用程序运行器上调用 runApp())。

_flutter.loader.loadEntrypoint({
  serviceWorker: {
    serviceWorkerVersion: serviceWorkerVersion,
  },
  onEntrypointLoaded: async function(engineInitializer) {
    await engineInitializer.autoStart();
  }
});

示例:显示进度指示器

在初始化过程中为应用程序的用户提供反馈,请使用为每个阶段提供的挂钩来更新 DOM

<html>
  <head>
    <!-- ... -->
    <script src="flutter.js" defer></script>
  </head>
  <body>
    <div id="loading"></div>
    <script>
      window.addEventListener('load', function(ev) {
        var loading = document.querySelector('#loading');
        loading.textContent = "Loading entrypoint...";
        _flutter.loader.loadEntrypoint({
          serviceWorker: {
            serviceWorkerVersion: serviceWorkerVersion,
          },
          onEntrypointLoaded: async function(engineInitializer) {
            loading.textContent = "Initializing engine...";
            let appRunner = await engineInitializer.initializeEngine();

            loading.textContent = "Running app...";
            await appRunner.runApp();
          }
        });
      });
    </script>
  </body>
</html>

有关使用 CSS 动画的更实际示例,请参阅 Flutter Gallery 的初始化代码

升级旧项目

如果你的项目是在 Flutter 2.10 或更早版本中创建的,你可以通过运行 flutter create 来使用最新的初始化模板创建一个新的 index.html 文件,如下所示。

首先,从你的 /web 目录中删除文件。

然后,从你的项目目录中运行以下命令

$ flutter create . --platforms=web