内容简介:Angular产品构建性能测试
翻译:Vincent
译者注:作者是一位从事于JavaScript开发的工程师,本文描述了作者立足于编译和绑定这两个因素,尝试不同方案对应用程序性能的影响。以下为译文。
在本文中,将讨论Angular应用程序的一些替代方案。将介绍几种不同的方法,并重点讲述它们的优点和缺点。
希望你能认真读完下面的内容,但是如果你觉得文章很长,不想细读,下面就展示了相关结果。
下面的表格显示了所有测试方案的结果:
在研究静态assets的时候,Angular应用程序中最重要的影响因素就是编译和绑定。
编译
Angular会将特定语法通过编译转换为浏览器可以理解的纯JavaScript。它可以将模板语法(如ngFor,ngIf等)转换为纯JavaScript。
编译有两种不同的形式:动态编译和静态编译。它们的区别不在于编译了什么,而在于什么时候开始编译的。
动态编译是在应用程序被下载以后,在浏览器端进行编译的,这不仅意味着在应用程序被渲染以前需要做大量额外的工作,还意味着在应用程序运行时需要装载另外一个编译器。
静态编译是在构建时进行编译的,所以解决了上述这些问题。此外,另一个好处就是在Angular运行时我们再也不需要包含其它的编译器了,正因为如此,bundle的大小也就明显减小了。
站在生产应用的角度来说,动态编译可能不是一个好的选择,但是由于它为我们提供了一个低端基准线可以进行比较,因此我还是会举一些相关例子。
我们使用的demo是一个中等大小的应用,是由我的一些Angular例子组成的。
Angular的性能在移动设备上是有问题的,所以我将在Chrome中使用扼制“Good 3G”来模拟一个性能差的设备,从而进行演示。
为了简单起见,所有报告的加载时间都来自Chrome浏览器的网络标签的“Finish”值。
由于我已经部署了所有示例的版本,所以可以随意尝试不同的指标。
动态编译
由于低端基准线的原因,我已经将应用程序部署成了一个标准的动态编译的项目。
应用部署到了 这里 。
正如你看见的那样,在应用被全部渲染之前,会有一个很明显的加载过程。如果你打开了浏览器的网络标签页,你就会知道原因了。
该应用程序需要发出163个请求,大约需要6秒才能完全加载。 相对于标准而言,这太慢了。
绑定的动态编译
就像我上面提到的那样,动态编译存在的一个问题就是仅仅为了加载应用它就需要发出163个请求。
在动态编译的构建期间,添加绑定应该就可以解决这个问题。
这次的样例位于 这里 。
我使用了SystemJS-Builder来进行绑定。SystemJS-Builder是SystemJS的一种工具,但是它是一款独立的工具,完全脱离SystemJS模块加载器。
你可以看见,效果明显提升了。动态编译再也不会发出163个请求了,而且还很明显地缩小了负载(260kb)。尽管如此,总的加载时间还是超过了2秒。
尽管前进了一些,但是渲染时的停顿感还是很明显。
静态编译
动态编译的问题已经解决的差不多了,但是性能问题还是比较棘手。
幸运的是我们并没有因此就放弃了。我们还可以通过选择静态编译来改善性能,对JavaScript进行进一步的优化应该也可以。
接下来,我们将研究更切合实际的生产方式,看看它们是如何提高性能的。
绑定
静态编译在性能方面有很多优点,但是关于绑定还有很多需要认真考虑的事。
Rollup
在动态编译的构建过程中,我尝试绑定了CommonJS模块。虽然它很灵活,但事实证明它并不适合用来绑定。相反我们应该使用ES2105模块。
ES2015模块更适合于一种名为“Tree shaking”的技术。
Tree shaking是在应用程序代码中遍历导入和导出语句的过程。它是Tree shaking的一种很好的实现,所以它成为了很多人的选择。
关于Rollup版本的应用程序可以点击 这里 。
正如你所看到的那样,Rollup这个版本明显比动态编译构建的版本更快。加载时间减少到大概只有1.3秒,大小只有147kb,比之前大概减少了43%,原因就是由于去掉了编译器和使用了Tree shaking。
Webpack
接下来我们将重复实验使用Webpack作为绑定。Webpack是另一种比较受欢迎的框架,但它的方法与Rollup是有着天壤的区别。
与Rollup相比,Webpack总是会产生一些较大的绑定。这是由Webpack会把每一个包含的模块整合成一个模块系统的方式决定的,这就导致了额外的函数包装器的绑定需要更多的开销。
Webpack不支持Tree shaking,这也就意味着没有任何机会去使用Tree shake了。Webpack与Tree shaking会有些令人混淆的内容,但是 这篇文章 会帮你理清楚的。
Webpack的相关程序在 这里 。
你可以看见,使用Webpack的性能跟Rollup差不多,但是体积明显增大了(151k ~增长了2.7%)。
这4K的区别不值得引起我们的注意,但是由于额外的开销,Webpack总是会更大一点。
同样不值得注意的是Angular中的NgModule架构阻碍了Tree shaking。这可能是我们在Rollup和Webpack之间看不到更大差异的原因之一。
如果你的代码从同一个文件导出多个类,您还会看到Webpack大小的增加。这是Webpack最糟糕的用例,因为它不能摆脱未使用的导出类。
Closure 编译器
目前为止所有的结果看上去都挺好的,但是可改善的空间还是很大的。
Webpack和Rollup都是传统的绑定。除了Tree shaking(Rollup)和minfication之外,它们提供的代码优化很少。
为了更好的优化,我们可以添加Closure编译器。
与它们相比,Closure编译器的主要区别在于它将对应用程序进行更深入的分析。 它可以通过功能内联,函数扁平化和删除部分代码等方法从而进行压缩。 这比minifcation更有效,从Closure编译的过程中就可以体验到。
这次的样例位于 这里 。
Closure仅仅只有97.4kb,比Webpack小了35%,太不可思议了!总的加载时间也就大概1秒钟。
Closure编译器的结果真是吓到宝宝了,但是这种优化是要付出一定代价的。编译器对您的代码做了几个假设。 除非您确保您的代码与Closure兼容,否则您的应用程序可能会中断。
Angular和其自定义的Typescript编译器使得编译变得容易一些了。 通过Angular的Typescript编译器,确保某些约定使得代码与Closure更加兼容。
Webpack
目前我们只讨论了单一捆绑应用。随着应用程序的发展,将整个应用程序作为单个JavaScript软件包进行服务可能行不通了。
Webpack跟其它的相比,提供了更多的灵活性。Webpack可以将应用程序分解成多个文件。这在您使用路由器的情况下就会更加突出了的,因为您可以在每个路由上创建一个包。这就给了你真正意义上的懒加载。
这就是Webpack提供的灵活性比其他选择都要多的地方。Webpack支持将应用程序分割成多个文件。当你在使用路由器的情况下为每个路由上创建绑定,就能看到它的优点了。这就给了你真正意义上的懒加载。
在最后一个例子中,我将演示应用程序转换为每个路由的绑定。
应用部署到了 这里 。
您可以看出,当您浏览应用程序时,单独的软件包将按需加载。除了路由特定的捆绑包,还有一个“共享”捆绑包。 共享捆绑是101kb。 默认路由将一个3.1kb的捆绑包添加到初始支付负载。
由于初始负载的总数只有104kb,所以我们非常接近于Closure编译器示例的结果。加载时间也很相似,只是一秒多一点。
这里的关键是将负载分散到多个请求中,而不是单个母版负载。所有bundle的总和都超过了单个的大小,这并不重要。通过按需加载小的和快速的,应用程序将是非常快的。
我想提一下,理论上也可以使用Closure编译器,但是在编写的时候设置它并不简单。一旦我们将延迟加载添加到一个Closure 构建中,我们可以期望得到更好的结果。
本文所有的例子都可以在 这里 找到。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 在 Android Studio 里使用构建分析器提升构建性能
- webpack构建和性能优化探索
- 构建高性能ASP.NET站点(上)
- 《高性能linux服务器构建实战》
- 构建高性能ASP.NET站点(下)
- 构建高性能ASP.NET站点(中)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
人工智能
腾讯研究院、中国信通院互联网法律研究中心、腾讯AI Lab、腾讯开放平台 / 中国人民大学出版社 / 2017-10-25 / 68.00元
面对科技的迅猛发展,中国政府制定了《新一代人工智能发展规划》,将人工智能上升到国家战略层面,并提出:不仅人工智能产业要成为新的经济增长点,而且要在2030年达到世界领先水平,让中国成为世界主要人工智能创新中心,为跻身创新型国家前列和经济强国奠定基础。 《人工智能》一书由腾讯一流团队与工信部高端智库倾力创作。本书从人工智能这一颠覆性技术的前世今生说起,对人工智能产业全貌、最新进展、发展趋势进行......一起来看看 《人工智能》 这本书的介绍吧!