Flutter Web 應用初始化
自定義 Flutter 應用在 Web 上的初始化方式。
本頁面詳細介紹了 Flutter Web 應用的初始化過程以及如何對其進行自定義。
載入程式(Bootstrapping)
#flutter build web 命令會在構建輸出目錄(build/web)中生成一個名為 flutter_bootstrap.js 的指令碼。該檔案包含初始化和執行 Flutter 應用所需的 JavaScript 程式碼。你可以透過在 Flutter 應用 web 子目錄下的 index.html 檔案中新增一個非同步指令碼標籤來使用此指令碼。
<html>
<body>
<script src="flutter_bootstrap.js" async></script>
</body>
</html>
或者,你也可以透過在 index.html 檔案中插入模板標記 {{flutter_bootstrap_js}},將 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_bootstrap.js 檔案會對 Flutter 應用執行簡單的初始化。但在某些場景下,你可能需要自定義此初始化過程,例如:
- 為你的應用設定自定義 Flutter 配置。
- 更改 Flutter Service Worker 的設定。
- 編寫自定義 JavaScript 程式碼以在啟動過程的不同階段執行。
若要編寫自己的自定義引導邏輯,而不是使用構建步驟生成的預設指令碼,你可以在專案的 web 子目錄中放置一個 flutter_bootstrap.js 檔案,該檔案會被複制並用於替代構建生成的預設指令碼。此檔案同樣支援模板化,你可以插入多個特殊標記,構建步驟會在將 flutter_bootstrap.js 檔案複製到輸出目錄時替換這些標記。下表列出了構建步驟將在 flutter_bootstrap.js 或 index.html 檔案中替換的標記:
| 標記 | 替換為 |
|---|---|
{{flutter_js}} |
使 FlutterLoader 物件在 _flutter.loader 全域性變數中可用的 JavaScript 程式碼。(詳情請參閱下方的 _flutter.loader.load() API 部分。) |
{{flutter_build_config}} |
一條設定構建過程產生元資料的 JavaScript 語句,該語句為 FlutterLoader 提供正確引導應用所需的資訊。 |
{{flutter_service_worker_version}} |
代表 Service Worker 構建版本的唯一數字,可作為 Service Worker 配置的一部分傳遞(請參閱下方的“常見警告”資訊)。 |
{{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 配置。 | 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 |
canvasKitMaximumSurfaces |
CanvasKit 渲染器可以使用的最大覆蓋圖層(overlay surfaces)數量。 | double |
debugShowSemanticNodes |
若為 true,Flutter 會在螢幕上直觀地渲染語義樹(用於除錯)。 |
bool |
entrypointBaseUrl |
Flutter 應用入口點的基礎 URL。預設為 "/"。 | String |
hostElement |
Flutter 渲染應用的 HTML 元素。如果不設定,Flutter Web 將接管整個頁面。 | HtmlElement |
renderer |
為當前的 Flutter 應用指定 Web 渲染器,可選 "canvaskit" 或 "skwasm"。 |
String |
forceSingleThreadedSkwasm |
強制 Skia WASM 渲染器以單執行緒模式執行以保持相容性。 | bool |
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,以便在初始化過程的不同部分執行自定義邏輯。初始化過程分為以下階段:
- 載入入口點指令碼
-
一旦 Service Worker 初始化完成,且瀏覽器下載並運行了
main.dart.js入口點,load函式就會呼叫onEntrypointLoaded回撥。在開發過程中的每次熱重啟(hot restart),Flutter 也會呼叫onEntrypointLoaded。 - 初始化 Flutter 引擎
-
onEntrypointLoaded回撥接收一個引擎初始化器物件作為其唯一引數。使用引擎初始化器的initializeEngine()函式來設定執行時配置(例如multiViewEnabled: true),並啟動 Flutter Web 引擎。 - 執行應用
-
initializeEngine()函式返回一個Promise,解析後得到一個應用執行器物件。應用執行器有一個單一方法runApp(),用於執行 Flutter 應用。 - 嚮應用新增(或移除)檢視
-
runApp()方法返回一個應用物件。在多檢視模式下,可以使用addView和removeView方法從宿主應用管理應用檢視。要了解更多資訊,請檢視嵌入模式。
示例:顯示進度指示器
#要在初始化過程中嚮應用使用者提供反饋,請使用每個階段提供的鉤子(hook)來更新 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;