前端开发性能优化

前端性能优化 – 资源预加载

当提到前端性能优化时,我们首先会联想到文件的合并、压缩,文件缓存和开启服务器端的 gzip 压缩等,这使得页面加载更快,用户可以尽快使用我们的 Web 应用来达到他们的目标。
资源预加载是另一个性能优化技术,我们可以使用该技术来预先告知浏览器某些资源可能在将来会被使用到。

引用 Patrick Hamann 的解释:

预加载是浏览器对将来可能被使用资源的一种暗示,一些资源可以在当前页面使用到,一些可能在将来的某些页面中被使用。作为开发人员,我们比浏览器更加了解我们的应用,所以我们可以对我们的核心资源使用该技术。
这种做法曾经被称为 prebrowsing,但这并不是一项单一的技术,可以细分为几个不同的技术:DNS-prefetch、subresource 和标准的 prefetch、preconnect、prerender。

DNS 预解析 DNS-Prefetch
通过 DNS 预解析来告诉浏览器未来我们可能从某个特定的 URL 获取资源,当浏览器真正使用到该域中的某个资源时就可以尽快地完成 DNS 解析。例如,我们将来可能从 example.com 获取图片或音频资源,那么可以在文档顶部的 标签中加入以下内容:

1 当我们从该 URL 请求一个资源时,就不再需要等待 DNS 的解析过程。该技术对使用第三方资源特别有用。

在 Harry Roberts 的文章中提到:

通过简单的一行代码就可以告知那些兼容的浏览器进行 DNS 预解析,这意味着当浏览器真正请求该域中的某个资源时,DNS 的解析就已经完成了。
这似乎是一个非常微小的性能优化,显得也并非那么重要,但事实并非如此 – Chrome 一直都做了类似的优化。当在浏览器的地址栏中输入 URL 的一小段时,Chrome 就自动完成了 DNS 预解析(甚至页面预渲染),从而为每个请求节省了至关重要的时间。

预连接 Preconnect

与 DNS 预解析类似,preconnect 不仅完成 DNS 预解析,同时还将进行 TCP 握手和建立传输层协议。可以这样使用:

1 在 Ilya Grigorik 的文章中有更详细的介绍:

现代浏览器都试着预测网站将来需要哪些连接,然后预先建立 socket 连接,从而消除昂贵的 DNS 查找、TCP 握手和 TLS 往返开销。然而,浏览器还不够聪明,并不能准确预测每个网站的所有预链接目标。好在,在 Firefox 39 和 Chrome 46 中我们可以使用 preconnect 告诉浏览器我们需要进行哪些预连接。
预获取 Prefetching

如果我们确定某个资源将来一定会被使用到,我们可以让浏览器预先请求该资源并放入浏览器缓存中。例如,一个图片和脚本或任何可以被浏览器缓存的资源:

1 与 DNS 预解析不同,预获取真正请求并下载了资源,并储存在缓存中。但预获取还依赖于一些条件,某些预获取可能会被浏览器忽略,例如从一个非常缓慢的网络中获取一个庞大的字体文件。并且,Firefox 只会在浏览器闲置时进行资源预获取。

在 Bram Stein 的帖子中说到,这对 webfonts 性能提升非常明显。目前,字体文件必须等到 DOM 和 CSS 构建完成之后才开始下载,使用预获取就可以轻松绕过该瓶颈。

注意:要测试资源的预获取有点困难,但在 Chrome 和 Firefox 的网络面板中都有资源预获取的记录。还需要记住,预获取的资源没有同源策略的限制。

Subresources

这是另一个预获取方式,这种方式指定的预获取资源具有最高的优先级,在所有 prefetch 项之前进行:

1 根据 Chrome 文档:

rel=prefetch 为将来的页面提供了一种低优先级的资源预加载方式,而 rel=subresource 为当前页面提供了一种高优先级的资源预加载。
所以,如果资源是当前页面必须的,或者资源需要尽快可用,那么最好使用 subresource 而不是 prefetch。

预渲染 Prerender

这是一个核武器,因为 prerender 可以预先加载文档的所有资源:

1 Steve Souders 在他的一篇文章中写到:

这类似于在一个隐藏的 tab 页中打开了某个链接 – 将下载所有资源、创建 DOM 结构、完成页面布局、应用 CSS 样式和执行 JavaScript 脚本等。当用户真正访问该链接时,隐藏的页面就切换为可见,使页面看起来就是瞬间加载完成一样。Google 搜索在其即时搜索页面中已经应用该技术多年了,微软也宣称将在 IE11 中支持该特性。
需要注意的是不要滥用该特性,当你知道用户一定会点击某个链接时才可以进行预渲染,否则浏览器将无条件地下载所有预渲染需要的资源。

更多相关讨论:

所有预加载技术都存在一个潜在的风险:对资源预测错误,而预加载的开销(抢占 CPU 资源,消耗电池,浪费带宽等)是高昂的,所以必须谨慎行事。虽然很难确定用户下一步将访问哪些资源,但高可信的场景确实存在:

如果用户完成一个带有明显结果的搜索,那么结果页面很可能会被加载
如果用户进入到登陆页面,那么登陆成功的页面很可能会被加载
如果用户阅读一个多页的文章或访问一个分页的结果集,那么下一页很可能会被加载
最后,使用 Page Visibility API 可以防止页面真正可见前被执行。

Preload

preload 是一个新规范,与 prefetch 不同(可能被忽略)的是,浏览器一定会预加载该资源:

1 虽然该规范还没有被所有浏览器兼容,但其背后的思想还是非常有意思的。

总结

预测用户下一步将访问哪些资源是困难的,需要进行大量的测试,但是这带来的性能提升是明显的。如果我们愿意尝试这些预获取技术,一定会显著提升用户的体验。

  1. 减少网络延迟与网络请求
    避免使用着陆页进行重定向。
    重定向会导致额外的HTTP请求,造成网络延迟,拖慢网页的呈现。重定向也可能造成额外的DNS查找,TCP握手和TLS协商。
    合并资源,减少网络请求
    合并资源,最常见的就是sprite精灵图了。
    此外,还可以合并一下 CSS 和 JS 代码。

  2. 控制资源下载数量
    访问一个网页时,所请求的资源一定要都是有用的,避免无用的资源请求,如:

  3. 多余的js文件,css文件

  4. 多余的图片请求

  5. 多余的字体请求

  6. 资源体积的优化
    网站用到的资源主要有:

文字类资源,如js, css 和 html;
图像类资源,各种图片
3.1 文字类资源的优化
首先当然是自己要写出优质、简洁的代码了。
其次,对于 js文件,html文件,css文件,要进行文件最小化处理,去除文字间的空格、换行,进行变量名的替换等等。
这些工作一般都是在前端工程打包时进行的, 如:

HTML 文件使用 HTMLMinifier;
CSS 文件在 Webpack 打包时,对 loader 配置minimize;
JS 文件使用UglifyJsPlugin 插件;
接下来就是使用GZIP对文件进行编码压缩了。
现代浏览器都可以接受 gzip 格式的文件,我们要做的就是对服务端进行配置。
3.2 图像类资源的优化
选择正确的图片格式
虽然经常说png 图片比 jpge 图片能更好的表现摄影图像,但是对于很多图片来说,png格式的图片,转化为 jpeg 格式后,对于图片的清晰度并没有特别大的影响,但是体积却能大大减少。
移除不必要的元数据
某些拍出来的照片会含有元数据,就是描述数据的数据。元数据会描述图片拍摄的设备信息,时间戳,图片尺寸等,这对于某些网页图片来说不是很重要,所以我们可以剔除掉这些元数据。
尝试下这个网站VerExif。
减小图片的尺寸
某些情况下,<img> 标签或标签的背景即使用了大图,其在实际网页中的尺寸也很小,这时使用大图就是造成资源的浪费了。这是可以对图片尺寸进行重设, 比如将1200 x 600 像素的图片改为 600 x 300 像素。
降低图片质量
在某些情况下,降低图片的质量并不会造成任何视觉上的差别,却能减少大量的体积。
有很多处理图片质量的软件,如:

XNConvert
ImageOptim
Resizelt
更多参考这里。

图片压缩
尽管对图片使用gzip压缩没什么效果,但是还是有很多软件可以在不影响图片尺寸和视觉质量的情况下,对图片进行压缩的,比如这个网站。
更多网站可以参考[这里](
http://enviragallery.com/9-be…。

  1. 使用HTTP缓存
    严格来说,这也算减少请求次数,但是实现方式是完全不一样的。
    使用HTTP缓存,是设置适当的缓存策略,从而可以避免浏览器重复地向服务端请求资源。
    HTTP缓存主要是服务端设置正确的响应头信息。
    缓存分为两种:强缓存 和协商缓存。

4.1 强缓存
强缓存是指浏览器直接使用存在本地的资源,而不再向服务端进行请求。涉及到的响应头有两个: Expires 和 Cache-control 。
Expires 是http 1.0的内容,其内容是服务端设置的一个具体的时间点, 如Expires: Wed, 21 Oct 2015 07:28:00 GMT, 无需过多了解。
Cache-control 是http 1.1 新增的头部,其值为下列指令之一或组合:

no-cache :表明浏览器可以对内容进行缓存,但是必须先向服务器确认,资源未改变的情况下,可以直接使用浏览器的缓存。与 no-store 互斥;
no-store : 表明内容不允许缓存,包括浏览器以及中间设备,如代理服务器等,与no-cache 互斥;
public : 表明缓存可以存在于浏览器和中间设备,与 private 互斥;
private :表明缓存只能存在于客户的浏览器中;
max-age: 以秒为单位的时间范围,表明经过多长时间之后,缓存内容将过期。过期之后,浏览器必须重新下载资源。
设置强缓存之后,浏览器每次请求就会使用本地缓存的内容或者根据返回的头部信息去浏览器验证。

4.2 协商缓存
当服务端对资源不设置强缓存时,可以使用协商缓存。开启协商缓存的方式有两种:

Last-Modified 与 If-Modified-Since;
Etag 与 If-None-Match;
两组头部信息的名字,都很语义化,降低了理解的难度。

4.2.1 Last-Modified 与 If-Modified-Since
服务端设置 Last-Modified 响应头, 表明资源最后修改的时间,这个值是一个时间点。浏览器请求时,会带上一个头信息 If-Modified-Since,其值为Last-Modified 的值。 服务器对比资源的上一次修改时间和 If-Modified-Since 所表示的时间,如果不曾改变,就返回304。

4.2.1 Etag 与 If-None-Match
服务端设置 Etag 响应头, 表明资源的的唯一标识字符串,只要资源被修改过,就会重新生成一个Etag。浏览器请求时,会带上一个头信息 If-None-Match,其值为Etag 的值。 服务器对比资源当前的Etag和 If-None-Match 的值,如果一致,就返回304。

文章出处:https://www.jianshu.com/p/4bb9eee3bd57

https://www.cnblogs.com/10manongit/p/12799757.html

猜你喜欢

转载自blog.csdn.net/weixin_39854011/article/details/111827027
今日推荐