聊聊Http 缓存机制

Http 缓存机制

Q:前端为什么要去了解http缓存机制呢?

  • 在偏C端的业务系统中,往往对于软件的性能要求会更高一些,软件的易用性,响应速度,首屏打开速度都会影响用户的体验感
  • 所以项目经理,产品经理都会对这个方面有较高的要求,更快的速度,更好的性能代表了更多的money
  • 而很多可以优化的地方都要前端工程师对于http缓存机制有更加深刻认识和了解

Q:缓存机制只有http缓存么?使用它有啥好处?

答案是否定的,缓存机制到处都存在,为了提高性能,有客户端缓存,服务端缓存,代理服务器缓存等

但是对于我们前端而言,http缓存是我们前端可以接触到并实际使用的web性能优化手段

(1)减少网络带宽消耗

无论对于网站运营者或者用户,带宽都代表着金钱,过多的带宽消耗,只会便宜了网络运营商。当Web缓存副本被使用时,只会产生极小的网络流量,可以有效的降低运营成本。

(2)降低服务器压力

给网络资源设定有效期之后,用户可以重复使用本地的缓存,减少对源服务器的请求,间接降低服务器的压力。

(3)减少网络延迟,加快页面打开速度

答案是肯定的,对于最终用户,缓存的使用能够明显加快页面打开速度,达到更好的体验。

Q:http缓存机制有哪几种类型?

强制缓存
  • 命中缓存

    • 请求数据的时候命中缓存了(有缓存,且未失效),就直接从缓存中拿数据,不用与服务器进行交互
  • 没有命中缓存

    • 请求数据的时候没有命中(无缓存或者失效),就会向服务端发送请求,然后讲服务端返回的数据及缓存规则写入缓存
  • 使用场景

    • 持久性资源数据,可以使用该策略
  • status为灰色的是强制缓存,分为两种from memory cache 和 from disk cache,浏览器会优先读取内存中的数据

    • from memory cache
      • 存在于内存中
      • 读取速度相对更快
      • 进程关闭就会清空(关闭标签页就会清空)
      • 一般存储js文件及图片资源
    • from disk cache
      • 存在于硬盘当中
      • 读取速度相对较慢
      • 进程关闭也不会清空
      • 一般存储css文件
  • 配置参数

    • Expires
      • 这个参数的配置属于http1.0的参数
      • 值是一个时间绝对值(小于这个时间都会使用强制缓存)
    • Cache-Control
      • 这个参数的配置属于http1.1的参数
      • 值为几种情况
        • public:所有内容都将被缓存(客户端和代理服务器都可缓存)
        • private:所有内容只有客户端可以缓存,Cache-Control的默认取值
        • no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
        • no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
        • max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效
    • 如果两个参数都存在的话,Cache-Control 优先级大于Expires

协商缓存
  • 强制缓存失效后,浏览器携带缓存标识(一般为(Last-Modified / If-Modified-Since和Etag / If-None-Match))向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
  • 协商缓存生效
    • 服务器判断资源未更新,就会返回304状态码,客户端直接使用之前的缓存数据
  • 协商缓存不生效
    • 服务器判断资源更新,就会从数据库获取最新的数据,返回200状态码,客户端使用最新的数据并更新缓存
  • Last-Modified / If-Modified-Since
    • 值为一个标准时间,服务器会根据这个时间去比对资源
    • 消耗性能小
    • 精度只能到秒(密集请求可能会存在问题)
  • Etag / If-None-Match
    • 一个唯一的hash值,服务器会比较这个hash值是否一致
    • 性能消耗较大
    • 精度高,一般会优先考虑这个
用户行为对浏览器缓存的控制
  1. 地址栏访问,链接跳转是正常用户行为,将会触发浏览器缓存机制;
  2. F5刷新,浏览器会设置max-age=0,跳过强缓存判断,会进行协商缓存判断;
  3. ctrl+F5刷新,跳过强缓存和协商缓存,直接从服务器拉取资源。

实践

  1. 是否缓存依赖于接口响应头里面设置的参数(其实对于前端来说,操作有限,了解可以针对一些特定场景来解决问题)

  2. 下面是一个使用Nginx作为Web服务器的缓存配置

    location / {   
    	# 其它配置  ...   
    	if ($request_uri ~* .*[.](js|css|map|jpg|png|svg|ico)$) {    
    		#非html缓存1个月    
    		add_header Cache-Control "public, max-age=2592000";  
    	}   
    	if ($request_filename ~* ^.*[.](html|htm)$) {
    		#html文件使用协商缓存    
    		add_header Cache-Control "no-cache";  
    	} 
    
  3. 配合webpack打包 contenthash的方案

    hash 计算与整个项目的构建相关;

    chunkhash 计算与同一 chunk 内容相关;(js和css在同一个chunk)

    contenthash 计算与文件内容本身相关.(文件内容发生改变,contenthash就会改变)

    module.exports = {
      output: {
        // 文件hash
        filename: '[name].[contenthash].js',
      },
      optimization: {
        moduleIds: 'deterministic',//避免因为模块解析顺序发生变化而导致文件 hash 值改变
        // runtime 单独打包为一个 chunk
        runtimeChunk: 'single',
        splitChunks: {
          cacheGroups: {
            // 第三方包打包为 vendors chunk,因为很少修改,有利长期缓存
            vendor: {
              test: /[\\/]node_modules[\\/]/,
              name: 'vendors',
              chunks: 'all',
            },
          },
        },
      },
    };
    
  4. 大厂的解决方案(B站)

    1. html:no-cache
    2. JS文件:max-age=31536000(1年),文件命名带版本号或指纹信息,方便及时更新。
    3. CSS文件:max-age=31536000,文件命名带版本号或指纹信息,方便及时更新。
    4. 图片:max-age=31536000,文件命名带版本号或指纹信息,方便及时更新。
    5. XHR请求: no-cache

总结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jjedp6jd-1656411814643)(C:\Users\xiaziwei\AppData\Roaming\Typora\typora-user-images\image-20220627174947855.png)]

注意点

  1. 缓存只能针对于get请求,对于post等对于数据库操作的请求类型是不支持的
  2. 缓存配置在响应体里,前端如果不涉及到后端的话,操作空间有限,只能与后端沟通哪些接口或者资源可以做缓存处理
  3. 缓存的目的是为了提供更好的体验和降低服务器压力,提高缓存命中率的同时,一定要保证数据的新鲜度
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值