|
本帖最后由 hanguokai 于 2013-4-2 23:02 编辑
原文:http://han.guokai.blog.163.com/b ... 712013121114040100/
Web 开发需要 Tree shaking
Web开发者总是希望引用的 js 文件越小越好,这样页面能加载更快。尤其是作为选用第三方库的一个重要参考,因为要用的话就必须完整引用它。但问题的实质是传统 Web 开发中缺少一种自动化的方式来排除未使用的代码。比如,我们只用到了一个库的一小部分功能,却不得不完整引用它。Web开发者真正需要的是一种类似连接器的工具,自动将不需要的代码排除。
Dart 的 tree shaking 技术正是这种工具,不用担心只使用一小部分功能而引用了一个较大的库,因为 dart2js 把没有用到的代码自动排除了。
Dart 语言之所以能够使用 tree shaking 排除不需要的代码,是因为 Dart 程序的结构在编译之后就不再改变了。Dart 不支持在运行时动态改变程序的结构,以及像 eval() 这样极端动态的功能。另外,Dart 代码本身有良好的结构:classes, libraries, packages, type annotations, metadata 等。这样 Dart 可以更加确定程序的结构,更具侵略性的判断出哪些部分可能不会被使用。
JavaScript 一般使用 Google Closure Compiler 或 YUI Compressor 等压缩工具,它们的基本功能是最小化 JavaScript 代码并做适当的优化。
注意“最小化”与“去除未使用的代码”是不同的概念。Google Closure Compiler 和 YUI Compressor 默认会对所有代码最小化(比如对局部变量重命名),而不管它们是否被使用到,因此并不删除未使用的代码。不过 Closure Compiler 在高级优化(ADVANCED_OPTIMIZATIONS)的编译级别下会采用更具侵略性的优化,具有删除 dead code 的功能,但具有一定的风险。
dart2js
dart2js 当前总是启用 tree shaking 功能,没有对应的开关选项。
dart2js 的输出既可以是 JavaScript 代码也可以是 Dart 代码,默认输出为 JavaScript 代码,要输出 Dart 代码需要加上 --output-type=dart 。
dart2js 支持最小化选项 --minify ,最小化功能默认没有启用,需要手工指定。
示例
最简单的示例代码:
- f1() => print('use f1');
- f2() => print('use f2');
-
- main() {
- f1();
- }
复制代码 这里有两个函数 f1 和 f2,它们既可以作为 main() 所在的 dart 程序的一部分,也可以作为一个独立的 library,放在哪里并不重要。主函数 main() 中只使用了 f1,没有使用 f2 。
下面我们使用 dart2js 看下效果,为了方便我们把输出设为 dart 代码。- dart2js --output-type=dart Test.dart
复制代码 这样 dart2js 会在当前目录输出一个 out.dart 的文件,内容为:
- f1()=>print('use f1');main(){f1();}
复制代码
输出结果已经去掉了空白符并且只有一行,但因为我们这个示例非常简单,所以还是很容易看明白。
从中可以看出,dart2js 的输出中只有 f1() 和 main() 函数,而没有 f2() 。
如果使用最小化选项:- dart2js --minify --output-type=dart Test.dart
复制代码 输出结果为:
- A()=>print('use f1');main(){A();}
复制代码 可以看到,f1 被重命名为更简单的 A 。最小化就是通过类似这样的办法把代码进一步压缩,而不影响程序执行的正确性。这个示例过于简单,在实际应用中会更加有效。
参考资料:Minification is not enough, you need tree shaking
|
|