本頁詳細介紹 Flutter Web 應用的初始化過程以及如何對其進行自定義。

啟動

#

flutter build web 命令會在構建輸出目錄(build/web)中生成一個名為 flutter_bootstrap.js 的指令碼。該檔案包含初始化和執行 Flutter 應用所需的 JavaScript 程式碼。您可以透過在 Flutter 應用的 web 子目錄中的 index.html 檔案中為其新增一個非同步指令碼標籤來使用此指令碼。

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

或者,您可以透過在 index.html 檔案中插入模板標記 {{flutter_bootstrap.js}} 來內聯 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_bootstrap.js 檔案,該檔案會簡單地初始化您的 Flutter 應用。但是,在某些情況下,您可能需要自定義此初始化過程,例如:

  • 為您的應用設定自定義 Flutter 配置。
  • 更改 Flutter 服務工作者的設定。
  • 編寫自定義 JavaScript 程式碼,在啟動過程的不同階段執行。

要編寫自己的自定義啟動邏輯,而不是使用構建步驟生成的預設指令碼,您可以將 flutter_bootstrap.js 檔案放在專案根目錄的 web 子目錄中。該檔案會被複制並用於替換構建生成的預設指令碼。此檔案也是一個模板,您可以在其中插入一些特殊的標記,這些標記會在構建時複製 flutter_bootstrap.js 檔案到輸出目錄時被構建步驟替換。下表列出了構建步驟將在 flutter_bootstrap.jsindex.html 檔案中替換的標記。

標記替換為
{{flutter_js}}使 FlutterLoader 物件可在全域性變數 _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 配置。Object
onEntrypointLoaded引擎準備好初始化時呼叫的函式。接收一個 engineInitializer 物件作為其唯一引數。Function

config 引數是一個物件,可以包含以下可選欄位:

名稱描述Dart 型別
assetBase應用 assets 目錄的基礎 URL。當 Flutter 從與實際 Web 應用不同的域或子目錄載入時,請新增此項。當您將 Flutter Web 嵌入到另一個應用中,或將其資源部署到 CDN 時,可能需要此項。String
canvasKitBaseUrl下載 canvaskit.wasm 的基礎 URL。String
canvasKitVariant要下載的 CanvasKit 變體。您的選項包括:

1. auto:下載最適合瀏覽器的變體。此選項預設為此值。
2. full:下載適用於所有瀏覽器的完整版 CanvasKit。
3. chromium:下載一個較小的 CanvasKit 變體,該變體使用 Chromium 相容的 API。警告:除非您計劃僅使用基於 Chromium 的瀏覽器,否則請勿使用 chromium 選項。
String
canvasKitForceCpuOnly當設定為 true 時,強制 CanvasKit 進行僅 CPU 渲染(引擎不會使用 WebGL)。bool
canvasKitMaximumSurfacesCanvasKit 渲染器可以使用的最大疊加層表面數量。double
debugShowSemanticNodes如果設定為 true,Flutter 會在螢幕上可見地渲染語義樹(用於除錯)。bool
entrypointBaseUrl您的 Flutter 應用入口點的基礎 URL。預設為“/”。String
hostElementFlutter 渲染應用的 HTML 元素。未設定時,Flutter Web 會接管整個頁面。HtmlElement
renderer指定當前 Flutter 應用的 Web 渲染器,可以是 "canvaskit""skwasm"String

示例:根據 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,以便在初始化過程的不同階段執行自定義邏輯。初始化過程分為以下幾個階段:

載入入口點指令碼
當服務工作者初始化完成,並且 main.dart.js 入口點已被瀏覽器下載並執行後,load 函式會呼叫 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();
  }
});

常見警告

#

如果您遇到類似以下的警告:

text
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;