前言javascript
瀏覽器爲了優化體驗,會有緩存機制。若是瀏覽器判斷當前資源沒有更新,就不會去服務端下載,而是直接使用本地資源。在webpack的構建中,咱們一般使用給文件添加後綴值來更名以及提取公共代碼到不會改變的lib包中來解決新資源緩存問題。css
hash & chunkhash & contenthashjava
咱們在webpack構建中經過配置filenames來決定輸出的文件名,好比咱們的配置以下webpack
則打包出來的目錄以下web
能夠看到, 打包出來的js名稱對應的就是這樣的規則,這裏之因此name對應的是main, 是由於咱們沒有指定entry的key值,默認是main,不然就是相對於的key值。瀏覽器
在上面,咱們看到,咱們配置的hash值,而後打包出的是一個長串字符串,這邊的的長度咱們能夠指定,好比配置爲緩存
entry: './src/index.js', output: { filename: '[name].[hash:8].js', path: path.resolve(__dirname, 'dist') }
這樣打包出來的就是8位的字符串,咱們看到這邊main模塊打包出的和slove模塊打包出的hash值是同樣的,這個是什麼緣由呢?咱們先來看一下官方對於hash的解釋ruby
模塊標識符(module identifier)的 hash
這個不是很好理解,什麼叫作模塊標識符呢?咱們知道對於webpack來講,它是一個打包編譯的過程,也就是一個 compilation的過程,這個標識符,標識的就是這個打包的過程。這樣就很好解釋了模塊標識符的概念就是在相同編譯打包過程當中的模塊所共有的標識符,也就是說同一過程產出的產物的hash值都是同樣的,也就解釋了上面的過程。bash
可是這樣會有很大的問題,由於咱們不想改變css模塊而去影響到js打包出來的名稱,這樣不利於咱們去作緩存。那該怎麼去解決這樣的問題呢?ide
這時候咱們就須要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的打包名稱也會改變,這是咱們不須要的,因此咱們怎麼解決這個問題呢。
從名稱上咱們能夠知道,它是根據文件內容來定義hash值得,因此咱們就可使用插件extract-text-webpack-plugin定義的contenthash來打包。配置以下:
new MiniCssExtractPlugin({ filename: "[name].[contenthash].css" })
這樣打包出來的結果是:
總結的一個方法:
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; };
引入的例子以下圖: