前言
这篇文章是《高性能网站建设指南——前端工程师技能精髓》的读书笔记,即,雅虎 14 条军规扩展版。个人认为书名副标题取名并不精确,前端工程师优化技能精髓似乎更适合,本文粗线条地记录了我觉得应该记录下来的知识点。个人备忘录,不具备连贯性,看不懂就对了。
通识
性能黄金法则
最终用户只有 10%~20%的响应时间花在了下载 HTML 文档上,其余的 80%~90%时间花在了下载页面中的所有组件上。
注:该统计出于大概十年前,现在比例应该有所变化,但还是有很大的优化空间
HTTP 备忘点
压缩
Request:Accept-Encoding: gzip,deflate
Response:Content-Encoding: gzip
条件 Get 请求
Request:If-Modified-Since: Wed, 22 Feb 2016 09:23:44 GMT
Response:Last-Modified: Wed, 22 Feb 2016 09:23:44 GMT
Expires
Response:Expires: Wed, 22 Feb 2016 09:23:44 GMT
Keep-Alive
Request:Connection: keep-alive
Response:Connection: keep-alive
14 军规
减少 HTTP 请求 Make Fewer HTTP Request
- 图片地图
- CSS Sprites
很多人认为合并后的图片会比分离的图片综合要大,因为合并后包含附加的空白区域。实际上恰恰相反,因为它降低了图片自身的开销(颜色表,格式信息,等等) - 内联图片
data:[<mediatype>][;base64],<data>
- 合并脚本和样式表
使用内容发布网络(CDN)
- 缺点:修改 HTTP 响应头必须通过第三方完成。
添加 Expires 头
- 可以同时制定两个响应头:Expires 和 Cache-Control 的 max-age。如果两者同时出现,HTTP 规范规定 max-age 指令将重写 Expires 头,例如:
Expires: Mon,15 Apr 2024 20:00:00 GMT
Cache-Control: max-age=312
开启 Gzip 压缩
- 注意点:代理缓存
- 在 Web 服务器相应中添加
Vary
头,这样就可以告诉代理根据一个或多个请求头来改变缓存的响应。
Vary: Accept-Encoding
代理缓存响应的多个版本,当有 gzip 头的请求时,响应压缩过的,反之是未经压缩的。 - 禁用缓存:
Vary: *
或Cache-Control: private
将样式表放在顶部
- 样式表放在底部对加载页面所需的实际时间并没有太大影响,但会导致浏览器阻止内容逐步呈现,这让用户感性上觉得页面加载更慢。
- 无样式内容的闪烁 FOUC(Flash of Unstyled Content)是浏览器行为,在样式表正确地下载并解析后,已经呈现的文字和图片要用新的样式重绘了。浏览器可以延迟呈现,知道所有样式表下载完毕,这导致了白屏,反之可以逐步呈现,但要承担闪烁的风险,这里没有完美的选择。
将脚本放在底部
- 放在顶部的影响:
- 会阻塞对其后面内容的呈现
- 会阻塞对其后面资源的下载
defer
属性表明脚本不包含document.write
,浏览器有这个线索可以继续呈现。
避免 CSS 表达式
-
谁会想到用户点击了一个文本框会导致 IE 锁死呢。
-
避免方式:创建一次性表达式和使用事件处理器取代 CSS 表达式
<style> p { background: expression(altBg(this)); } </style> <script> function altBg(ele) { ele.style.backgroundColor = new Date().getHours() % 2 ? "#f08" : "B98"; } </script>
使用外部 javascript 和 css
- 页面浏览量越少,内联论据越强势,反之外置论据越强势。
减少 DNS 查找
- 将静态资源放在独立域名下较好,但不要超过四个,在减少 DNS 查找和允许并行下载之间做出权衡。
精简 javascript 和 CSS
- gzip 压缩产生的影响更大,但精简能够进一步减小文件大小。
避免重定向
- 当服务器向浏览器返回一个重定向时,是指一个范围在 3XX 的状态码,表示用户代理必须执行进一步操作才能完成请求。
- 300 Multiple Choices
- 302 Moved Permancently
- 302 Moved Temporarily
- 303 See other
- 304 Not Modified (并非重定向,用来响应条件 GET 请求)
- 305 Use Proxy
- 306 不再使用
- 307 Temporary Redirect
301
和302
是使用最多的,303
和307
是 HTTP 1.1 添加的,用来澄清对 302 的使用,但现实情况是几乎没人采用。- 还有其他方式:
- HTML META :
<meta http-equiv="refresh" content="0; url=http://google.com">
- HTML META :
删除重复脚本
- 确保脚本只被包含一次,否则会带来性能损伤。
配置 ETag
- ETag 是唯一标识一个静态资源特定版本的字符串。
- If-None-Match 比 If-Modified-Since 具有更高的优先级
- ETag 可能会引发性能问题,这时候完全可以移除 ETag
使 AJAX 可缓存
- 当数据被认为是私有的时候,大多会使用
Cache-Control: no-store
。这样的响应根本不会被写入磁盘。 - 确保 AJAX 请求遵守性能优化原则,尤其应具有长久的 Expires 头
读后感
虽然知识点比较基础,但并不过时,读后我立即在自己博客上实践了下:
- 图片使用七牛 CDN,感谢hexo-qiniu-sync,访问速度明显加快。
- 删掉和替换掉了一些鸡肋功能,比如NexT 主题自带的浏览图片插件,换成了自己的简洁实现。
- 本来想搞一下 HTTP 配置,由于本站 HOST 在 Github 上,无从下手,好在 Github 在 HTTP 优化原则上已经做得很好了,省心省力。
除了 HTML/CSS/JavaScript(这三样已经够折腾的了),一个优秀的前端工程师还应该具备什么样的技能呢?从这本书可以得到点启发:
- 理解 HTTP 协议[《HTTP 权威指南》足矣]
- 了解浏览器工作原理及不同浏览器间的差异
- 掌握服务器端编程[可以从 Node 入手]
- 了解网络环境配置[可以学学 Nginx]