杨二

Machine repeats, Human creates

再读雅虎14条军规

前言

这篇文章是《高性能网站建设指南——前端工程师技能精髓》的读书笔记,即,雅虎 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
  • 301302是使用最多的,303307是 HTTP 1.1 添加的,用来澄清对 302 的使用,但现实情况是几乎没人采用。
  • 还有其他方式:

    • HTML META :<meta http-equiv="refresh" content="0; url=http://google.com">

删除重复脚本

  • 确保脚本只被包含一次,否则会带来性能损伤。

配置 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]

high performance