js前端面试常见浏览器缓存强缓存及协商缓存实例


Posted in Javascript onJune 21, 2022

前言

最近在背面试题时,时常会看见浏览器缓存,虽然没有用过但是从它的描写中大致是知道它的作用和重要性。但是还是没有代码实操过,也是一知半解的,这口气咽不下啊,开始找资料,但是大部分都是理论半行代码没有,终于东拼西凑顿悟了。开始搭环境,干活。

浏览器缓存

浏览器缓存是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。 浏览器缓存主要分为强缓存(也称本地缓存)和协商缓存(也称弱缓存)。

强缓存

当请求资源的时,如果是之前请求过的并使用强缓存,那么在过期时间内将不会发送本次请求向服务器获取资源,而是直接从浏览器缓存中获取(不管资源是否改动)。过期了将重新从服务器获取,并再次强缓存。

协商缓存

当请求资源时,如果是之前请求过的并使用协商缓存,还是发送请求到服务器,服务器通过逻辑判断确认资源没有修改返回304状态码,那么本次的资源则是从缓存中获取;如果经过判断确认资源被修改过,则重新发送资源到客户端,并且客户端更新缓存。

判断资源是否修改有两种标准,一种是判断最后修改时间是否变了(确实是修改了,但资源的内容可以没有变),另一种是判断资源的内容是否修改

使用缓存有下面的优点:

  • 减少冗余的数据传输
  • 减少服务器负担
  • 加快客户端加载网页的速度

搭建环境

  • 创建文件夹app,并在下创建app.js 和 fs/a.txt(里面随便写东西)

js前端面试常见浏览器缓存强缓存及协商缓存实例

我们使用node+koa2来搭建我们需要的环境,安装koa、安装路由

npm install koa --save
npm install koa-router --save

app.js

var Koa = require('koa');
var app = new Koa();
var Router = require('koa-router')();
const fs = require('fs')
Router.get("/", async (ctx) => {
    ctx.body = "ok"
})
app
    .use(Router.routes())   	//启动路由
    .use(Router.allowedMethods());
app.listen(3000);

启动服务器,网页输入网址127.0.0.1:3000,环境搭建成功

js前端面试常见浏览器缓存强缓存及协商缓存实例

强缓存

强缓存是利用http头中的Expires和Cache-Control两个字段来控制的,Expires是http1.0的规范,Cache-Control是在http1.1中出现的,我们这里使用Cache-Control示范。

Cache-Control有一些常设置的值

  • private:仅浏览器可以缓存(默认值);
  • public:浏览器和代理服务器都可以缓存;
  • max-age=xxx:过期时间单位秒;
  • no-cache:不进行强缓存;
  • no-store:不强缓存,也不协商缓存)

将上面 / 路由的代码改为

Router.get('/', async (ctx) => {
    const getResource = () => {
        return new Promise((res) => {
            fs.readFile("./fs/a.txt", (err, data) => {
                if (err) {
                    return;
                }
                res(data)
            })
        })
    }
    ctx.set('Cache-Control', 'max-age=10')  //设置强缓存,过期时间为10秒
    ctx.body = await getResource(); 
})

将测试搭建环境页面关闭,重新打开网页访问127.0.0.1:3000

前端页面响应头多了Cache-Control这个字段,且10s内都走本地缓存,不会去请求服务端

js前端面试常见浏览器缓存强缓存及协商缓存实例

在过期时间内再次请求资源,就可以看到这次请求并没有经过服务器

js前端面试常见浏览器缓存强缓存及协商缓存实例

协商缓存

主要涉及到两组header字段:Etag和If-None-Match、Last-Modified和if-modified-since。

Etag和If-None-Match

Etag/If-None-Match返回的是一个校验码。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。服务器根据浏览器上送的If-None-Match值来判断是否命中缓存。 当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化。

Last-Modify和if-modified-since

浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-Modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。

当浏览器再次请求该资源时,request的请求头中会包含 if-modified-since,该值为缓存之前返回的Last-Modify。服务器收到if-modified-since后,根据资源的最后修改时间判断是否命中缓存。

如果命中缓存,则返回304,并且不会返回资源内容,并且不会返回Last-Modify。

样例我们使用Last-Modify和if-modified-since来实现。对于Etag和If-None-Match的实现,读取资源内容,转成hash值,然后跟Last-Modify和if-modified-since的实现差不多了,同一个道理。

新添加一个路由器

Router.get('/pp', async (ctx) => {
    const ifModifiedSince = ctx.request.header['if-modified-since'];
    const getResource = () => {
        return new Promise((res) => {
            fs.stat("./fs/a.txt", (err, stats) => {
                if (err) {
                    console.log(err);
                }
                res(stats)
            })
        })
    }
    let resource = await getResource();
    // atime	Access Time	访问时间	
    // 最后一次访问文件(读取或执行)的时间
    // ctime	Change Time	变化时间	
    // 最后一次改变文件(属性或权限)或者目录(属性或权限)的时间
    // mtime	Modify Time	修改时间	
    // 最后一次修改文件(内容)或者目录(内容)的时间
    if (ifModifiedSince === resource.mtime.toGMTString()) { //把具体的日期转换为(根据 GMT)字符串
        ctx.status = 304;
    }
    ctx.set('Last-Modified', resource.mtime.toGMTString());
    ctx.body = resource
})

关闭页面,重新打开网页访问127.0.0.1:3000/pp

第一次请求,是没有if-modified-since字段的

js前端面试常见浏览器缓存强缓存及协商缓存实例

第二次请求,没有修改资源,返回状态码304,从缓存获取资源

js前端面试常见浏览器缓存强缓存及协商缓存实例

修改a.txt文件里内容时,重新请求服务器

js前端面试常见浏览器缓存强缓存及协商缓存实例

以上就是js前端面试常见浏览器缓存强缓存及协商缓存实例的详细内容,更多关于js前端面试浏览器缓存的资料请关注三水点靠木其它相关文章!


Tags in this post...

Javascript 相关文章推荐
js 获取(接收)地址栏参数值的方法
Apr 01 Javascript
在AngularJS中使用AJAX的方法
Jun 17 Javascript
基于jQuery和CSS3制作响应式水平时间轴附源码下载
Dec 20 Javascript
JavaScript数据操作_浅谈原始值和引用值的操作本质
Aug 23 Javascript
JavaScript每天必学之基础知识
Sep 17 Javascript
微信小程序 vidao实现视频播放和弹幕的功能
Nov 02 Javascript
使用D3.js构建实时图形的示例代码
Aug 28 Javascript
原生JS实现的自动轮播图功能详解
Dec 28 Javascript
vue实现动态按钮功能
May 13 Javascript
我要点爆”微信小程序云开发之项目建立与我的页面功能实现
May 26 Javascript
JavaScript实现省市区三级联动
Feb 13 Javascript
详解JavaScript中分解数字的三种方法
Jan 05 Javascript
JavaScript前端面试组合函数
Jun 21 #Javascript
Vue2项目中对百度地图的封装使用详解
JavaScript原型链中函数和对象的理解
JS精髓原型链继承及构造函数继承问题纠正
Jun 16 #Javascript
5个实用的JavaScript新特性
Jun 16 #Javascript
字节飞书面试promise.all实现示例
Jun 16 #Javascript
JS轻量级函数式编程实现XDM三
Jun 16 #Javascript
You might like
PHP查询数据库中满足条件的记录条数(两种实现方法)
2013/01/29 PHP
PHP数组遍历知识汇总(包含遍历方法、数组指针操作函数、数组遍历测速)
2014/07/05 PHP
PHP面向对象程序设计之命名空间与自动加载类详解
2016/12/02 PHP
设定php简写功能的方法
2019/11/28 PHP
基于JQuery实现滚动到页面底端时自动加载更多信息
2014/01/31 Javascript
jQuery中:contains选择器用法实例
2014/12/30 Javascript
JS实现网页背景颜色与select框中颜色同时变化的方法
2015/02/27 Javascript
JS+CSS模拟可以无刷新显示内容的留言板实例
2015/03/03 Javascript
JavaScript基本数据类型及值类型和引用类型
2015/08/25 Javascript
jquery表单验证插件validation使用方法详解
2017/01/20 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
AngularJS实现的JSONP跨域访问数据传输功能详解
2017/07/20 Javascript
初学者AngularJS的环境搭建过程
2017/10/27 Javascript
JS数组扁平化(flat)方法总结详解
2019/06/24 Javascript
详解Angular cli配置过程记录
2019/11/07 Javascript
Python多线程threading和multiprocessing模块实例解析
2018/01/29 Python
python数据分析数据标准化及离散化详解
2018/02/26 Python
Python3.5模块的定义、导入、优化操作图文详解
2019/04/27 Python
Python中请不要再用re.compile了
2019/06/30 Python
python实现LRU热点缓存及原理
2019/10/29 Python
python+tifffile之tiff文件读写方式
2020/01/13 Python
pytorch 查看cuda 版本方式
2020/06/23 Python
Pytorch 解决自定义子Module .cuda() tensor失败的问题
2020/06/23 Python
Python3爬虫中关于Ajax分析方法的总结
2020/07/10 Python
健身场所或家用健身设备:Life Fitness
2017/11/01 全球购物
GOOD AMERICAN官网:为曲线性感而设计
2017/12/28 全球购物
施华洛世奇美国官网:SWAROVSKI美国
2018/02/08 全球购物
AT&T Wireless:手机、无限数据计划和配件
2018/06/03 全球购物
小学生读书活动总结
2014/06/30 职场文书
泸县召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
微观世界观后感
2015/06/10 职场文书
网络营销实训总结
2015/08/03 职场文书
职工趣味运动会开幕词
2016/03/04 职场文书
《我在为谁工作》:工作的质量往往决定生活的质量
2019/12/27 职场文书
python基础之类属性和实例属性
2021/10/24 Python
zabbix配置nginx监控的实现
2022/05/25 Servers