《高性能网站建设进阶指南》读书笔记

《高性能网站建设进阶指南》

无阻塞加载脚本

无阻塞加载外链脚本的方法有:

  • XHR Eval,xhr 加载后 eval。
  • XHR 注入,xhr 加载后,创建 script 元素 scriptEle,然后把加载到的内容写进 scriptEle 的 text 属性来运行。
  • Script in Iframe,通过 frames/contentWindow 以及 parent/top 等来在父子窗口间相互调用。
  • Script DOM Element,动态创建 script 元素,然后设置 src 属性来加载外部脚本。
  • Script Defer,延迟执行,但执行顺序和声明 defer 的顺序一致,阻塞 DOMContentLoaded 事件。
  • document.write Script Tag,多个脚本并行下载,但依然阻塞其它类型资源,document.write("<script src='a.js'><\/script>")


整合异步脚本

异步脚本保持执行顺序的方法有:

  • 硬编码回调,外部脚本调用行内脚本的函数,从而让函数内的内容在外部脚本后执行
  • Window Onload, 监听 onload 事件,触发运行指定内容。需要外部脚本加载方式能阻塞 onload 事件
  • 定时器,定时检查依赖的外部脚本是否已加载(通过指定的暴露点),加载后才执行。
  • Script Onload

可伸缩的 Comet

Comet 是一个表示由服务端来控制数据流动的方案的概括术语,包括了轮询(Polling)1、长轮询(Long Polling)、永久帧(Forever Frame)、XHR 流(XHR Streaming)以及 WebSocket。

轮询,用 ajax 来主动发起轮询,收到响应结果后继续发起下一次请求。

长轮询,则是客户端首先和服务端建立起连接,服务端直到有数据时才返回给浏览器并关闭当前连接,然后浏览器发起下一次连接,这样,后续连接的发起是由服务端返回数据来驱动的,而不是浏览器主动轮询实现。其中,可以结合定时器来做心跳,服务端也可以做超时控制。

永久帧,用一个一直在输出内容不结束的 iframe 来父子通信,如服务端一个 while 循环。

XHR 流,利用 xhr 在 readyState 变为 4 之前接收到数据流来不断更新。

以上原基于 Ajax 的实现,可为了跨域需要而改为基于 JSONP 的实现。

WebSocket,在这本书出版的时候2,WebSocket 还没广泛支持,在 2018 年主流浏览器都支持了其基础功能,服务端推送的需求应首选该方案。

超越 Gzip 压缩

杀毒软件以及代理软件等客户端或 Web 代理可能会修改请求头,如移除或修改 Accept-Encoding,从而导致虽然绝大部分客户端(浏览器)都支持 Gzip,结果却返回未压缩的内容。

图像优化

这里关注的是无损压缩

优化 PNG 格式的图像:pngcrushPNGOUTOptiPNGPngOptimizer
剥离 JPEG 元数据(注释、APP 自定义信息、EXIF 等):jpegtran
把 GIF 转换为 PNG:ImageMagick
优化 GIF 动画:Gifsicle

高效 CSS 选择符的关键

样式系统从最右边的选择符开始向左匹配规则。只要当前选择符的左边还有其他选择符,样式系统就会继续向左移动,知道找到和规则匹配的元素,或者因为不匹配而退出。

  • 避免使用通配规则
  • 不要限定 ID 选择符
  • 不要限定类选择符
  • 避免使用后代选择器
  • 避免使用标签——子选择器
  • 质疑子选择符的所有用途
  • 依靠继承

响应时间规则

  • 0.1s,可以感知到和系统有交互,只需要展示结果而不需要额外的反馈
  • 1s,可以感知到交互有延迟,0.2s ~ 1s 间应展示适当的反馈来提示系统正在工作
  • 10s,用户保持专注的极限,超过这个极限应该给出预期完成时间或百分比等反馈。

参考


  1. 严格来说轮询并不属于 Comet,因为还是客户端主动发起 ↩︎
  2. 英文版在 2009-06-20 出版,中文版在 2010-04-01 出版 ↩︎