webpack构建缓存机制-hash介绍

 

前言

浏览器为了优化体验,会有缓存机制。如果浏览器判断当前资源没有更新,就不会去服务端下载,而是直接使用本地资源。在webpack的构建中,我们通常使用给文件添加后缀值来改名以及提取公共代码到不会改变的lib包中来解决新资源缓存问题。

hash & chunkhash & contenthash

输出文件名output Filenames

我们在webpack构建中通过配置filenames来决定输出的文件名,比如我们的配置如下

则打包出来的目录如下

可以看到, 打包出来的js名称对应的就是这样的规则,这里之所以name对应的是main, 是因为我们没有指定entry的key值,默认是main,否则就是相对于的key值。

hash

在上面,我们看到,我们配置的hash值,然后打包出的是一个长串字符串,这边的的长度我们可以指定,比如配置为

entry: './src/index.js',
output: {
    filename: '[name].[hash:8].js',
    path: path.resolve(__dirname, 'dist')
}

这样打包出来的就是8位的字符串,我们看到这边main模块打包出的和slove模块打包出的hash值是一样的,这个是什么原因呢?我们先来看一下官方对于hash的解释

模块标识符(module identifier)的 hash

这个不是很好理解,什么叫做模块标识符呢?我们知道对于webpack来说,它是一个打包编译的过程,也就是一个 compilation的过程,这个标识符,标识的就是这个打包的过程。这样就很好解释了模块标识符的概念就是在相同编译打包过程中的模块所共有的标识符,也就是说同一过程产出的产物的hash值都是一样的,也就解释了上面的过程。

但是这样会有很大的问题,因为我们不想改变css模块而去影响到js打包出来的名称,这样不利于我们去做缓存。那该怎么去解决这样的问题呢?

chunkhash

这时候我们就需要chunkhash出场来解决问题了,我们先来看一下官方对于chunkhash的解释

chunk 内容的 hash

我们知道chunk指代的是模块,顾名思义,chunkhash就是模块的hash,也就是根据模块内容计算的hash值。那这边我们css模块的修改和js模块就没有关系,我们看一下使用chunkhash打包出来的结果,配置如下:

entry: {
    main: './src/index.js',
    slove: './src/slove.js'
},
output: {
    filename: '[name].[chunkhash].js',
    path: path.resolve(__dirname, 'dist')
}

这时候打包出来的目录如图所示:

这时候我们看到main模块与slove模块的hash值是不同的,这样我们修改main中的内容就不会修改slove的名称,slove的缓存就可以继续使用了。但是,这时候我们发现,main模块中的css文件和js文件的hash值是相同的。如果我们修改了js的内容,css的打包名称也会改变,这是我们不需要的,所以我们怎么解决这个问题呢。

contenthash

从名称上我们可以知道,它是根据文件内容来定义hash值得,所以我们就可以使用插件extract-text-webpack-plugin定义的contenthash来打包。配置如下:

new MiniCssExtractPlugin({
    filename: "[name].[contenthash].css"
})

这样打包出来的结果是:

 
 
作者:JungleW
链接:https://www.jianshu.com/p/e609e7b55aa7
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

总结的一个方法:

const addHash = fname => {
    var r = fname;
    if (IS_DEV) return r;
    const name = "[name]";
    const index = fname.lastIndexOf(name);
    if (index !== -1) {
        const suffix = fname.substring(index + name.length);
        let hash = 'hash'
        if (suffix === '.js') {
            hash = 'chunkhash'
        } else if (suffix === '.css') {
            hash = 'contenthash'
        }
        r = fname.replace(name + suffix, `${name}.[${hash}:8]${suffix}`);
    }
    return r;
};
引入的例子如下图:

 


 

posted @ 2019-05-09 16:51  Milk.╮  阅读(473)  评论(0编辑  收藏  举报