webpack 学习笔记之十一 hash chunkhash contenthash

一.hash是什么?

hash 是一种散列算法.

它可以将[任意长度的二进制数]据映射成[较短的固定长度的]二进制值.

它的原理很简单,所有的数据,不管是图片,文字,视频,文件等乱七八糟的东西.

丢给一个固定的hash算法,只要文件的内容不发生改变,那么计算出来的hash永远都是一样的.

大家最熟悉的hash算法莫过于 MD5 了.


二.hash在前端开发的过程中,起到了哪些特别的作用?

前端开发,不管是用什么框架,什么打包工具,最终运行的环境是浏览器.

浏览器是有缓存机制的.如果一个文件的文件名不发生变化,那么浏览器就会有很大的可能去缓存这个文件(cache-control:no-cache除外.)

有时候,浏览器的缓存也是一把双刃剑.比如我们的某个css文件的内容实际上是改了,但是由于文件名没改.

浏览器就认为这个文件没有发生变动,不去再次发生请求从服务器获取,而是从本地缓存里读取.会导致用户看到的文件并不是最新的.

所以,经常会看到这样的css代码.

<link rel="stylesheet" href="style.css?v=1.0">
<link rel="stylesheet" href="style.css?v=1.2">
<link rel="stylesheet" href="style.css?v=1.3">

通过给一个基本没啥作用的查询字符串结尾,让浏览器认为这是一个动态的请求,从而获得最新的css文件的目的.

webpack 提供的类似的功能,就叫做hash功能.

可以给打包出来的文件名,加上一串hash值,每次都可以生成一个新的文件名.


webpack 给文件名插入之 hash

webpack.config.js

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  entry: {
    indexName: path.join(__dirname, 'index.js'),
    appFileName: path.join(__dirname, 'app.js')
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]_[hash].js'
  },
  mode: 'development',
  plugins: [
    new CleanWebpackPlugin()
  ]
}

打包查看结果:

image.png

查看打包的输出结果

  • 整个项目的hash值是: e4b33a6c56df04dda9be
  • appFileName的hash值是: e4b33a6c56df04dda9be
  • indexName的hash值是: e4b33a6c56df04dda9be

现在仅仅修改 index.js 文件.

// index.js
let i = 0

重新打包

image.png
  • 整个项目的hash值: 414410450aa6ab446bc3
  • appFileName的hash值是: 414410450aa6ab446bc3
  • indexName的hash值是: 414410450aa6ab446bc3

现在问题就来了, 我明明只改了 index.js 里的代码,app.js代码压根没动.但是它的hash还是变了.

hash是项目级别的.只要项目内部改动了任意一个位置,所有设置了 hash 的文件的hash值都会跟着一起发生改变.

(那些从来压根没改过的文件的hash也会跟着改变).这样的话,完全就不合理了.没变内容的文件如果hash也变了,文件

名就变了.文件变了,浏览器就需要重新下载这个文件,达不到缓存的作用了.


webpack 给文件插入之 chunkhash

chunkhash是针对entry的每一个入口文件,独立的hash。如果entry里面的其中一个文件内容改变,只会改变这个入口

文件build之后的文件名,而不会影响到其他文件。

webpack.config.js

const path = require('path')
// import { CleanWebpackPlugin } from 'clean-webpack-plugin' // node.js 还不支持ES6的import模块导入语法.
const {
  CleanWebpackPlugin
} = require('clean-webpack-plugin')

module.exports = {
  entry: {
    indexName: path.join(__dirname, 'index.js'),
    appFileName: path.join(__dirname, 'app.js')
  },
  output: {
    path: path.join(__dirname, 'dist'),
    // filename: '[name]_[hash].js'
    filename: '[name]_[chunkhash].js'
  },
  mode: 'development',
  module: {
    rules: [{
      test: /\.(png|jpg|gif)$/,
      use: [{
        loader: 'file-loader',
        options: {
          name: '[name]_[contenthash].[ext]'
        }
      }]
    }]
  },
  plugins: [
    new CleanWebpackPlugin()
  ]
}

查看结果

image.png
  • 整个项目的 hash 值是: 9ec8f05fbffa71101b9c
  • appFileName 的 hash 值是: 420fbddeda08d6b1d3c0.
  • indexName 的 hash 值是: bdd32b0728173915f845

他们三个的hash值都不相同.

现在修改 app.js

let i = 0

查看结果:

image.png
  • 由于对于整个项目而言,的确有文件的内容被修改了,所以 hash 值从原来的 9ec8f05fbffa71101b9c 变成了 2bd51d157cc397ec1523. 在情理和意料之中.
  • appFileName 的 hash 值 : 49d983a60c15f9a92cb4 而原来的是 420fbddeda08d6b1d3c0 . 也在情理和意料之中,因为我们修改了 app.js 的代码 let i = 0
  • indexName 的 hash 仍然是原来的 bdd32b0728173915f845 , 没有改动过代码,所以还是原来的值.

webpack 给文件名插入之 contenthash

contenthash 顾名思义, 就是根据当前文件的内容,来计算hash值.

将非output的文件名设置hash或者chunkhash,比如(css,image等)都将无效,而且默认使用的是contenthash

比如:

rules: [{
      test: /\.(png|jpg|gif)$/,
      use: [{
        loader: 'file-loader',
        options: {
          name: '[name]_[hash].[ext]' // 按道理是当前项目的hash值.
        }
      }]
    }]

结果:

image.png

按道理来说,设置了hash,图片文件名应该和项目的hash一致.

但结果,它俩完全不一样,肉眼都可以一眼看出,起码长度都不一样.

webpack.config.js

rules: [{
      test: /\.(png|jpg|gif)$/,
      use: [{
        loader: 'file-loader',
        options: {
          // name: '[name]_[hash].[ext]' // 按道理是当前项目的hash值.
          name: '[name]_[chunkhash].[ext]' //Path variable [chunkhash] not implemented in this context: 282-8_[chunkhash].jpg
        }
      }]
    }]

配置费output文件成为chunkhash,直接报错.

//Path variable [chunkhash] not implemented in this context: 282-8_[chunkhash].jpg

压根就没实现这个hash的功能.

配置contenthash

rules: [{
      test: /\.(png|jpg|gif)$/,
      use: [{
        loader: 'file-loader',
        options: {
          // name: '[name]_[hash].[ext]' // 按道理是当前项目的hash值.
          // name: '[name]_[chunkhash].[ext]' //Path variable [chunkhash] not implemented in this context: 282-8_[chunkhash].jpg
          name: '[name]_[contenthash].[ext]' // 根据文件的内容,生成的hash
        }
      }]
    }]

结果:

image.png

发现和配置hash 的情况一致.也就是说,给jpg等静态资源配置hash默认就会转成contenthash.


总结:

  • hash [范围最大] 是针对整个项目的,如果把整个项目当做是一个文件(为什么非要是单个的1.txt就这么好理解成是文件了?),那么这个项目文件的内容发生改变(文件删除添加,文件内容修改),都会导致整个项目的hash值发生改变.

  • chunkhash [范围其次] 是根据当前入口文件最终打包出来的js文件.output. 当前依赖链中,有任意文件变动,都会改变这个hash值.

  • 而contenthash [范围最小] 就仅仅只是针对当前文件的内容.

这里说了一堆东西.到底想表达什么?

hash,chunkhash,contenthash,说白了,就是根据不同的范围,给最终生成的文件名里加一串字符串.(hash把整个项目当成一个文件;chunkhash把一个独立的entry个output当前一个文件(多个模块之间的依赖当成一个chunk);contenthash则是把单个文件当成是一个文件)

它们有一个共同的特点就是,最终它们都会是生成一个独立的文件,且在浏览器中,会有一个链接指向它们.

有链接指向它们,它们就能利用所谓的各种hash,来做缓存了.

一张图解:

image.png

码云

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容