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模拟弹出效果代码修正版
Aug 07 Javascript
JavaScript 动态创建VML的方法
Oct 14 Javascript
jQuery中的bind绑定事件与文本框改变事件的临时解决方法
Aug 13 Javascript
网页源代码保护(禁止右键、复制、另存为、查看源文件)
May 23 Javascript
js导出txt示例代码
Jan 14 Javascript
javascript入门之数组[新手必看]
Nov 21 Javascript
Angular实现的简单查询天气预报功能示例
Dec 27 Javascript
Vue用v-for给循环标签自身属性添加属性值的方法
Oct 18 Javascript
微信公众号获取用户地理位置并列出附近的门店的示例代码
Jul 25 Javascript
Vue+iview+webpack ie浏览器兼容简单处理
Sep 20 Javascript
用vue写一个日历
Nov 02 Javascript
vue3.0中使用element的完整步骤
Mar 04 Vue.js
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
海河写的 Discuz论坛帖子调用js的php代码
2007/08/23 PHP
谈PHP生成静态页面分析 模板+缓存+写文件
2009/08/17 PHP
php格式化日期和时间格式化示例分享
2014/02/24 PHP
PHP整数取余返回负数的相关解决方法
2014/05/15 PHP
YII使用url组件美化管理的方法
2015/12/28 PHP
PHP抓取及分析网页的方法详解
2016/04/26 PHP
PHP时间戳格式全部汇总 (获取时间、时间戳)
2016/06/13 PHP
PHP解决高并发的优化方案实例
2020/12/10 PHP
Javascript YUI 读码日记之 YAHOO.util.Dom - Part.2 0
2008/03/22 Javascript
HTML长文本截取含有HTML代码同样适用的两种方法
2013/07/31 Javascript
js Select下拉列表框进行多选、移除、交换内容的具体实现方法
2013/08/13 Javascript
js+css实现导航效果实例
2015/02/10 Javascript
JavaScript实现横向滑出的多级菜单效果
2015/10/09 Javascript
EasyUI Pagination 分页的两种做法小结
2016/07/09 Javascript
JavaScript使用Range调色及透明度实例
2016/09/25 Javascript
原生js实现图片放大缩小计时器效果
2017/01/20 Javascript
浅谈JS封闭函数、闭包、内置对象
2017/07/18 Javascript
使用vue实现grid-layout功能实例代码
2018/01/05 Javascript
layui-laydate时间日历控件使用方法详解
2018/11/15 Javascript
vue 微信分享回调iOS和安卓回调出现错误的解决
2020/09/07 Javascript
JavaScript实现4位随机验证码的生成
2021/01/28 Javascript
写了个监控nginx进程的Python脚本
2012/05/10 Python
Python开发的实用计算器完整实例
2017/05/10 Python
Python之py2exe打包工具详解
2017/06/14 Python
Tornado高并发处理方法实例代码
2018/01/15 Python
Django的性能优化实现解析
2019/07/30 Python
django实现web接口 python3模拟Post请求方式
2019/11/19 Python
关于django python manage.py startapp 应用名出错异常原因解析
2020/12/15 Python
Mountain Warehouse澳大利亚官网:欧洲家庭户外品牌倡导者
2016/11/20 全球购物
毕业生个人求职的自我评价
2013/10/28 职场文书
捐书寄语赠言
2014/01/18 职场文书
入党积极分子学习党的纲领思想汇报
2014/09/13 职场文书
群众路线教育实践活动整改方案(个人版)
2014/10/25 职场文书
教师年度个人总结
2015/02/11 职场文书
广播稿:校园广播稿范文
2019/04/17 职场文书
Python批量将csv文件转化成xml文件的实例
2021/05/10 Python