无阻塞加载脚本
无阻塞加载外链脚本的方法有:
- 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 格式的图像:pngcrush、PNGOUT、OptiPNG、PngOptimizer。
剥离 JPEG 元数据(注释、APP 自定义信息、EXIF 等):jpegtran。
把 GIF 转换为 PNG:ImageMagick。
优化 GIF 动画:Gifsicle。
高效 CSS 选择符的关键
样式系统从最右边的选择符开始向左匹配规则。只要当前选择符的左边还有其他选择符,样式系统就会继续向左移动,知道找到和规则匹配的元素,或者因为不匹配而退出。
- 避免使用通配规则
- 不要限定 ID 选择符
- 不要限定类选择符
- 避免使用后代选择器
- 避免使用标签——子选择器
- 质疑子选择符的所有用途
- 依靠继承
响应时间规则
- 0.1s,可以感知到和系统有交互,只需要展示结果而不需要额外的反馈
- 1s,可以感知到交互有延迟,0.2s ~ 1s 间应展示适当的反馈来提示系统正在工作
- 10s,用户保持专注的极限,超过这个极限应该给出预期完成时间或百分比等反馈。