webpack 中,hash、chunkhash、contenthash 的區別是什么?


Webpack 有非常多的概念,很多名詞長得都差不多。我把這些分散在文檔和教程里的內容總結起來,寫了一份 webpack 中的易混淆知識點,目前看是全網獨一份,大家可以加個收藏,方便以后檢索和學習。

全集鏈接 ➡️ webpack 易混淆知識點

首先來個背景介紹,哈希一般是結合 CDN 緩存來使用的。如果文件內容改變的話,那么對應文件哈希值也會改變,對應的 HTML 引用的 URL 地址也會改變,觸發 CDN 服務器從源服務器上拉取對應數據,進而更新本地緩存。

4.1 hash

hash 計算是跟整個項目的構建相關,我們做一個簡單的 demo。

沿用案例 1 的 demo 代碼,文件目錄如下:

src/
├── index.css
├── index.html
├── index.js
└── utils.js

webpack 的核心配置如下(省略了一些 module 配置信息):

{
    entry: {
        index: "../src/index.js",
        utils: '../src/utils.js',
    },
    output: {
        filename: "[name].[hash].js",  // 改為 hash
    },
    
    ......
    
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'index.[hash].css' // 改為 hash
        }),
    ]
}

生成的文件名如下:

我們可以發現,生成文件的 hash 和項目的構建 hash 都是一模一樣的。

4.2 chunkhash

因為 hash 是項目構建的哈希值,項目中如果有些變動,hash 一定會變,比如說我改動了 utils.js 的代碼,index.js 里的代碼雖然沒有改變,但是大家都是用的同一份 hash。hash 一變,緩存一定失效了,這樣子是沒辦法實現 CDN 和瀏覽器緩存的。

chunkhash 就是解決這個問題的,它根據不同的入口文件(Entry)進行依賴文件解析、構建對應的 chunk,生成對應的哈希值。

我們再舉個例子,我們對 utils.js 里文件進行改動:

export function square(x) {
    return x * x;
}

// 增加 cube() 求立方函數
export function cube(x) {
    return x * x * x;
}

然后把 webpack 里的所有 hash 改為 chunkhash:

{
    entry: {
        index: "../src/index.js",
        utils: '../src/utils.js',
    },
    output: {
        filename: "[name].[chunkhash].js", // 改為 chunkhash
    },
          
    ......
    
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'index.[chunkhash].css' // // 改為 chunkhash
        }),
    ]
}

構建結果如下:

我們可以看出,chunk 0 的 hash 都是一樣的,chunk 1 的 hash 和上面的不一樣。

假設我又把 utils.js 里的 cube() 函數去掉,再打包:

對比可以發現,只有 chunk 1 的 hash 發生變化,chunk 0 的 hash 還是原來的。

4.3 contenthash

我們更近一步,index.js 和 index.css 同為一個 chunk,如果 index.js 內容發生變化,但是 index.css 沒有變化,打包后他們的 hash 都發生變化,這對 css 文件來說是一種浪費。如何解決這個問題呢?

contenthash 將根據資源內容創建出唯一 hash,也就是說文件內容不變,hash 就不變。

我們修改一下 webpack 的配置:

{
    entry: {
        index: "../src/index.js",
        utils: '../src/utils.js',
    },
    output: {
        filename: "[name].[chunkhash].js",
    },
      
    ......
    
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'index.[contenthash].css' // 這里改為 contenthash
        }),
    ]
}

我們對 index.js 文件做了 3 次修改(就是改了改 log 函數的輸出內容,過於簡單就先不寫了),然后分別構建,結果截圖如下:

我們可以發現,css 文件的 hash 都沒有發生改變。

4.4 一句話總結:

hash 計算與整個項目的構建相關;

chunkhash 計算與同一 chunk 內容相關;

contenthash 計算與文件內容本身相關。




最后推薦一下我的個人公眾號:「鹵蛋實驗室」,平時會分享一些前端技術和數據分析的內容,大家感興趣的話可以關注一波:



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM