1

浏览器缓存技术是提升前端性能一个非常重要的手段。在当前浏览器各方面性能都大幅提升的情况下,前端性能的瓶颈更多的集中在资源请求方面。

原理

说浏览器缓存,其实就是在说:

  • 浏览器实现缓存的机制

  • HTTP通讯协议定义的关于缓存的字段内容

先让我们回顾下,当我们在浏览器的地址栏输入URL之后发生哪些过程:

  1. DNS服务器解析域名,找到对应服务器的IP地址;

  2. 和服务器建立TCP连接;

  3. 基于TCP连接进行HTTP的Req/Res,服务器会根据HTTP请求到数据服务器取出相应的资源,并返回给前端;

  4. 浏览器获取HTML文档,并开始解析

  5. 遇到link标签,加载href指向的地址,并解析css,遇到带有src属性,且没有声明async或defer属性的script标签时,同步加载远程js脚本,同步解析js脚本,同步执行js脚本,浏览器的GUI渲染过程处于挂起状态。当js执行完毕后,继续后面的HTML解析的工作;

  6. DOM树构建完毕,CSS Rules解析完毕;

  7. DOM树CSS Rules一起构建Render树。和DOM树不一样的地方在于Render树是带有DOM样式的,伪元素不会在DOM树中出现,而会在Render树中出现。

  8. Render树构建完毕后开始repaintreflow过程,即渲染。最后将页面呈现给用户。

在这些过程当中:

  • 过程1:远程服务器可能是代理服务器,代理服务器可进行缓存匹配,可将缓存的资源直接返回给前端,降低对于源服务器的压力,同时还能做均衡负载;

  • 过程3:数据服务器可以进行memcached,进行数据库层面的缓存,可将上一次的查询结果缓存到内存当中,下次再查询相同的数据时,直接从内容从取出数据;

  • 过程5:可以利用浏览器缓存。这也是本文所讲的主要内容。

当我访问 SegmentFault 的个人主页时:

图片描述

在浏览器首次加载并解析HTML文档时,会维护一个资源的缓存池缓存池里存放了加载的包括css,js,图片,字体等文件,URL是这些资源的唯一标识。浏览器会根据HTTP响应字段来决定这些资源是否能缓存以及缓存的时间等:

  1. Expires字段设置了资源过期的时间。

  2. Cache-control字段的内容较多,例如no-cache会决定资源不会缓存;max-age指客户机可以接收生存期不大于指定时间(以秒为单位)的响应。具体的内容(图)

  3. Etag:资源的唯一标识符

  4. Last-Modified: 资源最后一次修改的时间

如果将页面刷新,此时加载同一份HTML文件,同样遇到外联的css,js,图片和字体等文件。此时浏览器首先会从缓存池中寻找,寻找的标记为资源的URL地址。

图片描述

如果缓存池中有对应的资源,通过查询Expires字段Cache-control字段的值,如果没有过期,那么会从缓存池中获取资源,不会进行HTTP请求。

若资源过期,则会进行HTTP请求,此时浏览器会检查缓存池中资源是否具有EtagLast-modified.如果有Etag字段(资源的唯一标识符,只要发生修改,其值都会发生改变)的内容,那么HTTP请求中会带上If-none-match字段,其值为Etag字段的内容,如果有Last-Modified字段(最后一次修改的时间),那么HTTP请求会带上If-Modified-Since字段,其值为Last-modified字段的内容。服务器根据HTTP请求去匹配If-none-matchIf-Modified-Since的内容。

If-none-match的内容匹配不成功时,服务器会返回状态码为200 success的响应及所有的资源内容,并设置新的和缓存相关的字段内容,若匹配成功返回304 Not Modify响应状态,但是不会返回资源内容。此时浏览器仍然是从资源池中获取资源。

If-Modified-Since的处理方式和If-none-match相同。

当以上2个字段在HTTP请求中都存在时,会优先匹配If-None-Match的内容,只有相同的情况下才会去匹配If-Modified-Since的内容,来绝对是返回200还是304。

总结

页面首次加载

初次加载

页面刷新

页面刷新

实践

之前在实习的过程中,对于浏览器缓存所做的工作之一就是每次在发版前通过gulp给资源打上版本号,例如:

"/css/style.css" => "/dist/css/style.css?v=1d87bebe";
"/js/script1.js" => "/dist/script1.js?v=61e0be79";

这样再去首页去加载这些资源的时候,因为在资源池里找不到对应的URL,因此会发送HTTP请求,从服务器端获取最新的资源。 具体实践过程请自行google

参考资料

  1. 浏览器缓存机制

  2. 《webkit技术内幕》

  3. HTTP Cache

  4. Google Develop Http Caching


苹果小萝卜
5.1k 声望356 粉丝

Github: [链接]


引用和评论

0 条评论