028-86261949

当前位置:首页 > 技术交流 > 浏览器缓存策略

浏览器缓存策略

2019/12/12 14:58 分类: 技术交流 浏览:0

 

在前端的性能优化中,缓存可以说是性能优化中简单高效的一种优化方式了。缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷,今天就来聊一聊浏览器的缓存策略,下图是一个浏览器发送请求获取资源的图示:

 

其中用到的缓存机制分为强缓存和协商缓存:

 

 

强缓存

可以再Html中通过meta标签设置,例如<meta http-equiv=”cache-control” content=”no-cache, must-revalidate”> 

 

cache-control可以设置为4个值

 

1. cache-control: max-age=xxxx,public

指的是发送的http请求返回内容所经过的任何路径当中,包括一些中间的http的代理服务器,以及发出这个请求的客户端浏览器,都可以进行对于返回内容的缓存的操作,缓存操作指的就是把这份内容缓存在本地,max-age=xxx,指的是下一次请求在xxx秒时间内可以直接读缓存去使用。

 

2. cache-control: max-age=xxxx,private

       指的是只有发起求情的浏览器才能够进行缓存,代理服务器不能缓存

 

3. cache-control: max-age=xxxx,immutable

客户端在xxx秒的有效期内,如果有请求该资源的需求的话就直接读取缓存,即使用户做了刷新操作,也不向服务器发起http请求。

 

4. cache-control: no-cache

       指的是任何节点都不能进行缓存,包括浏览器和代理服务器。

 

5. cache-control: no-store

要和no-cache做一个区分,no-cache是可以在本地进行缓存的,也可以在代理服务器进行缓存,但每次发起请求都要去服务器那边做验证,如果服务器返回告诉可以用本地的缓存,然后请求方才能去使用缓存。no-store指本地和代理服务器都不可以缓存,打个不恰当的比方,即使告诉浏览器可以使用缓存,浏览器本地也没有缓存。

 

协商缓存

上面说到的强缓存就是给资源设置个过期时间,客户端每次请求资源时都会看是否过期;只有在过期才会去询问服务器。所以,强缓存就是为了给客户端自给自足用的。而当某天,客户端请求该资源时发现其过期了,这是就会去请求服务器了,而这时候去请求服务器的这过程就可以设置协商缓存。这时候,协商缓存就是需要客户端和服务器两端进行交互的。

 

       协商缓存可以在response header里面的设置,分为Last-Modifiled和Etg 两种:

Last-Modifiled:

Last-Modifiled,上次修改时间,配合If-Modified-Since或者If-Unmodified-Since使用;我们请求一个资源,请求的资源返回了Last-Modifield头信息,指定了一个时间,这个时间在下一次浏览器发起请求的时候就会带上Last-Modifield传过来的值,比如值为val,那么浏览器会设置头信息If-Modified-Since或者If-Unmodified-Since,一般浏览器都是使用If-Modified-Since,If-Unmodified-Since很少会被用到,头信息的值就是val,服务器可以通过读取request的头信息,找到资源存在的地方,找到其修改的时间,如果发现这两个时间是一致的,代表该资源未被修改过,然后就告诉浏览器可以使用缓存的资源,如果不一致,就返回新的资源。

 

Etg:

Etg是一种更加严格的验证,通过数据签名 ,配合If-Match或者If-Non-Match使用,我们的资源,也就是内容会产生一个唯一的签名,如果资源的数据进行过修改,那么签名就会产生一个新的,最典型的做法就是会对资源的内容进行一个hash计算得到一个唯一值。也就是浏览器在请求一个资源的时候响应头会返回该资源的签名值,下次浏览器去请求的时候会带上头信息If-Match或者If-Non-Match,服务器收到后会和现在该资源的签名去做对比,如果一致,就不需要返回新的内容。下面通过node的一段代码简单了解:

const http = require('http');

const fs = require('fs');

 

 

const http = require('http');

const fs = require('fs');

 

http.createServer(function (requestresponse) {

    console.log('request come',request.url);

 

    if(request.url == '/'){

        const html = fs.readFileSync('test.html','utf-8');

        response.writeHead(200,{

            'Content-Type':'text/html'

        });

        response.end(html);

    }

    if(request.url == '/script.js'){

        const etag = request.headers['if-none-match'];

        if(etag === '777'){

            /**

             * 1.当写入头为304的时候,即使我们把Etag的值改变了,浏览器也不会重新拿到新资源,

             * 也不会更新响应头返回的Etag的新值,所以下次请求的时候用的还是老的Etag的值。

             * 2.当设置Cache-Control的值no-cache时候,如果响应头返回了Last-ModifiedEtag的值,

             * 浏览器再次发送请求的时候会添加Last-ModifiedEtag的请求头;

             * 当设置Cache-Control的值no-cache时候,即使应头返回了Last-ModifiedEtag的值,

             * 浏览器再次发送请求也不会添加Last-ModifiedEtag的请求头;

             **/

            response.writeHead(304,{

                'Content-Type':'application/javascript',

                'Cache-Control':'max-age=2000000,no-store',

                'Last-Modified':'123',

                'Etag':'7778'

            });

            response.end('some word')

        }else{

            response.writeHead(200,{

                'Content-Type':'application/javascript',

                'Cache-Control':'max-age=2000000,no-store',

                'Last-Modified':'123',

                'Etag':'777'

            });

            response.end('console.log("script loaded twice")');

        }

    }

 

}).listen(8888);

 

console.log('service listening on 8888');

 

 

 

#标签:浏览器缓存策略,前端性能优化