沐鳴平台網址_Flutter 性能優化:tree shaking 和延遲加載

作者: 凹凸曼 – Bruce

本文是 Flutter 性能優化系列文章之一,記錄了 Flutter 團隊優化 Flutter Gallery(https://gallery.flutter.dev/#/) 的實踐。本文主要介紹了 tree shaking 和延遲加載在性能優化中的使用。 

原文鏈接:https://medium.com/flutter/

在優秀的用戶體驗中,app 的加載速度扮演着重要角色。Flutter web app 的初次加載時間可以通過最小化 js 包體積來提高。Dart 編譯器自帶 tree shaking 和延遲加載特性,這兩者都可以最大程度地減少 js 包體積。這篇文章介紹了這兩個特性的工作原理,以及如何應用。

默認開啟的 tree shaking 特性

編譯 Flutter web app 時,JS 包是通過 dart2js 編譯器生成的。一次 release 構建將會得到最高級別的優化,其中就包括了 tree shaking。

Tree shaking 是一個通過只將一定會被執行到的代碼包含進來,從而剔除無用代碼的過程。所以說,你不用擔心你的 app 引用的各種庫,因為沒有用到的 class 或者 function 會被排除掉。

來看一下 tree shaking 的實際效果:

  1. 創建一個 Dart 文件 greeter.dart :
abstract class Greeter {
  String greet(String name);
}

class EnglishGreeter implements Greeter {
   String greet(String name) => 'Hello $name';
}

class SwedishGreeter implements Greeter {
   String greet(String name) => 'Hej $name';
}

void main() {
  print(EnglishGreeter().greet('World'));
}
  1. 執行 dart2js -04 greeter.dart 命令,然後看一下生成的文件 out.js。

在生成的 JS 代碼中,沒有 SwedishGreeter 類,也找不到 Hej $name,因為它們在 tree shaking 過程中被編譯器移除了。

如果只通過靜態分析,編譯器只能找出哪些代碼是會被執行,哪些不會被執行的。舉個例子,假如 greeter 的定義依賴系統地區設置:

Locale locale = Localizations.localeOf(context);
if (locale.languageCode == 'sv') {
  greeter = SwedishGreeter();
} else {
  greeter = EnglishGreeter();
}

編譯器不知道用戶的系統地區設置,因此 EnglishGreeter 和 SwedishGreeter 都會被打包進去。對於這種情況,延遲加載可以幫助減少初始化的包體積。

延遲加載

延遲加載,也叫懶加載,允許你在需要時再加載各種庫。它可以用來加載 app 中很少用到的功能。請注意延遲加載是一個 dart2js 特性,所以這個特性對移動端 Flutter app 不可用。在以下這個最簡單的例子中,將包或者文件引入為 deferred,然後在使用時先等待加載:

import 'greeter.dart' deferred as greeter;

void main() async {
  await greeter.loadLibrary();
  runApp(App(title: greeter.EnglishGreeter().greet('World')));
}

在 Flutter 中,一切都是 widget,所以你可能會需要用到 FutureBuilder。因為一個 widget 的構建方法應該是同步的,因此你不能在一個構建方法中去 await loadLibrary 方法。但是,你可以在構建方法中返回一個 FutureBuilder,你也可以在等待加載庫時使用它來显示不同的 UI:

import 'greeter.dart' deferred as greeter;

FutureBuilder(
  future: greeter.loadLibrary(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.done) {
      return Text(greeter.greet('World'));
    } else {
      return Text('Loading...');
    }
  },
)

你可以嘗試運行這個倉庫中完整的例子,打開 Chrome 開發者工具,然後點擊網絡 tab 查看網絡活動。刷新頁面來觀察庫是什麼時候引入和加載的。在下面的截圖中,文件 main.dart.js_1.part.js 的加載是延遲的:


Flutter Gallery 中的本地化延遲加載

Flutter Gallery 支持超過 70 中語言,但是大多數用戶只用到一種。延遲加載本地化字符串是這個特性非常棒的應用。比如,實現了延遲加載本地化字符串之後,app 的初始化 JS 包體積減少了一半。如果你的 Flutter web app 中有很多本地化字符串,可以考慮一下延遲加載這些文件。gen_l10n.dart 腳本 使用了 –use-deferred-loading 選項來實現這個需求(目前只在 1.19 SDK master channel 上可用)。

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9722