Flutter 性能优化:tree shaking 和延迟加载

更新日期: 2020-10-16阅读: 2.3k标签: Flutter

作者: 凹凸曼 - 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 上可用)。


链接: https://fly63.com/article/detial/9722

移动跨平台框架Flutter介绍和学习线路

Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序。我们兼容滚动行为、排版、图标等方面的差异。

初识flutter

关注flutter已经好久,因为没有发正式版,所以一直也不想过早的躺浑水,但是最近无意中看到几篇文章,再加上美团和咸鱼等app也一直在做灰度测试,所以上周开始看了一下官方文档,地址:https://flutter.io/docs/get-started/install,然后在此做一下总结。

深入理解Flutter多线程

Flutter默认是单线程任务处理的,如果不开启新的线程,任务默认在主线程中处理。和iOS应用很像,在Dart的线程中也存在事件循环和消息队列的概念,但在Dart中线程叫做isolate。

Flutter1.5 开始,将成为全平台 UI 框架!

Flutter 1.5 的发布,同期也宣布发布 Flutter for Web 的 Preview 版本,正式开启了 Flutter 的全平台 UI 框架之路。早在年初发布的 Flutter 2019 Roadmap 中,就有提到,会在今年支持移动设备之外的平台,对 Web 的支持,算是完成了一个新的里程碑吧。

Flutter支持Web开发了!

Flutter作为一个可移植的UI框架,已经支持现代Web应用开发了!我们很开心已经发布了SDK预览版,这样你可以在Web浏览器里直接运行你的Flutter UI代码。

Flutter 混合开发 (交互通信)

Flutter 与原生之间的通信依赖灵活的消息传递方式:1,Flutter 部分通过平台通道将消息发送到其应用程序的所在的宿主环境(原生应用)。2,宿主环境通过监听平台通道,接收消息。

Flutter 局部路由实现

Flutter是借鉴React的开发思想实现的,在子组件的插槽上,React有this.props.children,Vue有<slot></slot>。当然Flutter也有类似的Widget,那就是Navigator,不过是以router的形式实现(像<router-view></router-view>)。

Flutter Kotlin 到底该如何选择?

这两个技术在当下如何选择,我之前在公众号上的回复是:如果你已经处于一个比较满意的公司,并考虑长期发展,公司并未使用这两个技术,你可以专心钻研公司当下使用的,或者未来将要使用的,这些才能助你在公司步步高升。

Flutter 与 iOS 原生 WebView 对比

本文对比的是 UIWebView、WKWebView、flutter_webview_plugin(在 iOS 中使用的是 WKWebView)的加载速度,内存使用情况。测试网页打开的速度,只需要获取 WebView 在开始加载网页和网页加载完成时的时间戳

Flutter For Web

用来构建漂亮、定制化应用的跨平台的 UI 框架 Flutter 现在已经支持 Web 开发了。我们很高兴推出了一个预览版的 SDK 可以让开发者直接使用 Flutter UI 和业务逻辑代码构建 web 应用

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!