前端性能优化
on Front-End
其实,针对前端性能优化的基本思路大致有这么三个方向:
- 基于浏览器渲染页面原理上的 CSS、JavaScript 语法层面的优化。
- 针对 HTTP 协议特性上的网络层面的优化,如合并、压缩资源等。
- 针对用户体验层面的交互逻辑优化,如懒加载等。
在当前计算机物理性能的快速发展下,只要代码写得不是特别过分,即使使用了第一点中更好的语法也不会对前端性能提升很多。而第二点则是必须持续要做的,同时第三点现在也成为了性能优化的主要发力点。基于以上后两点的思路,常见的手段和实践如下:
在 http 请求中添加 Expires 或 Cache-Control 报文头
对静态内容添加 Expires
,可以将静态内容设为永不过期,或者很长时间以后。
对动态内容应用合适的 Cache-Control
,可以让浏览器根据条件来发送请求并使响应可以被浏览器缓存。
减少 http 请求次数
减少页面中的资源请求次数是缩短网页响应时间的关键。常见的技巧有:
- 捆绑压缩文件: 将多个脚本或样式文件打包并压缩成一个文件。
- CSS Sprites:将多张图片拼成一张图片,由 CSS 控制局部图片的显示。
- base64 转换:将较小的图片通过 base64 转换为字符串以减少 http 请求。
Gzip 压缩传输文件
Gzip 通常可以减少网页内容 70% 的大小,包括脚本、样式表、图片等文件,主流服务器都有相应的压缩支持模块。
使用 GET Ajax 请求
浏览器在实现 XMLHttpRequest POST 的时候分成两步,先发 header,然后发送数据。而 GET 却可以用一个 TCP 报文完成请求,所以使用 Ajax 请求数据时尽量通过 GET 来完成。
减少 Cookie 大小
Cookie 被用来做认证或个性化设置,其信息被包含在 http 报文头中。常见的技巧有:
- 去除没有必要的 Cookie,如果网页不需要 Cookie 就完全禁掉。
- 将 Cookie 的大小减到最小。
- 注意 Cookie 设置的 domain 级别,没有必要情况下不要影响到 sub-domain。
- 设置合适的过期时间,比较长的过期时间可以提高响应速度。
使用 CDN
前端性能优化的第一定律就是减少网页内容的下载时间。CDN 就可以有效地提升下载速度。
根据域名划分内容或使用无 Cookie 域名
大多数网站的静态资源都没必要设置 cookie,所以可以采用不同的 domain 来单独存放这些静态文件,这样做不仅可以减少 Cookie 大小从而提高响应速度,还有一个好处是有些 proxy 拒绝缓存带有 Cookie 的内容,如果能将这些静态资源的 Cookie 去除,那就可以得到这些 proxy 的缓存支持。一般网站会将静态资源放在类似于 static.example.com 或 CDN 上,动态内容放在 www.example.com 上。
浏览器一般对同一个域的下载连接数有所限制,按照域名划分下载内容可以增大并行下载连接数。但是注意控制域名数量在 2-4 个之间,不然 DNS 查询也是个问题。
减少 DNS 查询次数
DNS 查询也会消耗响应时间。如果网页内容来自多个不同的 domain,那么浏览器首次解析这些 domain 就需要消耗一定的时间。所以应该尽可能少地使用外部资源或保持外部域名的少样性。
减少 DOM 元素数量
网页中过多的 DOM 元素对网页的加载和脚本的执行都是沉重的负担。通过 document.getElementsByTagName('*').length
便可计算出页面中 DOM 元素的数量。用 JavaScript 访问 DOM 也应该缓存已经访问过的元素。
采取适当的资源引用方式
使用外链的 JavaScript 和 CSS 文件可以使这些文件被浏览器缓存,从而在不同的请求内容之间重用,同时也减小了网页内容的大小。
不过,使用外链的决定因素在于这些外部文件的重用率,如果用户在浏览网站时会访问多次相同页面或者可以重用脚本的不同页面,那么外链形式可以带来很大的好处。但对于用户通常只会访问一次的页面,那么 inline 的方式相对来说可以提供更高的效率。
JavaScript 优化
- 把 JavaScript 置底,这样可以让网页渲染所需要的内容尽快加载显示给用户。
- 主流浏览器都支持 defer 属性,可以指定脚本在文档加载后执行。
- HTML5 中新加了 async 关键字,可以让脚本异步执行。
减少 CSS 表达式
CSS 表达式的问题在于它被重新计算的次数远比想象的要多,不仅在网页绘制或大小改变时计算,即使滚动屏幕或者移动鼠标的时候也在计算,所以尽量避免使用它来防止使用不当而造成的性能损耗。如果想达到类似的效果可以通过简单的 JavaScript 做到。
避免空的图片 src
空的图片 src 仍然会使浏览器发送请求到服务器,这样完全是浪费时间,而且浪费服务器的资源。
不要在 HTML 中缩放图片
不要通过缩放图片来适应页面。如果需要小图片,就直接使用小图片。不要加载大图片再缩放成小图片。
使用小且可缓存的 favicon.ico
网站图标文件 favicon.ico,不管服务器有还是没有,浏览器都会去尝试请求这个图标。所以要确保这个图标存在。文件要尽量小,最好小于 1k,同时设置一个长的过期时间。
减少 iframe 数量
使用 iframe 要注意理解 iframe 的优缺点:
优点:
- 可以用来加载速度较慢的内容,例如广告。
- 安全沙箱保护。浏览器会对 iframe 中的内容进行安全控制。
- 脚本可以并行下载。
缺点:
- 即使 iframe 内容为空也会消耗加载时间。
- 会阻止页面加载。
延迟加载、提前加载
延迟加载是基于我们知道网页最初加载需要的最小内容集是什么,剩下的内容就可以加入延迟加载的集合中。JavaScript 是典型的可以延迟加载的内容。
提前加载则是为了提前加载接下来网页中访问的资源。
减少 302 和 404
有时 302 的重定向是多种因素导致的,比如说服务转移、业务需要。但是从用户角度考虑,一次请求之后的多次页面跳转会带来更多的等待时间,这种等待会覆盖我们在技术层面的种种优化尝试。同理, 404 的错误也应该尽量避免。