前端性能优化之缓存利用

 

前言

越来越多的公司开始做PWA,渐进式web应用了。我的博客源码是2014年年初写的,近期有时间正准备优化一下,也改成PWA的web应用。关于PWA渐进式web应用,我在博客改版之后再来详细介绍!今天主要详细介绍一下性能优化之缓存利用,本文将详细介绍各种缓存,及其机制,前段时间我也写过一篇关于前端浏览器缓存的文章,在我博客中搜索缓存,也能搜到几篇文章,感兴趣的可以先去我之前文章去看一下,本文将详细介绍缓存及如何利用。

缓存种类

大体想了一下,关于缓存,无非有如下几种:

1、CDN缓存

2、DNS缓存

3、客户端缓存(无需请求的memory cache,disk cache,需要发请求验证的Etag、Last-Modified304)

4、Service Worker与缓存及离线缓存

5、PageCache与ajax缓存

CDN缓存

看到一个形象的比喻,来比喻CDN。

10年前,还没有火车票代售点一说,12306.cn更是无从说起。那时候火车票还只能在火车站的售票大厅购买,而我所在的小县城并不通火车,火车票都要去市里的火车站购买,而从我家到县城再到市里,来回就是4个小时车程,简直就是浪费生命。后来就好了,小县城里出现了火车票代售点,甚至乡镇上也有了代售点,可以直接在代售点购买火车票,方便了不少,全市人民再也不用在一个点苦逼的排队买票了。

CDN就可以理解为分布在每个县城或者乡镇的火车票代售点,用户在浏览网站的时候,CDN会选择一个离用户最近的CDN边缘节点来响应用户的请求,这样海南移动用户的请求就不会千里迢迢跑到北京电信机房的服务器(假设源站部署在北京电信机房)上了。

CDN的优势很明显:(1)CDN节点解决了跨运营商和跨地域访问的问题,访问延时大大降低;(2)大部分请求在CDN边缘节点完成,CDN起到了分流作用,减轻了源站的负载。

关于CDN缓存 ,在浏览器本地缓存失效后,浏览器会向CDN边缘节点发起请求。类似浏览器缓存,CDN边缘节点也存在着一套缓存机制。CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议,通过http响应头中的

Cache-control: max-age

的字段来设置CDN边缘节点数据缓存时间。

当客户端向CDN节点请求数据时,CDN节点会判断缓存数据是否过期,若缓存数据并没有过期,则直接将缓存数据返回给客户端;否则,CDN节点就会向源站发出回源请求,从源站拉取最新数据,更新本地缓存,并将最新数据返回给客户端。 CDN服务商一般会提供基于文件后缀、目录多个维度来指定CDN缓存时间,为用户提供更精细化的缓存管理。

CDN缓存刷新

CDN边缘节点对开发者是透明的,相比于浏览器Ctrl+F5的强制刷新来使浏览器本地缓存失效,开发者可以通过CDN服务商提供的“刷新缓存”接口来达到清理CDN边缘节点缓存的目的。这样开发者在更新数据后,可以使用“刷新缓存”功能来强制CDN节点上的数据缓存过期,保证客户端在访问时,拉取到最新的数据。

DNS缓存

DNS(Domain Name System): 负责将域名URL转化为服务器主机IP。

DNS查找流程:首先查看浏览器缓存是否存在,不存在则访问本机DNS缓存,再不存在则访问本地DNS服务器。所以DNS也是开销,通常浏览器查找一个给定URL的IP地址要花费20-120ms,在DNS查找完成前,浏览器不能从host那里下载任何东西。

TTL(Time To Live):表示查找返回的DNS记录包含的一个存活时间,过期则这个DNS记录将被抛弃。浏览器DNS缓存也有自己的过期时间,这个时间是独立于本机DNS缓存的,相对也比较短,例如chrome只有1分钟左右。

DNS性能优化最佳实践

当客户端的DNS缓存为空时,DNS查找的数量与Web页面中唯一主机名的数量相等。所以减少唯一主机名的数量就可以减少DNS查找的数量。

但是问题来了,有时候需要多设置主机数量,来增加DNS的负载均衡,因此减少DNS查找和增加主机数量形成了矛盾关系,经过实战DNS设置2-4个主机名是最佳的。更多负载均衡可以用其他方式实现,例如用nginx做负载均衡!

浏览器缓存策略之客户端缓存

1、Cache-control: max-age

假设你的站点有引用一个脚本文件,你非常确认这个脚本文件内容五十年不变。那么自然希望浏览器把这个脚本缓存起来,不用每一次都请求服务器,然后服务器再返回相同的内容。这样能够节省带宽开销并且提升性能。

此时你只需要设置文件返回的HTTP头中的Cache-Control设置为:

Cache-Control: max-age=31536000

虽然是五十年不变,但是标准中规定max-age值最大不能超过一年,又因为是以秒为单位,所以值为31536000

例如这个五十年不变的脚本地址是 www.haorooms.com/never-expire.js 那么接下来每次用户请求这个地址时,浏览器都不会再向服务器发出请求,而是直接从本地的浏览器缓存中取。直到一年以后或者用户手动的清除了缓存。

但是,如果这一年中的某一天你发现脚本内容必须要更改了怎么办?很简单,改变请求的文件名就好了,例如never-expire-v2.js。

Cache-control: max-age 可以控制缓存时间。如下图:

enter image description here

Max-age 使用秒来计量,如:

Cache-Control:max-age=645672

指定页面645672秒(7.47天)后过期。

2、Expires

enter image description here

设置了Expires也可以避免浏览器和服务器发请求,直到时间过期。

以上2个缓存,遵循三级缓存原理

3、Last-Modified 304协商缓存

服务器为了通知浏览器当前文件的版本,会发送一个上次修改时间的标签,例如:

Last-Modified:Tue, 06 Jan 2018 08:26:32 GMT

如下图:

enter image description here

假如是304协商缓存,验证步骤如下:

  1. 浏览器:Hey,我需要jquery.min.js这个文件,如果是在 Last-Modified:Tue, 06 Jan 2018 08:26:32 GMT 之后修改过的,请发给我。

  2. 服务器:(检查文件的修改时间)

  3. 服务器:Hey,这个文件在那个时间之后没有被修改过,你已经有最新的版本了。

  4. 浏览器:太好了,那我就显示给用户了。

4、ETag

上面截图中也圈出来了,其实Etag和304类似,但是级别比 Last-Modified 高一些。

请求过程如下:

1. 浏览器:Hey,我需要haorooms的main.css这个文件,有没有不匹配"61213-1762a-50bf790757204"这个串的2. 服务器:(检查ETag…)3. 服务器:Hey,我这里的版本也是"61213-1762a-50bf790757204",你已经是最新的版本了4. 浏览器:好,那就可以使用本地缓存了

Service Worker与缓存及离线缓存

随着Service Worker(以下简称SW)的普及和规范,我们可以使用SW提供的缓存接口替代HTTP缓存。当然SW的功能是强大的,除了缓存功能,还能够使用它来实现离线、数据同步、后台编译等等。

一个标配版的sw缓存工代代码应该有以下的片段:

const version = '2';self.addEventListener('install', event => {event.waitUntil(caches.open(`static-${version}`).then(cache => cache.addAll(['/styles.css','/script.js'])));
});self.addEventListener('fetch', event => {event.respondWith(caches.match(event.request).then(response => response || fetch(event.request)));
});

首先你要明白的前提是,网络请求首先到达的是SW脚本中,如果未命中再转发给HTTP缓存。

这段代码的意思是,在SW的install阶段我们将script.js和styles.css放入缓存中;而在请求发起的fetch阶段,通过资源的URL去缓存内查找匹配,成功后立刻返回,否则走正常的网络请求流程。

但你有没有考虑过,在install阶段的资源内容是哪里来的?仍然是从HTTP缓存中。这样SW缓存机制又有可能随着HTTP缓存陷入了之前所说的版本不一致的困境中。

既然我们借助SW重写了缓存机制,所以也不想再受牵制于旧的HTTP缓存。解决办法是让SW中的请求必须向服务端验证:

self.addEventListener('install', event => {event.waitUntil(caches.open(`static-${version}`).then(cache => cache.addAll([new Request('/styles.css', { cache: 'no-cache' }),new Request('/script.js', { cache: 'no-cache' })])));
});

目前并非所有的浏览器都支持cache选项的配置。但这个不是太大问题,我们可以通过添加随机数来保证每次请求的URL都不相同,间接的使得缓存失效:

self.addEventListener('install', event => {event.waitUntil(caches.open(`static-${version}`).then(cache => Promise.all(['/styles.css','/script.js'].map(url => {// cache-bust using a random query stringreturn fetch(`${url}?${Math.random()}`).then(response => {// fail on 404, 500 etcif (!response.ok) throw Error('Not ok');return cache.put(url, response);})}))));
});

离线缓存

关于离线缓存,可以看我之前的文章:http://www.haorooms.com/post/html5_appcache

PageCache与Ajax可缓存

PageCache其实是facebook提出的,解决ajax缓存的一种方案!简单的说,就是将访问过的页面缓存在客户端。但我们知道,作为Facebook这样交互性很强的网站,需要保障用户能尽早的获得更新后的信息,而不是给用户展示一个毫无意义的过期页面。

Facebook设计了一个框架来识别一个页面是否来自于缓存(猜测:页面首次加载完毕后将所有Ajax的Callback和Result缓存在本地。Facebook页面是基于Ajax获取页面内容,参见BigPipe),若来自于缓存,通过Ajax来更新所需更新的模块(猜测:通过JS预先定义本页面所需更新的div Id及对应的callback handler,并在页面下载时同时下载下来)。

其提到了三种更新类型:增量更新,用户复写(例如用户在页面上回复了一则评论)及跨页更新(例如在消息详细页面将一则消息标识为已读,需将首页的未读消息数进行更新。)。核心思路还是依据Ajax进行更新。具体思路为:

1、增量更新:只要页面来自于缓存,即更新所有预定义的需增量更新的模块。

2、用户复写:通过HistoryManager记录用户操作并在cache页面读取后重放所有被标记为“replayable”的操作。

3、跨页更新:通过服务端Database API发送信号至客户端将过期缓存标识为invalid(不清楚如何实现。也许是DB端提供一个开放的webservice,客户端通过Ajax持续访问此API来获得此信息)。获得了缓存过期信号后,通过Ajax更新需要更新的信息。

Facebook顺带提到了一个更新Ajax内容避免页面变化/闪烁的小技巧,就是先将需更新的地方设置为blank,而非直接更新其内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/23487.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT教你如何解决复杂高并发系统缓存设计(上)

ChatGPT教你如何解决复杂高并发系统缓存设计(上) ❗缓存,消息队列,分库分表是高并发解决方案三剑客。 为什么需要设计系统缓存 设计系统缓存的主要目的是提高系统的性能和可伸缩性,同时减轻底层资源(如数据库、网络)的…

NPM报错 Error: EPERM: operation not permitted, unlink......解决办法和清除缓存。

由于国内外环境因素,npm install安装依赖的时候经常会出现各种问题,特别是“Error: EPERM: operation not permitted, unlink…”这个错误。 这个错误因为报错信息的误导性,导致很多网上提出的解决办法都是什么设置权限,以管理员…

人工智能趋势——2023 年综述

随着DALLE 2 于 2022 年 4 月的宣布,关于2022 年初第三个 AI 冬天——或 AI 撞墙——的预言过时得很快而且效果不佳,随后出现了更多主要由扩散模型驱动的文本到图像应用程序,这是一个非常多产的领域用于计算机视觉研究及其他领域。AI 的 2022…

王炸 ChatGPT又更新,能联网同5000+应用交互

都说ChatGPT是AI的“iPhone时刻”,现在属于它的“应用商店”来了。 OpenAI刚刚又甩出一个王炸—— 宣布推出插件功能,赋予ChatGPT使用工具、联网、运行计算的能力。 例如在官方演示中,ChatGPT一旦接入数学知识引擎Wolfram Alpha&#xff0…

tab栏切换的实现

Tab导航栏切换在网页场景中十分常见,本文将介绍如何用js来实现交互的导航栏。 分析: 1.当鼠标点击上面相应的选项卡(tab),下面盒子的内容跟随变化 2.点击某一个选项,当前这一个底色会变成红色,字…

Ubuntu16.04如何将桌面上左边任务栏移到屏幕下方

操作步骤 1)移动到桌面的下方: 打开终端,(快捷键:CtrlAltT)然后输入命令:gsettings set com.canonical.Unity.Launcher launcher-position Bottom效果图如下所示: 2)移动到桌面的左方: 打开终端,输入命令:g…

简单的tap栏切换

效果图&#xff1a; HTML部分 <div class"tab"><div class"tab_top"><ul><li class"current">水果</li><li>家电</li><li>书籍</li><li>服装</li></ul></div>&l…

Ubuntu图形桌面切换到命令行界面

Ubuntu提供两种进入方式&#xff0c;一个是我们平常最熟悉的图形界面形式&#xff0c;还有一种是纯命令行方式。 1、按 Ctrl Alt (F1~F6中的任意一个)即可进入纯命令行模式。 进入后&#xff0c;需要输入用户名&#xff0c;密码(此处包括root用户与非root用户)。 注意&#x…

如何利用chatgpt做到大型桌面应用无痛换肤

有一个换肤的需求&#xff0c;但是颜色实在太多了&#xff0c;虽然有主题色&#xff0c;但是除了主题色的颜色还是好多好多。利用chatgtp做到尽快&#xff0c;快速换肤。 1.先要求chatgpt帮你写一个脚本。 文件夹下的的所有文件包括文件夹下的文件夹内的所有文件&#xff0c;…

firefox网页自动翻译

firefox自带翻译组件 1. 在应用程序菜单中选择扩展和主题 2. 附加组件中直接搜素相应的翻译组件 推荐第二个 我使用的很顺手 !! 有网页翻译和划词翻译 3. 基础设置 设置方便 但是有一部分翻译源是需要向源申请的,需要一部分自己的信息,不过操作简单,按照流程就可以 4. 其他…

Firefox启动自带翻译

一般情况下&#xff0c;使用Firefox访问英文网页时不会弹出翻译工具栏&#xff0c;但我们可以在Firefox高级配置的首选项中启用它&#xff08;图为测试使用的浏览器版本&#xff09; 首先&#xff0c;在 Firefox 地址栏输入 about:config&#xff0c;进入高级首选项配置界面 …

火狐浏览器划词翻译设置操作

当我们阅读国外文献时&#xff0c;往往遇到不懂的单词和句子&#xff0c;要是能够变阅读变翻译&#xff0c;同时也为了我们避免仅仅依靠翻译软件&#xff0c;不仅学习而且还能重点学习不认识和不懂的单词&#xff0c;那么如何在火狐浏览器中设置划词翻译呢&#xff1f; 其实是…

在火狐浏览器上安装Tampermonkey和Greasy Fork和使用iciba划词翻译

网页上都是英文&#xff0c;有时候翻译很不方便&#xff0c;为了更好的查看英文文档&#xff0c;安装了汉化翻译软件。话不多说开始安装步骤&#xff1a; 一、安装Tampermonkey 网页&#xff1a;Tampermonkey • Home 根据自己的火狐浏览器的版本选择合适的Tampermonkey&…

火狐浏览器翻译网页

火狐浏览器翻译网页 1 打开火狐浏览器&#xff0c;找到附加组件 2 打开附加组件&#xff0c;点击寻找更多的附加组件 3 搜索翻译&#xff0c;选择你需要的翻译组件 4 推荐使用这个 5 点击添加就行了 6 不喜欢的话可以选择移除&#xff0c;重新更换附加组件

火狐浏览器中如何设置自动翻译网页

火狐需要通过自己的设置来拥有和谷歌一样的自动翻译网页的功能&#xff0c;具体操作如下&#xff1a; 在扩展与主题里找到“插件” 在“插件”界面直接搜索“translation”&#xff0c;搜索答案中第一个中文标题的叫“翻译界面”&#xff0c;这个就很好用&#xff0c;直接下载…

这可能是最好的firefox移动版翻译插件

这可能是最好的firefox移动版翻译插件 需求 上一篇不是介绍了如何在firefox移动版自由安装插件么&#xff0c;但是整页翻译的插件因为不能显示浮窗和实现鼠标右键而不能正常使用。 解决 今天更新完firefox重新启用了图中这个插件后发现浮窗正常了&#xff0c;有点东西&…

【原创】火狐浏览器网页翻译

5个火狐浏览器必备的插件翻译工具&#xff0c;个个都支持翻译多国语种_网页_内容_页面 腾讯翻译 一个由腾讯发布的的一款浏览器翻译插件&#xff0c;能够一键翻译国外网站&#xff0c;打开火狐的扩展主题&#xff0c;搜索名字就可以快速找到&#xff0c;然后点击添加就可以将…

火狐浏览器翻译页面功能如何设置

有不少小伙伴喜欢用火狐浏览器&#xff0c;当浏览英文网页或时要怎么开启翻译页面功能呢?今天小编就和大家说说火狐浏览器翻译页面功能的开启方法&#xff0c;快来看看吧! 工具/原料&#xff1a; 系统版本&#xff1a;windows 10 品牌型号&#xff1a; 戴尔 成就3910 方法…

火狐浏览器翻译

应急的话用这个网站&#xff1a;点我翻译 这是火狐浏览器插件&#xff1a;翻译Firefox 扩展&#xff08;zh-CN&#xff09; 不会搞浏览器加载插件点我 很不错哟 多试几个选个喜欢的&#xff1a;侧边翻译 – 下载 &#x1f98a; Firefox 扩展&#xff08;zh-CN&#xff09; 软件…

firefox 火狐浏览器yandex网页翻译

1.概述 firefox 浏览器相对于 chrome 浏览器的一个弱势就是网页翻译。 firefox 浏览器现有的翻译扩展存在各种各样的问题&#xff0c;例如 HTTPS 网站不允许插入混合内容&#xff0c;使用 HTTP 协议的翻译 API 就无法运行。 Google 翻译看似很美好&#xff0c;但「正常情况下」…