【GISER&&前端优化】前端缓存的几种主流选择

  这周遇到了一个新需求,产品反馈地图瓦片服务的图片资源没有Http缓存,每次移动地图范围都会向后台发处请求/响应数据,影响了客户端的地图加载体验。所以需要增加这样一种缓存:1)针对同一个请求资源地址URL,首次加载需要缓存数据,后续加载直接读取缓存;2)后台数据发生更新时,需要实时更新缓存;
  在完成这个需求之前,我借机补习了一下前端的缓存体系:

一  HTTP缓存
  提起前端缓存,首先第一反应就是浏览器自带的缓存机制,通过在Http报文头部中设置一些属性字段,告知浏览器对本次请求响应的资源进行缓存,之后对于相同URL的资源请求则直接从缓存中读取。这个思路没错,那具体应该如何实现呢?这就需要我们对这些属性进行简单介绍一下:

  1  强缓存
   首次请求资源A设置缓存,再次请求资源A时直接查找缓存,如果缓存命中,则不发送新的请求;否则发送新请求;
   控制强缓存的主要属性字段:
    【Expire】:HTTP1.0标准下的字段,指定一个日期或时间,在时间过期前执行上述逻辑,时间过期后重新执行
    【Cache-Control】:
      field description
      private 仅客户端缓存
      public 客户端和代理服务器缓存
      max-age=xxx 缓存内容将在xxx秒后失效(相对请求时间)
      s-max-age 仅适用于public共享缓存
      no-cache 需要使用协商缓存来验证缓存(会发送新的请求)
      no-store 所有内容都不缓存
      must-revalidate

  2 协商缓存
  顾名思义,由服务端协助客户端实现缓存机制:即在资源B已缓存的前提下,再次请求资源B时,会继续想服务器端发送请求,通过服务器发送请求,获取资源B是否失效的信息,如果未失效,返回未失效Flag告知前端,从而在缓存中获取资源B,如果失效,则返回新的数据和报文缓存头设置;
常用的协商缓存包括:
  【Cache-Control的must-revalidate】:标识每次必须向服务端请求验证资源

  【Etag】-【if-none-match】:资源的唯一标识,即在第一次请求资源C时,会计算一个能够唯一标识当前资源C的tag值,并放在response的Etag属性字段中,当资源C缓存在前端后,后续的每一次请求资源C都会将tag值设置在请求request的if-none-match中,服务端根据tag值进行判断当前请求资源C是否发生变化,如变化这表示缓存未命中,返回新的资源C,否则返回缓存命中标识,直接返回304获取资源C在前端的缓存。

  【last-modified】-【if-modified-since】:同上Etag,只不过此处一般以时间戳作为判断依据,服务端则需要获取资源C的文件最后修改时间(这个在JAVA中File提供了getLastModified方法),并将时间戳赋值给response中的last-modified属性字段,后续的每一次请求会将时间戳放在if-modified-since中,与后台的新时间戳对比,如果时间戳不同,则表示缓存未命中,返回新的资源C,否则返回缓存命中标识,前端获取缓存值;

  3 实现
  OK,梳理完上述的Http缓存机制后,我们很容易发现如果要满足需求(即客户端缓存数据,且能够在数据发生变化后请求返回新的数据,更新缓存),应当选择协商缓存。
策略选择好之后,实现还是比较简单的,我们这里以时间戳为例:
  3.1)  后台在返回数据时增加时间戳判断:

Public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
//......
  String filePath = ""; //
  File fileC = new File(filePath);
  long lastNew = fileC.lastModified();
  String lastNewStr = Long.toString(lastNew); //获取当前资源的最后修改时间
  String lastOldStr = request.getHeader("if-modified-since"); //获取当前资源缓存的最后修改时间

  if(lastNewStr.equalsIgnoreCase(lastOldStr)){
    Response.setStatus(304); //返回304 not modified
  }else{
  //获取新的数据
  }
// ......
}

  3.2) 验证效果
  效果比较尴尬,因为在实现了这类缓存后,请求响应资源的效率提高并不明显,虽然实现了缓存,但是每次资源校验依然要经过一次完整的请求响应过程,其中的连接开销应该是耗时的主要部分,而非数据的传输。所以,只能临时更改策略,采用期限强缓存,后台如果更新数据,则需要客户端手动刷新缓存。

  实现方法如下,采用Cache-Control的max-age,以一天时间为缓存期限:

Public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
  //…
  response.setHeader("Cache-Control", "max-age=86400");
  //…
}

二  前端数据库缓存
  在完成这个任务后,我突然想起来之前在完成矢量地图渲染时,为了提高前端中文字体加载效率,曾经使用过前端数据库indexDB作为缓存技术,这个和Http缓存又有什么不同呢?一般来说,前端数据库主要有一下几种:
  1 cookie
  常用场景:用户个人信息保存(用户名/密码)
  存在问题:
    容量:4KB
    数据安全问题

  2 localStorage/sessionStorage【键值对】:本地浏览器数据库,根据浏览器不同,缓存容量不同,一般5MB左右,适合存储一些常用结构简单的数据;
    localStorage.setItem("key", "value")
    localStorage.getItem("key")
    localStorage.removeItem("key")
    localStorage.clear()
  优势场景:
    兼容性好,易操作
  缺点:
    容量小,每个域名分配3-5M空间

  3 indexedDB【结构化对象】:本地数据库存储,使用索引高效检索,异步处理;
  优势场景:
    a 异步操作,可大量读写数据而不阻塞浏览器主线程
    b 支持事务
    c 存储空间大(250MB->更多)
    d 支持二进制存储ArrayBuffer和Blob
  缺点:
    操作比较繁琐复杂,不如localStorage方便
  实现:
    var databaseName = "test"
    var version = "20191121"
    var request = window.indexedDB.open(databaseName, version) //创建一个indexedDB数据库
  具体操作略微有些复杂,需要熟悉相关API接口,此处就不作详细介绍了,具体可以参照阮一峰的教程;

三  比较
  比较Http缓存和前端数据库缓存,暂时没有发现这些缓存有什么明显的差异,只是针对应用场景不同而已:
  1)Http缓存一般能够缓存一些前端请求的一些公共资源,减少一些不必要的请求响应开销,提高web端的体验
  2)而前端数据库缓存则能够缓存一些高频常用的业务数据,提高业务请求的数据返回速度,比如高德地图和百度地图: 【高德地图】:打开Chrome控制台的Application选项卡,可以查看IndexedDB中的数据,其中包含了road/region等矢量瓦片数据;  【百度地图】:打开IndexedDB空空如也,但是在LocalStorage中发现了一些POI搜索记录;并且百度地图的矢量数据服务利用了Cache-Control属性强缓存了矢量数据,从而减小实时的数据请求。

原文地址:https://www.cnblogs.com/escage/p/11907269.html

时间: 2024-10-07 22:02:28

【GISER&&前端优化】前端缓存的几种主流选择的相关文章

前端优化代码主要的几种方式!

一.减少HTTP请求 1.合并CSS.js:每次调用js.css都要发送一次http请求,所以并不是分开写好几个文件比较好 js.css压缩.js压缩可以用grunt HTML优化: 使用语义化标签 减少iframe:iframe是SEO的大忌,iframe有好处也有弊端 避免重定向 CSS优化: 删除空样式 不滥用浮动,字体,需要加载的网络字体根据网站需求再添加 选择器性能优化 避免使用表达式,避免用id写样式 js优化: 压缩 减少重复代码 2.图片优化 图片合并,CSS sprite技术

【转】关于大型网站技术演进的思考(二十一)--网站静态化处理—web前端优化—下【终篇】(13)

本篇继续web前端优化的讨论,开始我先讲个我所知道的一个故事,有家大型的企业顺应时代发展的潮流开始投身于互联网行业了,它们为此专门设立了一个事业部,不过该企业把这个事业部里的人事成本,系统运维成本特别是硬件采购的成本都由总公司来承担,当然互联网业务上的市场营销成本这块还是由该事业部自己承担,可是网站一年运维下来,该公司发现该事业部里最大的成本居然不是市场营销的开销,而是短信业务和宽带使用上的开销,是不是有点让人感到意外呢?下面我来分析下这个场景吧. 短信这块是和通讯运营商有关,很难从根本上解决,

关于大型网站技术演进的思考(二十一)--网站静态化处理—web前端优化—下【终篇】(13)

本篇继续web前端优化的讨论,开始我先讲个我所知道的一个故事,有家大型的企业顺应时代发展的潮流开始投身于互联网行业了,它们为此专门设立了一个事业部,不过该企业把这个事业部里的人事成本,系统运维成本特别是硬件采购的成本都由总公司来承担,当然互联网业务上的市场营销成本这块还是由该事业部自己承担,可是网站一年运维下来,该公司发现该事业部里最大的成本居然不是市场营销的开销,而是短信业务和宽带使用上的开销,是不是有点让人感到意外呢?下面我来分析下这个场景吧. 短信这块是和通讯运营商有关,很难从根本上解决,

【转】yahoo前端优化军规

雅虎给出了前端优化的34条法则(包括Yslow规则22条) 详细说明,下载转发 ponytail 的译文(来自帕兰映像). Minimize HTTP Requests 减少http请求 图片.css.script.flash等等这些都会增加http请求数,减少这些元素的数量就能减少响应时间. 把多个JS.CSS在可能的情况下写进一个文件,页面里直接写入图片也是不好的做法,应该写进CSS里,利用 CSS sprites 将小图拼合后利用background来定位. Use a Content D

Web前端优化最佳实践及工具集锦

前端的性能对于一个Web应用来说非常重要,如果一个Web应用的页面加载速度非常快.对于用户的操作可以及时响应,那么产品的用户体验将会极大地提升.下图显示了页面加载速度对于用户体验的影响. 你的Web页面的速度是否已经足够快了?其实可能还有很多可以提升的地方.Google和雅虎也提出了一些Web应用的前端优化建议,并发布了一些工具,你可以逐一检验你的Web应用,以便达到更高的性能. 这些优化不仅仅可以给用户提供更好的体验,从开发者角度来说,进行优化还可以减少页面的请求数.降低请求所占的带宽.减少资

【前端优化之拆分CSS】前端三剑客的分分合合

几年前,我们这样写前端代码: <div id="el" style="......" onclick="......">测试</div> 慢慢的,我们发现这样做的很多弊端,单就样式一块,改一个样式会涉及到多处调整,所以慢慢的dom标签中的css全部去了一个独立的css文件 再后来,交互变得异常复杂,onclick也不好使了,所以js也分离开了,经典的html+css+javascript结构分离逐步清晰,三种代码各司其职

web 前端优化-戈多编程

大家好,我是戈多,从事web开发工作接近三年了,今天来归纳下web前端优化的解决方案(码农搬砖工,来自各网络汇总) 1.减少Http请求 http请求越多,那么消耗的时间越多,如果在加上网络很糟糕,那么问题就更多了.且如果网页中的图片.css文件.js文件很多甚至有音乐文件时,这势必会造成负担. (1)图片地图 即多个图片排成一行作为链接到其他页面的按钮,我们当然可以使用五福图片,发送5个http请求,但是这是不合适的. 我们可以选择使用图片地图,即只用一张图片,然后使用<map>属性通过控制

前端优化的问题

转自--- 影响用户访问的最大部分是前端的页面.网站的划分一般为二:前端和后台.我们可以理解成后台是用来实现网站的功能的,比如:实现用户注册,用户能够为文章发表评论等等.而前端呢?其实应该是属于功能的表现. 而我们建设网站的目的是什么呢?不就是为了让目标人群来访问吗?所以我们可以理解成前端才是真正和用户接触的. 除了后台需要在性能上做优化外,其实前端的页面更需要在性能优化上下功夫,只有这样才能给我们的用户带来更好的用户体验.不仅仅如此,如果前端优化得好,他不仅可以为企业节约成本,他还能给用户带来

前端优化带来的思考,浅谈前端工程化

重复优化的思考 这段时间对项目做了一次整体的优化,全站有了20%左右的提升(本来载入速度已经1.2S左右了,优化度很低),算一算已经做了四轮的全站性能优化了,回顾几次的优化手段,基本上几个字就能说清楚: 传输层面:减少请求数,降低请求量执行层面:减少重绘&回流 传输层面的从来都是优化的核心点,而这个层面的优化要对浏览器有一个基本的认识,比如: ① 网页自上而下的解析渲染,边解析边渲染,页面内CSS文件会阻塞渲染,异步CSS文件会导致回流 ② 浏览器在document下载结束会检测静态资源,新开线