0%

【文章翻譯】Best practices for optimizing Flutter web loading speed

【文章內容使用 Gemini 1.5 Pro 自動產生】

優化 Flutter Web 載入速度的最佳實務

身為一名與 Google Flutter 團隊合作,並在私人時間進行個人專案的 Flutter 開發人員,我遇到並理解了關於 Flutter Web 應用程式載入速度的擔憂。優化載入速度對於提升效能和提供良好的使用者體驗至關重要,尤其是在 Flutter 開發人員擴展到 Web 開發時。本指南提供可執行的策略和最佳實務,以加速 Flutter Web 應用程式的效能。

渲染

CanvasKit 是 Flutter Web 應用程式的預設 渲染器,它透過利用 WebGL 在平台間提供高效能和像素完美的一致性。這種功能對於需要豐富動畫和高保真度的複雜圖形應用程式特別有用。然而,CanvasKit 的內建檔案大小(約 1.5 MB)可能是一個缺點,特別是在初始載入時間至關重要的應用程式中。

儘管 flutter.js 載入 API 可並行下載 CanvasKit 和 main.dart.js,但所有 Flutter Widget 都必須等到它們完全載入到瀏覽器中,這可能會在應用程式變得互動之前導致明顯的延遲。為了減輕這些問題並優化載入體驗,開發人員可以選擇 Wasm 渲染模式。

由於 Flutter Web 中的 WebAssembly 支援 被視為實驗性並且可能會發生變化,因此這些步驟適用於願意嘗試尖端功能的開發人員。功能和指令可能會演變,因此請務必參閱最新的 Flutter 文件以瞭解目前的實務。

相容性

當使用 Wasm 進行構建時,dart:html 套件不受支援。此限制意味著您必須仔細考慮您的應用程式相依的 API。或者,web 套件dart2wasmdart2js 支援。

效能

Wasm 不僅與 CanvasKit 相比減少了應用程式大小,而且與 JavaScript 相比,啟動速度也更快。

延遲載入

Dart 的 延遲載入函式庫 允許您分割程式碼,並且只在需要時載入部分程式碼,從而減少初始載入時間。以下部分將討論如何使用延遲載入。

宣告延遲載入

在 Dart 檔案的頂部,宣告您要延遲載入的載入。在載入陳述式中,指定 deferred,後面接著識別符號。當您需要使用函式庫時,請使用延遲載入的 loadLibrary() 方法非同步載入它:

1
2
3
4
5
6
import 'package:myapp/hello.dart' deferred as hello;

Future<void> loadHelloLibrary() async {
await hello.loadLibrary();
hello.sayHi();
}

呼叫載入函數

在您的 Flutter 應用程式中,根據需要呼叫此函數,例如,作為對使用者互動的回應。以下範例在使用者按下 Widget 時載入所需的函式庫:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(home: MyApp()));
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
loadHelloLibrary();
},
child: Text('Load Feature'),
),
),
);
}
}

未等待的函數呼叫

為了減少顯示應用程式初始 Widget 所花費的時間,請嘗試在呼叫 runApp 之前不要等待代價高昂的 Future。可以將一些 Future 設為未等待,以便它們在完成後更新 UI。unawaited 函數 允許應用程式程式設計師明確告知「未等待的 Future」提示,這些 Future 不會等待。此改進透過讓應用程式感覺更具回應性,在應用程式啟動和頁面載入期間都增強了使用者體驗。但是,必須小心管理這些函數,以避免與應用程式狀態一致性和資源管理相關的問題。

1
2
3
4
5
6
7
8
9
10
import 'dart:async';
import 'package:flutter/material.dart';

void main() {
unawaited(downloadVideos().then((videos) {
playlist.add(videos);
}));

runApp(const MyApp());
}

媒體檔案

以最佳解析度顯示資產

Flutter 會自動根據設備的像素密度 以適當的解析度載入資產。這可確保在不同螢幕尺寸上顯示最佳視覺效果。雖然優化資產以進行有效傳遞很重要,但請優先考慮在探索替代圖片格式之前提供所需精確解析度的資產,就像我們在下一節中將討論的那樣。

更好的圖片壓縮

PNG 和 JPG 是網站上使用最普遍的圖片格式。這些格式以其廣泛的支援和相容性而聞名。然而,新一代格式(如 WebPAVIF)在減少檔案大小方面取得了重大進展,而不會顯著降低圖片品質。例如,原始大小為 319 KB 的 PNG 圖片可以用 WebP 格式壓縮到僅 38 KB,或者更令人印象深刻的是,可以用 AVIF 格式壓縮到 10 KB。這些檔案大小的縮減是透過肉眼幾乎無法察覺的品質損失來實現的,這證明了這些格式在保持視覺保真度的同時,提升網站載入速度的潛力。

PNG 319 KB / WebP 38 KB / AVIF 10 KB

然而,重要的是要注意,並非所有瀏覽器都支援 WebPAVIF 圖片。在將這些格式整合到您的網站之前,請驗證它們與您的觀眾最常使用的瀏覽器的相容性。這將幫助您確定這些新一代圖片格式是否符合您的網站要求和觀眾需求。

快取

記憶體、磁碟、Service Worker 快取

利用記憶體快取、磁碟快取和 Service Worker 的功能可以顯著減少初始頁面載入後的載入時間。這是因為這些快取機制需要檔案先載入一次,然後才能快取它們。記憶體快取儲存在 RAM 中,提供快速的存取速度,但易失性。另一方面,磁碟快取雖然速度較慢,但提供持久性。Service Worker 作為可程式化的網路代理,可以跨記憶體和磁碟實現複雜的快取策略。

瀏覽器或作業系統通常會自動管理記憶體和磁碟快取,除非有特定的要求需要以程式方式操作它們,否則不需要手動干預。雖然 Flutter 在一定程度上管理 Service Worker,但開發人員可以靈活地在 Flutter 之外實作自訂 Service Worker,以增強對快取和網路互動的控制。

Wasm

瀏覽器會快取 Wasm 檔案(如 CanvasKit,以及很快的 dart2wasm 輸出),以及它們的編譯原生程式碼。這意味著快取的 Wasm 模組載入速度與原生二進制檔案一樣快,與 JavaScript 不同,JavaScript 需要重新解析、重新編譯和重新 JIT(Just-In-Time)處理。

雖然 Flutter 的 Wasm 構建選項尚未完全穩定,但當 dart2wasm 穩定後,採用現代 JS-interop 實務會使您受益。例如,避免使用 dart:htmldart:js 等傳統函式庫,並優先考慮 package:webdart:js_interop。此外,請考慮檢查您正在使用的其他套件是否與 Wasm 相容。

預載入

HTML <head> 標籤、HTTP 響應標頭

預載入資產(如圖片、字體和 JavaScript 檔案)可以顯著提高網頁載入速度。透過在 HTML <head> 標籤中預載入或使用 HTTP 響應標頭,您可以指示瀏覽器在需要用於渲染之前下載這些資源。這樣可以消除延遲,並確保更順暢的使用者體驗。若要預載入資產,請在 <head> 部分添加 <link> 標籤,並將 rel 屬性設定為 preload。僅預載入立即使用的資產,最優化的是應用程式的第一個螢幕,否則瀏覽器會將預載入視為浪費頻寬。

HTML <head> 標籤

1
2
3
4
5
6
7
8
<head>
<link rel="preload" href="assets/logo.webp" as="image" type="image/webp" />
</head>
<body>
<picture>
<source src="assets/logo.webp" type="image/webp" />
</picture>
</body>

Firebase 托管的 HTTP 響應標頭

以下程式碼塊是一個 firebase.json 範例,其中包含一個鍵/值組合,展示如何為資產預載入添加 HTTP 標頭。

1
2
3
4
5
6
"headers": [
{
"key": "Link",
"value": "<assets/logo.webp>; rel=preload; as=image"
}
]

登陸頁面

Flutter 使您能夠使用純粹的 HTML/CSS 為您的應用程式構建完全互動式的登陸頁面。當使用者與您的登陸頁面互動時,flutter.js 會預載入您的 Flutter 應用程式 - 確保使用者導航到 Flutter 應用程式時立即啟動。這對於具有 播放 按鈕的遊戲和需要登入的應用程式特別有用。

載入/啟動畫面

雖然我們一直關注應用程式載入速度的技術優化,但感知載入速度更為關鍵。您的目標應該是讓您的應用程式 感覺很快

載入/啟動畫面在增強這種感知方面非常有效。透過提供視覺活動,它們向使用者保證應用程式正在迅速啟動。相反,空白螢幕會引起不確定性,可能會導致沮喪和頁面重新整理。

為了實現最快的回應能力,請使用純粹的 CSS/HTML 在您的 index.html 檔案中直接實作啟動畫面。這可以最大限度地減少任何潛在的延遲。

例如,請查看 Flutter Gallery 實作

結語

在本文件中,我們探討了加速 Flutter Web 應用程式初始載入和渲染效能的方法。您可以採用多種策略,但請記住,每個解決方案都涉及權衡取捨。選擇最適合您的特定需求和使用者需求的優化。透過結合這些方法، 您可以為您的 Flutter Web 應用程式創造更流暢、更具回應性的使用者體驗。


優化 Flutter Web 載入速度的最佳實務 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。