原文连接:https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99ejavascript
当咱们创建的网站愈来愈多依赖Javascript时,咱们有时候会为了一些咱们不容易看到的地方付出代价。在这边文章中,我会讲述一些规范,若是你想让你的网站在移动设备上更快加载和响应的话,这些规范可能会对你有帮助。html
tl;dr: less code = less parse/compile + less transfer + less to decompress前端
tl;dr是too long; don't read的缩写java
当大多数开发者想到Javascript的开销时,可能会联想到下载和执行开销。传送的数据量越大,那用户链接的速度就越缓慢。webpack
即便在一些大国家,若是用户的有效网络不是3G, 4G 或者WiFi的话(用户可能在咖啡厅用着wifi,可是实际网速是2G),那么这就会成为一个问题。git
你能够经过如下几种方式来减小网络传输的开销:github
一旦脚本下载完成了以后,JS最大的开销之一就是JS引擎的解析/编译代码。在Chrome开发者工具里的“性能”模块,解析和编译代码用黄色标识.web
经过Bottom-Up/Call Tree(调用树),能够看实际的解析/编译用时:npm
可是,为何这个很重要呢?小程序
花费大量时间在解析/编译代码上会延迟用户与网站的交互,破坏用户体验。在网站呈现以前,JS量越大,花在解析/编译上的时间就越长。
对于大小相同的JS和图片或者网页字体,JS须要浏览器花费的时间最多— Tom Dale
与Javascript相比,处理相同大小的图片所须要的开销明显小不少。
当咱们讨论解析和编译的速度之慢时,上下文是很重要的。咱们的讨论是基于平均水平的移动设备。平均水平的用户使用的移动设备多是CPU/GPU很慢的、没有L2/L3缓存的或者甚至内存颇有限的。
网络和设备不老是匹配的。一个用户可能有很好的网络条件,可是只有一部烂手机。相反,一个用户可能有一部神机,却碰上了龟速网络 — Kristofer Baxter, LinkedIn
在JavaScript Start-up Performance文中, 我提到了分别在低端和高端机型中1MB原始JS代码的解析时间. 它们之间的差距达到了2-5倍.
那实际的网站如何呢,好比CNN.com?
在高端机iPhone 8上,解析/编译JS代码只需大约4s,而在平均水平的手机Moto G4上却要花上将近13s。这很明显得影响了用户可以多快看到界面。
这就要求咱们要更加注重一些平均水平的设备的测试,而不只仅是本身口袋里的高端机。上下文是很重要的:必定要针对你的用户的设备和网络进行优化。
能够经过 mobile device classes 来看看真实用户的分析状况。
咱们真的是传输了太多的JS代码吗? 呃。。有可能 :)
使用HTTP Archive (top ~500K sites)来分析JS在移动设备上的使用状况JavaScript on mobile, 咱们就能发现50%左右的网站须要14s以上才能真正让用户用上。这些网站光花在解析/编译JS上的时间就多达4s.
介于以上这些状况,怪不得用户在尚未看到页面以前就离开了。咱们固然能够在这点上作得更好。
删除一些非必要JS代码能有效减小转换时间、CPU的解析/编译时间以及内存占用。一样也能是用户更快得与网站交互。
固然,编译和解析只是JS开销的一部分。执行JS代码也是主线程上必需要作的,若是执行时间冗长,也会直接影响用户体验。
一旦脚本执行时间超过50ms,后果不堪设想 — Alex Russell
为了减小执行时间,你能够将JS代码分离成一块块的,以避免阻塞主线程。
有时候一些设计模式可以帮助你,好比基于路由的代码分块 (route-based chunking) 或者PRPL.
以下图所示,PRPL就是一个利用代码分离和缓存方式来优化交互体验的模式:
让咱们来看看这个影响.
咱们使用V8的 Runtime Call Stats 分析了一些主流网站以及PWA的加载时间。能够看到,解析时间在整个加载时间中占了可观的部分:
Wego,是使用了PRPL的一个站点,让每一个路由都保持不多的解析时间,使得用户能更快得与网站交互。上图中的不少网站也是采用了代码分离和性能预算 (performance budget) 来尝试下降JS开销。
JS也会在其它方面影响页面性能:
内存。页面可能会由于垃圾回收而致使频繁的闪烁或暂停。当浏览器回收内存的时候,JS执行就会暂停。这就致使了当浏览器频繁回收垃圾时,JS执行的暂停频率就会比咱们想象中的更多。避免内存泄漏和频繁的垃圾回收可以是页面更稳定。
在运行时,若是JS运行时间过长就会阻塞主进程,致使页面没法交互。把这些任务分红一小块一小块 (能够采用 requestAnimationFrame() 或者 requestIdleCallback() 或者 scheduling) 可以最小化其带来的影响。
为了让网站更快呈如今用户面前,许多网站会使用服务器端渲染来实现,而后在页面返回后经过绑定事件来“升级”它。
小心 -- 这种方式也有它的开销。一方面传输回来的HTML比较大,另外一方面用户必须等到JS处理完毕才能真正与页面进行交互。
渐进式 Bootstrapping 多是一种更好的方法。先发送一部分功能性页面(只是当前路由须要的HTML/JS/CSS)回来。当更多的资源传输回来时,页面就会进行懒加载而且解锁更多的功能。
加载当前页面的代码实在是很是好的方法。PRPL和渐进式 Bootstrapping 就是能帮助实现这点的模式。
在网络不佳的状况下,传输数据的大小是相当重要的。对于CPU不给力的设备,解析时间是很重要的。
参考 Alex Russell 的 “Can You Afford It?: Real-world Web Performance Budgets”。
若是你正在搭建一个基于移动设备的站点,尽可能在典型的设备上开发。减小JS解析/编译时间,采用Performance Budget让团队成员都能检测JS开销。
这是本人的前端技术小程序,基本上全部的文章都会同步更新在小程序中。欢迎你们来凑热闹。