Web 前端性能优化

传说中的雅虎军规前端优化35条。

1.内容优化

1.尽量减少 HTTP 请求

合并文件图片,脚本文件,样式表,(CSS Sprites(背景图绝对定位)、行内图片(Base64编码))。

2.减少 DNS 查找
在DNS查找完成之前,浏览器无法从主机名下载任何东西。减少不同的主机名就可以减少DNS查找。
DNS查找被缓存起来(网络服务提供商,本地网络服务器,操作系统,浏览器)逐级查找。
使用预加载提速:Controlling_DNS_prefetching,dns-prefetching

3.尽量减少重定向
Web 站点子目录的后面添加个 / (Slash) ,就能有效避免一次重定向,二者之间是有差异的。
Apache 服务器,通过配置 Alias 或mod_rewrite 或是 DirectorySlash 能解决这个问题。

4.使得 Ajax 可缓存
让响应变得可缓存,对 Ajax 来说至关重要。适用于Ajax的其它规则:Gzip组件、减少DNS查找、压缩JavaScript、避免重定向、配置ETags。

5.延迟加载组件
灵活运用异步思想,onload事件之前和之后的一个理想选择。

6.预加载组件
灵活运用异步思想,无条件预加载(尽快开始加载,获取一些额外的组件),条件预加载(根据用户操作猜测用户将要跳转到哪里并据此预加载),提前预加载(在推出新设计之前预加载)。

7.减少 DOM 元素数量
用更好的语义化标记。

8.跨域分离组件
提高页面组件并行下载能力。但不要跨太多域名,否则就会增减dns查询。

9.最小化 iframe 的数量
iframe 不利于 SEO。针对前端优化来说优点:引入缓慢的第三方内容,比如标志和广告、安全沙箱、并行下载脚本。缺点:阻塞页面加载,非语义。

10.杜绝 http 404 错误
充分测试页面链接,加上对 Web 服务器 error 日志的不断跟踪,能有效减少 404 错误。
链接到的外部JavaScript有错误而且结果是404,将阻塞并行下载。

2.CSS优化

11.避免 CSS 表达式
通过其它手段也同样能实现更好一些。

12.使用link 而不是 @import
在 IE 中 @import 等于把 link 标记写在 HTML 的底部.

13.避免使用Filter
这个滤镜会阻塞渲染,卡住浏览器,还会增加内存消耗,用下划线hack:_filter来避免影响IE7及更高版本的用户。

14.把 CSS 放到代码顶部
把 CSS 放到代码页上端,HTML 页面从顶到下进行解析和渲染。

3.JavaScript优化

15.移除重复脚本
重复脚本会创建不必要的HTTP请求,执行无用的JavaScript代码,而影响页面性能。

16.减少 DOM 访问
用JavaScript访问DOM元素是很慢的,所以应该:
缓存已访问过的元素的索引。
先“离线”更新节点,再把它们添到DOM树上。
避免用JavaScript修复布局问题。
参考《如何优化 JavaScript 脚本的性能》提高 Ajax 应用程序性能,避开 Web 服务漏洞。

17.用智能的事件处理器
有时候感觉页面反映不够灵敏,是因为有太多频繁执行的事件处理器被添加到了DOM树的不同元素上,这就是推荐使用事件委托的原因。如果一个div里面有10个按钮,应该只给div容器添加一个事件处理器,而不是给每个按钮都添加一个。事件能够冒泡,所以可以捕获事件并得知哪个按钮是事件源。

18.脚本放到 HTML 代码页底部
当一个脚本在下载的时候,浏览器干不了其它的事儿(串行了)。所以,把它扔到最后面去处理。对于一些功能性的脚本,可能实现起来有些两难。不过对于国内网站来说,有很多使用 Google Analytics 服务进行网站数据分析的。这这一点来说,绝对可行的建议,放到页面最底下。

19.从页面中剥离 JavaScript 与 CSS
用外部文件可以让页面更快,因为JavaScript和CSS文件会被缓存在浏览器。

20.压缩 JavaScript 与 CSS
去除不必要的字符以减少大小,从而提升加载速度。启用了gzip模块。

4.图像优化

21.优化图片 (Optimize Images)
尽可能的使用 PNG 格式的图片,在考虑用 Pngcrush 或类似的工具进行优化。
请设计的同学考虑面向 Web 的图片。

22.使用 CSS Sprites 技巧对图片优化
图片横向排列一般都比纵向排列的最终文件小。
图片相似颜色可以保持低色数,最理想的是256色以下PNG8格式。
考虑移动端,不要在Sprite图片中留下太大的空隙。虽然不会在很大程度上影响图片文件的大小,但这样做可以节省用户代理把图片解压成像素映射时消耗的内存。
一个大k图片就把整个网站拖得很慢。

23.不要在 HTML 中使用缩放图片
不要因为在HTML中可以设置宽高而使用本不需要的大图。

24.用更小的并且可缓存的 favicon.ico
足够小,越小越好。
设置合适的有效期HTTP头(以后如果想换的话就不能重命名了),把有效期设置为几个月后一般比较安全,可以通过检查当前favicon.ico的最后修改日期来确保变更能让浏览器知道。

5.Cookie优化

25.缩小 Cookie
清除不必要的cookie。
保证cookie尽可能小,以最小化对用户响应时间的影响。
注意给cookie设置合适的域级别,以免影响其它子域。
设置合适的有效期,更早的有效期或者none可以更快的删除cookie,提高用户响应时间。

26.针对 Web 组件使用域名无关性的 Cookie
当浏览器发送对静态资源的请求时,cookie也会一起发送,而服务器根本不需要这些cookie。造成没有意义的网络通信量,应该确保对静态组件的请求不含cookie。可以创建一个子域,把所有的静态组件都部署在那儿。
Yahoo! 的静态文件都在 yimg.com 上,客户端请求静态文件的时候,减少了 Cookie 的反复传输对主域名 (yahoo.com) 的影响。

6.移动端优化

27.保证所有组件都小于25K
这个限制是因为iPhone不能缓存大于25K的组件,注意这里指的是未压缩的大小。这就是为什么缩减内容本身也很重要,因为单纯的gzip可能不够。

Updated: 根据这篇 iPhone caching 的文章,可供 Cache 的最大单个数据对象是 15K,而不是前面说的 25K。iPhone 总的 Cache Size 为 ###5M。浏览器地址栏的刷新按钮将导致无条件刷新所有组件。这些也是挺有趣的。

28.把组件打包到一个复合文档里
把各个组件打包成一个像有附件的电子邮件一样的复合文档里(多部分组成的文档),可以用一个HTTP请求获取多个组件(减少 HTTP 请求)。用这种方式的时候,要先检查用户代理是否支持(iPhone就不支持)。

7.Server端优化

29.使用Gzip组件
从HTTP/1.1开始,web客户端就有了支持压缩的Accept-Encoding HTTP请求头。(Accept-Encoding: gzip, deflate)。
如果web服务器看到这个请求头,它就会用客户端列出的一种方式来压缩响应。web服务器通过Content-Encoding相应头来通知客户端。(Content-Encoding: gzip)

30.避免图片src属性为空
html与JavaScript的src为空,会使浏览器会向服务器发送另一个请求。

31.设置 Etags
实体标签(ETags),是服务器和浏览器用来决定浏览器缓存中组件与源服务器中的组件是否匹配的一种机制(实体即静态资源)。
Etag 对多数站点性能的影响并不是很大。除非是面向 RSS 的网站。(IE 的 ETag 注意 IIS事项)
很多网站在不注意的情况下都是打开 Etag 的,而没有网站关心如何用,消耗资源而不知。并不是说 Etag 不好,合理利用 Etag ,绝对能取得很好的收益。

32.对 AJAX 请求使用 GET 方法
XMLHttpRequest POST 要两步,先发送HTTP头,在发送数据,而 GET 只需要一步,发送一个TCP报文。但要注意的是在 IE 上 GET 最大能处理的 URL 长度是 2K。

33.尽早清空缓冲区
较理想的清空缓冲区的位置是HEAD后面,因为HTML的HEAD部分通常更容易生成,并且允许引入任何CSS和JavaScript文件,这样就可以让浏览器在后台还在处理的时候就开始并行获取组件。(异步的思路)

34.使用 CDN
最好先分散静态内容,而不是一开始就重新设计应用程序结构。这不仅能够大大减少响应时间,还更容易表现出CDN的功劳。一组分散在不同地理位置的web服务器,用来给用户更高效地发送内容。
国内 CDN 的普及还不够。不过我们有独特的电信、网通之间的问题,如果针对这个作优化,基本上也算能收到 CDN 或类似的效果吧(假装如此)。

35.添加 Expires 或 Cache-Control 信息头
对于静态组件:通过设置一个遥远的将来时间作为Expires来实现永不失效。
多余动态组件:用合适的Cache-ControlHTTP头来让浏览器进行条件性的请求。
Apache、Nginx的相应配置。

最后使用工具 PageSpeed 一步一步来优化吧。

Reference:
https://developer.yahoo.com/performance/
http://ingf.github.io/web/2014/12/10/web-.html