Junwen's home
  • ES6

    • ES6 Decorator
    • ES6核心特性
    • Promise&Generator
  • js原理

    • 简单实现bind、apply和call
    • 如何遍历一个dom tree
    • 实现函数currying
    • 实现一个event
    • 详解js的继承
    • 详解requestAnimationFrame
    • Canvas api详解
    • DOM事件
    • EventLoop详解
    • JavaScript的内存管理
    • JavaScript的运行机制
    • Math对象
    • new操作符都做了什么
    • create基本实现原理
    • Set、Map、WeakSet和WeakMap
    • web worker原理
    • WebGL教程(MDN)
  • jsInfoSeries

    • 简介
    • JavaScript基础知识
    • 基础知识2
    • 基础知识3
    • 基础知识4
  • 技巧

    • 5个js解构有趣用途
    • 如何使用set提高代码性能
    • cordova构建项目时的问题
    • js中轻松遍历对象属性的几种方式
  • 怎么写出更好的css
  • BFC详解
  • box-shadow详解
  • CSS小技巧
  • Grid布局详解
HTML
  • IP十问
  • http笔试
  • http协议
  • 浏览器原理
  • 浏览器缓存其实就这么一回事儿
  • 浏览器兼容性问题
  • 移动端开发兼容性适配
  • 前端性能优化
  • 前端如何进行seo优化
  • webpack

    • webpack HMR
    • webpack优化基本方法
  • leetcode题解

    • 两数之和
    • 判断整数是否为回文串
    • 无重复字符的最长子串
  • Js链表
  • JavaScript排序
  • React

    • 虚拟DOM原理理解
    • React Hook
    • 组件复用指南
  • Vue

    • Vue举一反三
面试题
读书笔记
GitHub (opens new window)

Syun0216

多读书多种树
  • ES6

    • ES6 Decorator
    • ES6核心特性
    • Promise&Generator
  • js原理

    • 简单实现bind、apply和call
    • 如何遍历一个dom tree
    • 实现函数currying
    • 实现一个event
    • 详解js的继承
    • 详解requestAnimationFrame
    • Canvas api详解
    • DOM事件
    • EventLoop详解
    • JavaScript的内存管理
    • JavaScript的运行机制
    • Math对象
    • new操作符都做了什么
    • create基本实现原理
    • Set、Map、WeakSet和WeakMap
    • web worker原理
    • WebGL教程(MDN)
  • jsInfoSeries

    • 简介
    • JavaScript基础知识
    • 基础知识2
    • 基础知识3
    • 基础知识4
  • 技巧

    • 5个js解构有趣用途
    • 如何使用set提高代码性能
    • cordova构建项目时的问题
    • js中轻松遍历对象属性的几种方式
  • 怎么写出更好的css
  • BFC详解
  • box-shadow详解
  • CSS小技巧
  • Grid布局详解
HTML
  • IP十问
  • http笔试
  • http协议
  • 浏览器原理
  • 浏览器缓存其实就这么一回事儿
  • 浏览器兼容性问题
  • 移动端开发兼容性适配
  • 前端性能优化
  • 前端如何进行seo优化
  • webpack

    • webpack HMR
    • webpack优化基本方法
  • leetcode题解

    • 两数之和
    • 判断整数是否为回文串
    • 无重复字符的最长子串
  • Js链表
  • JavaScript排序
  • React

    • 虚拟DOM原理理解
    • React Hook
    • 组件复用指南
  • Vue

    • Vue举一反三
面试题
读书笔记
GitHub (opens new window)
  • 浏览器原理
  • 浏览器缓存其实就这么一回事儿
    • 浏览器缓存其实就这么一回事儿
  • 浏览器兼容性问题
  • 移动端开发兼容性适配
  • 前端性能优化
  • 前端如何进行seo优化
  • lerna学习笔记
  • 用nodejs搭建api网关
  • etcd学习
  • webpack

    • webpack HMR
    • webpack优化基本方法
  • CI/CD

    • 如何从0到1一步步成体系地搭建CI
    • 如何建立前端标准化研发流程
    • 如何打造全链路项目生命周期的统一交付平台
  • project
junwen
2020-05-18

浏览器缓存其实就这么一回事儿

# 浏览器缓存其实就这么一回事儿

# 前言

说到浏览器缓存,做前端的同学可能也不会陌生,他是我们优化前端性能的重要组成部分。但一说到这个东西,大家又觉得跟自己平时开发的业务需求不太沾边,仅仅是面试的时候才会去背一下相关的知识,所以过会就忘了,而且也没有真正了解他。本文中,小编将带着大家去实践一下浏览器缓存的各种使用场景,其实浏览器缓存就这么一回事儿。

# 准备环境

本文中,我们会以mac的环境来讲解,所以相关命令也是mac系统的命令。

  1. 首先,我们要在mac系统下安装nginx,nginx是什么这里我也不多讲了。输入一下命令,我们便可进行安装。
brew update # 更新homebrew
brew search nginx # 查看nginx信息
brew install nginx # 安装nginx
nginx # 运行nginx
nginx -s reload # 重载nginx
1
2
3
4
5

成功后我们便可看到一下截图:

  1. 配置nginx的conf
cd /usr/local/etc/nginx  # 进入nginx根目录
mkdir conf # 创建配置目录
touch ./conf/index.conf # 创建我们的nginx配置
vim nginx.conf # 配置nginx
1
2
3
4
  1. 在nginx.conf下的配置以下语句:
http {
    ...
    include conf/*; # 引入所有conf目录下的配置文件
}
1
2
3
4
  1. 配置我们刚才创建的index.conf文件
server {
    listen 9527;
    server_name localhost;
    location / {
        root html/web;
        index index.html index.htm;
        try_files $uri /index.html;
    }
    location ~ .*dll\.js$ { # 对dll结尾的js文件进行缓存设置
        root html/web;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 配置我们的静态资源

# 创建静态资源文件

cd /usr/local/var/www # 到nginx存放html的根目录
mkdir web # 创建我们刚才的web文件夹
touch ./web/index.html ./web/react_dll.js ./web/index.js # 创建对应的文件资源, react_dll.js是我们使用 
1
2
3

# 配置我们的index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>hello world</title>
</head>
<body>
    <div id="app"></div>
    <script src="/index.js"></script>
    <script src="/react_dll.js"></script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13

# 配置index.js

document.querySelector('#app').innerHTML = 'Hello world!';
1

# 不使用缓存

如各位所见,刚才我们配置的index.conf并没有配置浏览器缓存的语句,所以每次请求都会返回200,我们来看下一下截图: 第一次请求,我们从服务器读取我们的资源,当我们刷新一下页面,js资源就会直接从浏览器内存中读取: 可以看到这个memory cache就是从浏览器缓存中读取的意思,这个时候我们不需要消耗时间来请求文件。
那么当我们关掉浏览器的tab,将会看到什么情况呢: 那么我们可以得出以下结论:当我们没有配置任何浏览器缓存时,我们每次打开浏览器tab来请求我们的资源都会去服务器取,需要耗时,而当我们刷新页面时,浏览器会在内存中取得这些文件。

# 使用强缓存

强缓存(本地缓存)是指浏览器在发送请求前,会先去缓存里查看是否命中强缓存,如果命中,则直接从缓存中读取资源,不会发送请求到服务器。

# Expired

Expired是HTTP/1.0时引入,我们可以设置一个绝对时间,在这个时间之前资源都会走本地缓存而不会去请求服务器。比如我们在index.conf文件中作一下配置:

location ~ .*dll\.js$ { # 对dll结尾的js文件进行缓存设置
    root html/web;
    expires 1d; # 一天之后过期
}
1
2
3
4

可以看到当我们设置了强缓存,我们首次加载还是会请求我们的服务器: 当我们关掉tab页,再打开,我们发现浏览器会从磁盘直接读取文件: 再次刷新,我们就在浏览器的内存读取文件了: 我们也可以从response headers里看到我们设置的expires时间,这个是一个绝对时间。

# cache-control

到了HTTP/1.1, Expire已经被Cache-Control替代,原因在于Expire控制员村的原理是使用客户端的时间与服务端返回的时间对比,如果客户端与服务端的时间因为某些原因发生误差,那么强制缓存就会直接失效。
Cache-Control的主要取值为:

  • public: 所有内容都会被缓存(客户端和代理服务器都可缓存)
  • private: 所有内容只有客户端可以缓存, Cache-Control的默认值
  • no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
  • no-store: 所有内容都不会被缓存,即不适用强制缓存也不使用协商缓存
  • max-age=xxx: 缓存内容将在xxx秒后失效

我们在index.conf中配置Cache-Control看下真是情况是怎样的:

# max-age
location ~ .*dll\.js$ { # 对dll结尾的js文件进行缓存设置
    root html/web;
    # expires 1d; # 一天之后过期
    add_header Cache-Control max-age=30;
}
1
2
3
4
5
首次请求后,我们就会在磁盘中请求文件,如下图显示: 当我们过了30s后再次请求,则会重新向服务器请求资源:

# public

location ~ .*dll\.js$ { # 对dll结尾的js文件进行缓存设置
    root html/web;
    # expires 1d; # 一天之后过期
    add_header Cache-Control public;
}
1
2
3
4
5

# no-cahce

可以在本地进行缓存,但每次发请求时,都要向服务器进行验证,如果服务器允许,才能使用本地缓存。跟max-age=0;用法相同。那么当我们设置了这个属性后,浏览器加载资源将会怎么样,我们来看一下流程图:

# 使用协商缓存

当我们在nginx上写了如下代码:

location ~ .*dll\.js$ { # 对dll结尾的js文件进行缓存设置
    root html/web;
    # expires 1d; # 一天之后过期
    add_header Cache-Control no-cache; # 或者设置Cache-Control max-age=0;
} 
1
2
3
4
5

# Last-Modified & If-Modified-Since

# Etag & If-None-Match

在Github上编辑此页 (opens new window)
#浏览器缓存
上次更新: 3/22/2021, 3:47:15 AM
浏览器原理
浏览器兼容性问题

← 浏览器原理 浏览器兼容性问题→

最近更新
01
如何打造全链路项目生命周期的统一交付平台
04-10
02
如何建立前端标准化研发流程
04-10
03
如何从0到1一步步成体系地搭建CI
04-10
更多文章>
Theme by Vdoing | Copyright © 2019-2021 Syun
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式