webpack怎么解决浏览器缓存?使用指纹策略

1,281 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

背景

前端页面防止浏览器缓存,解决方案之一就是,给文件后面添加一串随机的字符串或者数字,我之前的一种做法是给后面添加t=new Date().getTime();
现在webpack里面的出口文件也就是bundle文件也可以使用这种去解决浏览器缓存。
在webpack中,我们想要使用hash的方式去解决浏览器缓存的问题,我们只要出口文件名里面设置hash就行了,这种就叫做指纹策略
这种是Webpack自带的,不用手动再去安转插件库什么的。 一共有三种方式:

  1. hash
  2. chunkhask
  3. contenthash 它们的侧重点各不相同,往下看就知道了。

hash

文件名里面会加入一串随机字符,每个bundle文件是同步的,并且每个bundle文件的hash也是一样的。 先看一下之前的配置以及效果:
之前的webpack.config.js截屏2022-06-16 下午10.46.31.png 构建后的效果:

截屏2022-06-16 下午10.52.05.png
出口文件是没有hash处理的。
webpack.config.js这样配置的:
image.png 出口文件配置的文件名那里加了hash的处理,[name]-[hash].js,意思是原来入口文件名字后面拼接一个 - + 一串随机的字符 。 里面的hash位置文件名的任何地方都是可以的,看自己喜好。 其他文件代码: src/index.js

import {add} from './other.js'
import css from "./index.css";
import test from "./test.less";
console.log("hello 浅唱"); 

src/other.js:

 export function add(a,b){
  return a+b
}

src/list.js:

console.log('我是list文件呀');

src/index.css:

body {
    background: red;
}

src/test.less:

body{
  div{
    height:200px;
    background:url('./images/01.jpg') 0 0 no-repeat;
  }
}

项目目录:

image.png
看效果:

image.png
出口文件的index.js和list.js文件名都有了随机的字符串,并且每次代码更新时,构建后,出口文件的hash是变化的,否则不变。
我文件里面随便改一下,看看:
改之后的src/index.js:

import {add} from './other.js'
import css from "./index.css";
import test from "./test.less";
console.log("hello 是浅唱"); 

改之前的src/index.js:

import {add} from './other.js'
import css from "./index.css";
import test from "./test.less";
console.log("hello 浅唱"); 

执行构建后:

image.png 出口文件中的index.jslist.js文件名中的hash是改变了。
但是,大家有没有觉得hash字符实在太长了,没关系,可以配置,如下:

image.png
-[hash:6]意思是最长hash为6位
但是有个问题,我只改了index.js的内容,list.js并没有改变,但是出口文件,list.js是跟着index.js一块改变的,也就是说其中一个bundle文件改变了,其他的bundley也会跟着一块改变,虽然他们属于不同bundle,如何解决呢,chunkhash。

chunkhash

影响的是改变的那个chunks,而不是所有bundle是同步的,每个bundle文件的hash也就是那串字符串也是不一样的
看看如何配置: webpack.config.js:

image.png
执行构建成功后:

image.png
可看到,出口文件index.js和list.js的hash不一样了,我们再改一下入口文件src/index.js试一下:
改之前:

image.png
改之后:

image.png
执行构建后,出口文件:

image.png
我们看到改变的只是chundle文件index.js,list.js并没有改变。
但是我们改一下src/index.js: 看下dist里面css的变化 改之前:

import {add} from './other.js'
import css from "./index.css";
import test from "./test.less";
console.log("hello 浅唱");

改之后:

import {add} from './other.js'
import css from "./index.css";
import test from "./test.less";
console.log("hello 是浅唱");

webpack.config.js里配置一下css,给css也加一个hash方便判断。
先这样把css配置一下在插件里面配置:给css一个配置了一个文件名和css输出的位置。

image.png
效果是这样的:

image.png 加上chunkhash后:

image.png
效果:

image.png
但是它和出口文件index.css的hash是一样的,所以猜想,它的改变会影响index.css,因为src/index.css是被src/index.js引入的,index.css是一个chunk一个代码片段,而入口文件src/index.js也是一个chunk也是一个代码片段,所以出口文件dist/index.js,bundle文件也是一个chunks,它里面有三个chunk分别是index.js和index.css,list.js。所以说index.js和index.css是属于同一个chunks,chunkhash这样设置,也是会同一个chunks里面的chunk是互相影响的。
回过头来校验一下:
上面的index.js改变之后:
代码改之前的构建效果:

image.png
改之后:

image.png
index.css是随着index.js变化的,事实上我们不需要index.css变化,你js自己变了,就改自己的呗,我index.css为什么要跟着你变化,我多累呀。有解决方法吗?
有的,contenthash来啦

contenthash

顾名思义,自身内容更新,自己才会更新。
配置一下:
webpack.config.js:

image.png
给css添加了这个contenthash,意思是只有css改变了,出口文件中的css才会改变,否则不改变,我们改一下src/index.js试试看:
改之前:

import {add} from './other.js'
import css from "./index.css";
import test from "./test.less";
console.log("hello 浅唱");

改之后:

import {add} from './other.js'
import css from "./index.css";
import test from "./test.less";
console.log("hello 是浅唱");

看效果:

image.png
看:index.js的改变,并没有影响到index.css,它两的hash也不一样。
但是注意,因为css设置了contenthash,但是index.js它设置的还是chunkhash,所以,index.js改变不会影响到css,但是css的改变还是会影响到index.js的。

总结

指纹策略可以解决前端的浏览器缓存问题,文件名都会加一串随机的字符串,分别有3种方式,他们的侧重点不同,chunk之间chunks之间的影响度不同

  1. hash:缺点是改变其中一个bandlu文件,全部的bandlu都会跟着一块改变,它们之间是同步的。并且每个bundle文件的hash也就是那串字符串是一样的。
  2. chunkhask:影响的是改变的那个chunks,各自的chunks之间不是同步的,每个chunks也就是bundle文件的hash也就是那串随机字符是不一样的。
  3. contenthash:自身内容更新,才会更新 多页面用chunkhash,单页面用hash,其他资料用contenthash