韩国代理服务器地址头条:浏览器缓存库设计总结(localStorageindexedDB)

  新加坡是英语国家吗

  头条:浏览器缓存库设计总结(localStorage/indexedDB)

  大厂技术坚持周更精选好文前言浏览器缓存设计一直是web性能优化中非常重要的一个环节,也是SPA应用盛行的今天不得不考虑的问题.作为一名优秀的前端工程师,为了让我们的应用更流畅,用户体验更好,我们有必要做好浏览器缓存策略.

  每个Web应用体验都必须快速,对于渐进式 Web 应用更是如此。快速是指在屏幕上获取有意义内容所需的时间,要在不到 5 秒的时间内提供交互式体验。数据存储服务器并且,它必须真的很快。很难形容可靠的高性能有多重要。可以这样想: 本机应用的首次加载令人沮丧。已安装的渐进式 Web 应用必须能让用户获得可靠的性能。

  本文会介绍一些笔者曾经做过的Web性能优化方案以及浏览器缓存的基本流程,并会着重介绍如何利用浏览器缓存API封装适合自己团队的前端缓存库来极大地提高应用性能,并为公司省钱.

  你将收获熟悉浏览器缓存的基本过程Web性能优化基本方案以及缓存策略为公司带来的价值基于localStorage的缓存方案设计以及库的封装(vuex/redux数据持久化解决方案)基于indexedDB的缓存方案设计以及库的封装结合http请求库(axios/umi-request)进行更细粒度的缓存代理层设计正文1.浏览器缓存的基本过程

  首先要想设计一个优秀的缓存策略,一定要了解浏览器缓存的流程,接下来是笔者总结的一个基本的流程图:

  上图展示了一个基本的从浏览器请求到展示资源的过程,我们的缓存策略一部分可以从以上流程出发来做优化.我们都知道页面的缓存状态是由header决定的,下面具体介绍几个概念:

韩国代理服务器地址头条:浏览器缓存库设计总结(localStorageindexedDB)

  由服务端根据资源内容生成一段 hash 字符串,标识资源的状态,用户第一次请求时服务器会将ETag随着资源一起返回给浏览器, 再次请求时浏览器会将这串字符串传回服务器,韩国代理服务器地址验证资源是否已经修改,如果没有修改直接使用缓存.具体流程可以是如下情景:

  服务器端资源最后的修改时间,必须和 cache-control 共同使用,是检查服务器端资源是否更新的一种方式。当浏览器再次进行请求时,会向服务器传送 If-Modified-Since 报头,询问 Last-Modified 时间点之后资源是否被修改过。如果没有修改,则返回 304,使用缓存;如果修改过,则再次去服务器请求资源,返回200,重新请求资源。

  缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间,需要和 Last-modified 结合使用. Expires 是 Web 服务器响应消息头字段,在响应 http 请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。

  单位为秒,指定设置缓存最大的有效时间。当浏览器向服务器发送请求后,国外VPS在 max-age 这段时间里浏览器就不会再向服务器发送请求了。以上就是浏览器缓存几个基本的概念,更多知识可以在wiki中学习,这里就不一一介绍了.接下来我们具体看看如何优化web应用以及缓存策略给公司带来的价值.

  Web性能优化又是老生常谈的问题了,几年前就一直在探讨这个问题,笔者大致盘点一下性能优化的几个常用的方向:

  比如我们常用的gulp或者webpack这些打包工具, 可以帮我们压缩js,css,html代码,并且将不同页面模块的js,css打包合并到一个文件中,好处就是减少了http请求,降低了资源的体积,使得响应更快.但是仍然存在一个缺陷,就是合并代码会导致一次请求的资源体积会比之前分包的要大,所以会一定程度的影响页面渲染时间,所以这里需要做一个权衡,或者部分采用按需加载的方式.

  一个网站往往更占资源的是媒体文件,比如图片,视频,音频等,对于图片在发布到线上时最好是需求提前压缩一下, 为了减少图片请求几年前常用的做法是雪碧图,也就是几张图片合成一张大图,通过背景定位来显示不同的图片,不过目前貌似用的不多了,现在更多的采用字体图标,svg,或者webp,所以我们需要根据不同的场景使用不同的策略,当然目前主流的云平台支持对象存储,对媒体资源有不错的优化,有条件的可以采用这种方案,比如七牛云,阿里的对象存储oss.

  这个优化主要是为了提高页面渲染时间,我们都知道css和js的加载一般都是阻塞的, css不会阻塞js和外部脚本的加载,但是会阻塞js的执行, 如果我们把css放到body最底部,那么我们在网络不好的情况下可能会看到先展示html文本然后才渲染页面样式的窘境,如果我们把js脚本放到head内,那么将会阻塞后面内容的渲染,并且造成一些应dom还未生成的导致的错误, 虽然我们可以采用async、defer让script变成异步的,但是如果不同js文件有依赖关系,那么很可能导致意外的错误,所以我们的最佳实践往往是如下这种结构的:

  资源的懒加载可以极大的降低页面首屏时间, 我们不仅仅可以对图片采用懒加载, 即只给用户展示可视区域内的图片(虽然图片的懒加载意义更加重大),我们还可以对内容进行懒加载,本质上是一种特殊的分页技巧, jquery时代的lazyload是一个很好的例子,当然现在自己实现一个懒加载方案也非常简单,我们只需要使用getBoundingClientRect这个API配合具体业务使用即可,内容型平台用的比较多,比如我们手机滑到某一区域才加载更多内容,笔者之前做的某头条的广告埋点上报机制就是一个很好的例子.大致思路如下:

  预加载就是提前加载图片,当用户需要查看时可直接从本地缓存中渲染.这种机制和懒加载往往相反,预加载为了带来更加流畅的用户体验,比如漫画网站,我们如果不使用预加载,那么用户频繁切换图片时体验是相当差的,所以我们需要提前将图片加载好,牺牲的代价就是用户可能会等待一定的时间来开启漫画之旅.

  cdn的好处就是可以突破浏览器同域名下一次最大请求并发数量,从而不用排队来提高加载速度.我们都是到同一域名下浏览器最多并发请求6条(不同浏览器之间有差异),超过6条的则会等待前面的请求完成才会继续发起,如果使用cdn,一方面它采用离用户最近的资源来响应,另一方面cdn往往和应用处于不同的域下,所以可以不用等待其他域下的并发数限制,从而加速网站响应.

  这一块就是本文上一节中探讨的内容,这里不做过多介绍了,我们还可以采用localStorage, indexedDB来进一步优化缓存,我们下面会详细介绍这一块的内容.

  代码层面往往就是工程师自己对代码掌控的能力,一个优秀的工程师往往会写出代码量更少,性能更好的代码, 比如采用函数式编程来优化代码结构,使用算法来提高js代码执行效率(比如排序,搜索算法),如果想了解更多这方面的知识,可以参考笔者之前写的两篇文章:

  Web Worker的作用就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。

  Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。新加坡机房服务器但是Worker比较耗费资源,一旦使用完毕,就应该关闭。

  知道了这些web性能优化知识,我们还要充分理解为什么要做这些优化.有过内容平台开发经验的朋友可能会知道,内容平台比较耗资源的就是媒体资源,比如图片,视频等,我们为了有更好的用户体验往往会将这些资源放到第三方服务平台存储,这样会有更好的请求性能还不用担心服务器压力,但是唯一缺点就是烧钱.每一个请求都是钱,虽然不多, 但是也抗不了百万千万的ip请求量,所以这些做的好的内容平台每年至少在这块花个几百万很正常,尤其是按请求付费.所以优化好了网站, 一方面可以带来更多的用户,更好的用户体验,也可以帮公司省流量, 进而帮老板省钱!(跪求求一个年终奖o(╥﹏╥)o).

  关于localStorage的文章也写了很多,使用方法也很简单, 这里就不做过多介绍了,但是有没有考虑自己封装一个localStorage呢? 大多数人可能会觉得很多余,因为localStorage提供的api已经够简单了,没必要封装,但是你有没有考虑过,localStorage是持久化缓存,不支持过期时间,所以有些业务场景下原生localStorage是满足不了的,所以这种情况下饿哦们需要自己实现具有过期时间的localStorage库, 关于如何实现该功能,笔者之前也写过一篇文章,有详细的介绍,并且可以让localStorage使用起来更强大,感兴趣的可以学习研究一下:

  或者在html标签中直接使用umd文件,github地址:基于localStorage封装的可以设置过期时间的库

  我们常用的vue里的状态管理库vuex,因为状态都是存在内存中的,那么如果要做web离线应用,或者web游戏,我们往往需要考虑持久化缓存, 那么我们也可以借助localStorage来实现状态的持久化功能,但是请记住,localStorage的存储空间在5-10M,如果有更大的需求,可以采用接下来介绍的indexedDB来实现.

  IndexedDB主要用于客户端存储大量结构化数据(包括, 文件/ blobs)。该API使用索引来实现对该数据的高性能搜索。虽然 Web Storage 对于存储较少量的数据很有用,但对于存储更大量的结构化数据来说,这种方法不太有用。IndexedDB是一个事务型数据库系统,类似于基于SQL的RDBMS。然而,不像RDBMS使用固定列表,IndexedDB是一个基于JavaScript的面向对象的数据库。它允许我们存储和检索用键索引的对象;可以存储结构化克隆算法支持的任何对象。我们只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务。

  我们刚刚接触indexedDB时往往觉得它很难懂, 我们首先需要使用open方法打开数据库,因为indexedDB大部分方法都是异步的,所以我们很难管理, 包括创建事务,创建表(一组数据的对象存储区), 添加对象存储等,这里笔者不会介绍如何使用indexedDB的具体使用方法,而是叫大家如何简化操作indexedDB的使用流程,封装成一个简单好用的缓存库.以下的封装都是基于promise,这样使用起来更优雅.以下是封装的思路:

  我们工作中处理的indexedDB无非如上几个操作,所以我们需要将其从indexedDB底层API中抽离出来这几个api.具体实现如下:

  这样就实现了一个基于promise的且支持过期时间的indexedDB库,实现过期时间也非常简单,就是在创建表的行时在底层添加一个过期时间字段,用户需要设置改行过期时间时, 只需要添加过期时间即可,当我们再次获取表格数据时只需要检测改行是否过期,如果过期就清除重新设置即可.

  为了更大程度的发挥indexedDB存储空间的优势,并且进一步优化缓存策略,我们来可以做缓存拦截.我们都知道,一个应用的有些请求不需要频繁获取,比如省市级联数据, 区位地图数据,或者一些不需要经常更新的数据, 如果我们可以做到只请求一次, 下次请求直接使用内存数据,并设置一个过期时间, 到过期时间之后会重新请求数据, 那么是不是对请求又可以做一次优化?我们第一印象可能会写出这样的代码:

  这样虽然可以实现功能,但是每一个业务都要写类似的代码, 往往很难受, 所以作为一个有追求的程序员,我们可以在请求上下功夫.我们都有过axios或者fetch库的使用经验,我们也接触过请求/响应的使用, 那么我们能不能考虑对请求本身也做一层拦截呢?我想实现的效果是我们在业务里还是正常的像之前一样使用请求,比如:

  然而内部已经帮我们做好请求缓存了,我们的req实际上不是axios或者fetch的实例,而是一层代理.

  通过这种方式我们对原来的请求方式可以不做任何改变, 完全采用代理机制在请求中和响应中布局我们的代理即可,关键点就是存到数据库中的内容要和服务器响应的内容结构一致.

  以上方式我们可以对所有的get请求做缓存,如果我们只想对部分请求做缓存,其实利用以上机制实现也很简单,我们只需要设置缓存白名单, 在请求中判断如果在白名单内才走缓存逻辑即可.

  这样,我们再次进行某项数据的搜索时,可以不走任何http请求,直接从indexedDB中获取,这样可以为公司节省大量的流量.

  关于indexedDB的库的封装,我也发布到npm和github上了,大家可以直接使用或者进行二次开发.

  大厂技术坚持周更精选好文前言浏览器缓存设计一直是web性能优化中非…

  关注Kevin和互联网产品经理们,一起成长作者lKevin来源lkevin改变世…

  今天周末,韩国代理服务器地址聊点别的。国内某电商巨头顶级富豪在意大利购入一套价值8…

  头条:浏览器缓存库设计总结(localStorage/indexedDB)

  天天快看:Surface Laptop Go 2体验:入门级配置不算强,但胜在好用

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

天眼测评网_VPS测评推荐网站 国外VPS推荐 韩国代理服务器地址头条:浏览器缓存库设计总结(localStorageindexedDB) https://www.tyidc.com.cn/22293.html

常见问题

相关文章

评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务