本期精读的文章是:[Front End Performance Checklist 2017](https://www.smashingmagazine.com/2016/12/front-end-performance-checklist-2017-pdf-pages/) 现在随着 web 应用的复杂性日益增加,其性能优化就会显得尤为必要,同时会给性能指标分析带来新的挑战,因为性能指标之间的差异性非常大,这取决于使用的设备、浏览器、协议、网络类型以及其它能够对性能产生影响的潜在因素(如:CDN、ISP、cache、proxy、firewall、load balancer、server 等)。 # 1 引言 logo 本文提供了解决如何让网站响应更加迅速、访问更加流畅等前端性能优化问题的方法,读者们可以提供一些在实际场景中的性能优化问题以及解决方案,可泛谈优化策略,亦可针对性深入讨论某个优化方法。 # 2 内容概要 文中列举了很多不同的性能优化策略、模型或方法,如下: ## 制定目标 ### 网站速度快于他人 20% 根据 [psychological research](https://www.smashingmagazine.com/2015/09/why-performance-matters-the-perception-of-time/#the-need-for-performance-optimization-the-20-rule) 指出,网站最少在速度上比别人快 20%,才能让用户感觉到比别人的更快。这个速度说的并不是整个页面的加载时间,而是[启动渲染时间](http://www.websiteoptimization.com/speed/tweak/start-render/),[首次有效渲染时间](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint),[交互时间](https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive)。 ### 控制响应时间在 100ms,控制帧速在 60 帧/秒 [RAIL performance model](https://www.smashingmagazine.com/2015/10/rail-user-centric-model-performance/) 提出的性能优化指标:务必在用户初始操作后的 100ms 内提供反馈。考虑到存在响应时间不足 100ms 的情况,页面最迟要在 50ms 的时候,把控制权交给主线程。 针对动画,其每一帧都需要在 16ms 内完成,这样才能保证每秒 60 帧(一秒/60=16.6ms),如果可以的话最好能在 10ms 内完成。 ### 控制首次有效渲染时间在 1.25s,控制 SpeedIndex 在 1000 控制启动渲染时间在 1s 以内,且速度指数在 1000 以内,对于首次有效渲染时间,最好可以优化到 1.25s 以内。 ## 环境搭建 ### 做好构建工具的选型 不要过度使用那些酷炫的技术栈,坚持选择适合开发环境的工具,如 Grunt、Gulp、Webpack、PostCSS,或者组合起来的工具。只要这个工具运行的速度够快,而且没有给项目维护带来太大问题,就够了。 ### 渐进增强 在构建前端结构的时,应始终将[渐进增强](https://www.aaron-gustafson.com/notebook/insert-clickbait-headline-about-progressive-enhancement-here/)作为指导原则。首先设计并且构建核心体验,再完善为高性能浏览器设计的高级特性的相关体验。 ### 前端框架 最好使用那些支持服务器端渲染的框架,如 Angular,React,Ember 等。所选的框架要保证是被广泛使用并且经过考验的。不同框架对性能有着不同程度的影响,同时对应着不同的优化策略,所以要清楚的了解所选择框架的每个方面。 ### AMP 或 Instant Articles - Google 的 [AMP](https://www.ampproject.org/) 技术会提供一套可靠的性能优化框架(基于免费的 CDN 网络) - Facebook 的 [Instant Articles](https://instantarticles.fb.com/) 技术可以在 Facebook 上提升网站的性能。 ### 合理利用 CDN 根据网站的动态数据量,可以将部分内容给静态网站生成工具生成一个静态版本,将其置于 CDN 上,从而避免数据库的请求,亦可选择基于 CDN 的静态主机平台,通过交互组件丰富页面。 ## 优化构建 ### 确定优先级 将网站的所有文件(js,图片,字体,第三方 script 文件,多媒体内容等)进行分门别类。根据优先级区分基础核心内容,高性能浏览器设计的升级体验,附加内容等。具体细节可参考 [Improving Smashing Magazine’s Performance](https://www.smashingmagazine.com/2014/09/improving-smashing-magazine-performance-case-study/)。 ### 使用 cutting-the-mustard 技术 使用 [cutting-the-mustard](http://responsivenews.co.uk/post/18948466399/cutting-the-mustard) 技术能够实现不同类型的浏览器载入不同类型的资源(传统浏览器载入核心型资源,现代浏览器载入增强型资源)。在载入资源时要严格遵守相应的规则:页面加载时应首先载入 Core 资源,然后在 DomContentLoaded 事件触发时载入 Enhancement 资源,最后在 Load 事件触发时载入 Extras 资源。 ### micro-optimization 和 progressive booting - 使用 [skeleton screens](https://twitter.com/lukew/status/665288063195594752) 代替 loading indicator 展示 - 使用能够加速 App 初始化渲染的技术,如 [tree-shaking](https://medium.com/@richavyas/aha-moments-from-ngconf-2016-part-1-angular-2-0-compile-cycle-6f462f68632e#.8b9afnsub)、[code-splitting](https://webpack.github.io/docs/code-splitting.html) - 针对[服务端渲染](https://www.smashingmagazine.com/2016/03/server-side-rendering-react-node-express)增加[预编译](https://www.lucidchart.com/techblog/2016/09/26/improving-angular-2-load-times/)环节 - 使用 [Optimize.js](https://github.com/nolanlawson/optimize-js) 来加快初始加载速度,其原理是包装优先级高的调用函数 - [渐进启动](https://aerotwist.com/blog/when-everything-is-important-nothing-is/),先通过使用服务器端渲染快速完成首次有效渲染,浏览器再通过少量的 JS 代码就可以让交互时间接近于首次有效渲染时间。 ### 正确设置 HTTP cache header 需要正确设置 expires、cache-control、max-age 以及其它 HTTP 缓存响应头。请使用 Cache-control: immutable,可以参考 [Heroku’s primer on HTTP caching headers](https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers)、[HTTP caching primer](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en)以及[缓存之最佳实践](https://jakearchibald.com/2016/caching-best-practices/)。 ### 减少使用第三方库,异步加载 JS 想要在不等 js 执行完就开始渲染页面,可以通过在 HTML 的 script 标签上添加 defer 以及 async 属性来实现。减少第三方库和脚本的使用,尤其是社交网站的分享按键和 iframe 嵌入等。 ### 合理优化图片 - 要实现图片的响应式,应尽可能地使用带有 srcset、sizes 属性的 HTML 标签,如 `` - 使用 [WebP](https://www.smashingmagazine.com/2015/10/webp-images-and-performance/) 格式的图片 ### 图片优化进阶 - 可以使用[渐进式 JPEG 图片](http://www.zhangxinxu.com/wordpress/2013/01/progressive-jpeg-image-and-so-on/) - 可以使用压缩工具对不同格式的图片进行压缩,如 JPEG 图片用 [mozJPEG](https://github.com/mozilla/mozjpeg) 压缩、PNG 图片用 [Pingo](http://css-ig.net/pingo) 压缩、GIF 图片用 [Lossy GIF](https://kornel.ski/lossygif) 压缩、SVG 图片用 [SVGOMG](https://jakearchibald.github.io/svgomg/) 压缩 - 可以通过过滤掉不必要的图片细节(通过给图片添加高斯模糊滤镜实现)来减小文件的大小 - 可以使用 PhotoShop 导出(质量在 0-10%)的图片用于做背景图 - 可以使用[多张背景图的技巧](http://csswizardry.com/2016/10/improving-perceived-performance-with-multiple-background-images/)来提高对图片性能感知的能力 ### 优化 web 字体 - 如果使用开源字体,可以使用字体库中的子集或自己归类的子集来压缩文件大小 - 浏览器对 WOFF2 的支持度较高,当浏览器不支持 WOFF2 时,可以将 WOFF、OTF 作为备用 - 可以从 [Comprehensive Guide to Font-Loading Strategies](https://www.zachleat.com/web/comprehensive-webfonts/) 中选择一些针对字体优化的策略 - 可以使用 service worker 来达到字体缓存持久化 - [关于如何快速入门字体优化的教程](https://pixelambacht.nl/2016/font-awesome-fixed/) ### 快速推送 critical CSS 文件 为了保证能够让浏览器快速渲染,会将所有用于首屏渲染的 CSS 文件整合成一个文件(即 [critical CSS](https://www.smashingmagazine.com/2015/08/understanding-critical-css/)),以 `