关闭

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

时间: 2020-10-16阅读: 83标签: 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 上可用)。


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

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

关闭

Flutter 国际化应用实战

借助App Store与Google Play,全世界任何一个国家的使用者都可以使用我们开发的应用,不过由于应用的使用者来自不同国家,所以在应用正式上架之前需要让应用能够支持多种语言,即应用的国际化。在Flutter开发中

Flutter 局部路由实现

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

Flutter事件监听

在大前端的开发中,必然存在各种各样和用户交互的情况:比如手指点击、手指滑动、双击、长按等等。在Flutter中,手势有两个不同的层次:

Flutter For Web

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

Flutter的生命周期和路由

Flutter主要有两种:无状态的 StatelessWidget和有状态的 StatefulWidget,一个 StatelessWidget 是不能被改变的,比如:Icon、Text等。由于不可改变,因此并没有什么生命周期。

Flutter 同步系统的 HTTP 代理设置

一般的,在 Flutter APP 里请求 HTTP 使用的是官方提供的 http 包。但是,有一个问题,在 Android 或者 iOS 上运行 Flutter APP,系统里配置的 HTTP 代理并不生效?

深入Flutter

本文主要说了Flutter内部使用了怎样的算法和优化让Flutter如此强大。某些内容对比了Flutter和其他开发工具一致性算法的优劣,不过个人感觉还是太过简短,后面我会花更多的时间来研究这方面的内容,后续补上

深入理解Flutter多线程

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

flutter 自定义弹框

对于这种样式,我们可以选择自定义Dialog,具体的样式可以根据自己的需要进行修改。 例如,下面是我的实现,由于文本是一个列表,所以我需要新建一个实体类,如下所示。

Flutter 应用性能检测与优化

软件项目的交付是一个复杂且漫长的过程,任何细小的失误都有可能导致交付过程失败。在软件开发过程中,除了代码逻辑的 Bug 和视觉异常这些功能层面的问题之外,移动应用另一类常见的问题是性能问题,比如滑动操作不流畅

点击更多...

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