ntscshen / ntscshen.github.io

个人博客
0 stars 2 forks source link

JS经典interview(四) - http资源缓存 #5

Open ntscshen opened 7 years ago

ntscshen commented 7 years ago

http资源缓存策略

强制缓存和协商缓存

Cache-Control ( 强缓存 )

  1. HTTP1.1中的定义:Cache-Control: max-age=315360000 这意味着该资源从原服务器上取得后,缓存的( 新鲜度 )有效期为一小时,在后续一小时内,用户重新访问该资源则无需发送请求
  2. HTTP1.0中的定义:Expires: Sun, 21 Mar 2027 08:40:01 GMT
    // 强制缓存
    res.setHeader('Expires', new Date(Date.now() + 315360000).toUTCString()); // http1.0
    res.setHeader('Cache-control', 'max-age=315360000'); // http1.1

    Etag && if-none-match( 协商缓存1 )

  3. Etag优先级大于Last-Modified。
  4. 和Last-Modified一样,对文件进行标识。不同的是,Etag的取值是一个队文件进行标识的特征字串。在向服务器查询文件是否有更新时,浏览器通过 If-None-Match 字段把特征字串发送給服务器,由服务器和文件最新特征进行匹配,来判断文件是否有更新。 Etag和Last-Modified 可以根据需求使用一个或者两个同时使用。两个同时使用时,只要满足其中一个条件,就认为文件没有更新
    // ...
    let ss = fs.createReadStream('./index.html');// 读
    let md5 = crypto.createHash('md5');// 加密
    ss.on('data', function(data) {
    md5.update(data);
    });
    ss.on('end', function() {
    let value = md5.digest('hex');
    let head = req.headers['if-none-match'];
    if( head === value ){
    res.statusCode = 304;
    res.end();
    } else {
    res.setHeader('Etag', value);
    fs.createReadStream(path.join(__dirname, pathname)).pipe(res);
    }
    })
    // ...

    Last-Modified && if-Modified-Since( 协商缓存2 )

    它标志资源的最后修改时间,服务器在响应中带回一个 Last-Modified 的头部,告诉浏览器该资源的最后修改时间。 当第二次请求此URL时,浏览器会向服务器发送 If-Modified-Since 请求头,服务器根据该字段的值进行一定的逻辑处理 1、如果资源没变,则返回304告知浏览器直接使用缓存 2、如果资源变更,则返回最新资源,并且响应码为200,同时更新 Last-Modified 字段( 一个全新的请求 )。

ntscshen commented 7 years ago

Cache-Control:控制缓存有效时间 Last-Modified:缓存失效后,向服务器查询是否有更新

一般是配合使用 Cache-ControlLast-Modified 的前置判断, 在第一次请求页面的时候,会通过 Cache-Control 的指示缓存资源,同时设置资源的 Last-Modified。 当再一次请求页面资源时,根据 Cache-Control: max-age=xxx 指定的时间,在这个时间期间内,每次向服务器获取资源时,都会直接获取缓存内容,并且响应码为 200 Ok ( from disk cache )。 若资源过期,则会向服务器发起请求,此时请求中会带上 If-Modefied-Since 请求头, 服务器根据该字段的值进行一定的逻辑处理 1、如果资源没变,则返回304告知浏览器直接使用缓存 2、如果资源变更,则返回最新资源,并且响应码为200,同时更新 Last-Modified 、 Cache-Control字段( 一个全新的请求 )。

ntscshen commented 7 years ago
Etag

和Last-Modified一样,对文件进行标识。不同的是,Etag的取值是一个队文件进行标识的特征字串。在向服务器查询文件是否有更新时,浏览器通过 If-None-Match 字段把特征字串发送給服务器,由服务器和文件最新特征进行匹配,来判断文件是否有更新。 Etag和Last-Modified 可以根据需求使用一个或者两个同时使用。两个同时使用时,只要满足其中一个条件,就认为文件没有更新

ntscshen commented 7 years ago

已经缓存了,那么该如何更新( 现代互联网企业,会把静态资源和动态网页分集群部署,静态资源会被部署到CDN节点上,网页中引用的资源也会变成对应的部署路径 )

在资源内容更改后,更改动态网页中的静态资源网址,强制用户下载新的响应 这真是一个伤感的话题,上家公司每次更新都是人肉修改的链接

这种办法有一个更好听的名字叫做 - "消灭304"

在实际应用中,为了解决 Cache-Control 缓存时长不好设置,已经"消灭304",Web端常常采用的方式是

  1. 把在需要缓存的资源设置 Cache-Control:max-age= 31536000 , 正常情况是设置成一年。在一年内,使用本地缓存; 那问题来了,你不让浏览器发资源请求,这缓存怎么更新呐?
  2. 通过更新页面中引用的资源路径( MD5 ),让浏览器主动放弃缓存,加载新资源
  3. 至于如何替换DM5的静态资源路径 - 使用构建工具 webpack 资源修改变更过文件名

这块属于静态资源优化

  1. 配置超长事件的本地缓存 - 节省带宽,提高性能
  2. 内容变更才改变对应的文件名 - 精准控制变更的缓存
  3. 静态资源部署CND - 优化网络请求
  4. 更新资源发布路径 实现非覆盖式发布 - 平滑升级
ntscshen commented 7 years ago

浏览器缓存分类

Read more

你应该知道的浏览器缓存知识 大公司里怎样开发和部署前端代码? 浏览器缓存浅析