Webpack5 的一些知識總結

前言

webpack 5 是 2020 年發佈的,webpack 4 是 2018 年發佈的,在 webpack 4 之上也做出了挺多的改變,比如,添加了 cache 的支持,模塊聯邦新玩意......

持久性緩存來提高構建性能

在 webpack 5 之前,webpack 是沒有提供持久化緩存,我們開發的時候需要使用類似 cache-loader 來做緩存方面的處理。

在 webpack 4 中:

module.exports = {
  module: {
    rules: [
      {
        test: /.ext$/,
        use: ['cache-loader', ...loaders],
        include: path.resolve('src'),
      },
    ],
  },
};

在 webpack 5 中

在 webpack 5 中自身也加入了持久化緩存,緩存生成的 webpack 模塊和 chunk,來改善構建速度。cache 會在開發 模式被設置成 type: 'memory' 而且在 生產 模式 中被禁用。

module.exports = {
  cache: {
    type: 'filesystem',
  },
};

cache.type 有兩個值 memory | filesystemmemory 表示會將打包生成的資源存放於內存中。filesystem 表示開啓了文件系統緩存。

更好的 hash 算法

這裏指的就是訪問 web 頁面時的瀏覽器緩存,我們也知道,之前有 hash chunckhash contenthash 在 webpack 5 中,把 hash 改成了 fullhash

首先,我們介紹一下這幾個 hash 值有什麼不一樣。

hash/fullhash

hash/fullhash 是根據打包中的所有文件計算出來的 hash 值,在一次打包中,所有的資源出口文件的 filename 獲得的 [hash] 都是一樣的。

chunckhash

chunckhash 顧名思義是根據打包過程中當前 chunck 計算出來的 hash 值。

contenthash

contenthash 顧名思義是根據打包時的內容計算出的 hash 值。

當然,這麼看好像,看不出啥問題,不就是把一個 hash 改成 fullhash 而已嘛?dang dang dang 然不是,我們就來扒扒看,直接上實戰,喵喵有啥不一樣。

我們先設定 webpack 的設置如下

const path = require('path');
module.exports = {
  mode: 'production',
  entry: {
    index: './index.js'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[contenthash].js',
  },
}

這裏是要打包的 index.js 的內容

const num = 1;
console.log('這裏是輸出', num);

這是添加註釋和修改變量後的 index.js 的內容

const str = 1;
//這裏是輸出
console.log('這裏是輸出', str);

webpack 4 打包

我們可以看到這裏的 hash 值爲 e8510378c5f44d16af40

這裏是添加註釋和修改變量後打包後的結果

我們可以看到這裏的 hash 值爲 2c719bba27df586bf8f2

webpack 5 打包

我們可以看到這裏的 hash 值爲 d1bc13ae7e7dc828a64f

這裏是添加註釋和修改變量後打包後的結果

我們可以看到這裏的 hash 值爲 d1bc13ae7e7dc828a64f

總結

我們可以明顯看出,webpack 4 對於添加註釋和修改變量其實,是會影響它的一個 contenthash 值的計算,如果是 webpack 5 的話,就不會影響。

Tree Shaking 的改進

tree shaking 是一個術語,通常用於描述移除 JavaScript 上下文中的未引用代碼 (dead-code)。它依賴於 ES2015 模塊語法的 靜態結構 特性,例如 import 和 export。

既然 webpack 4 都有這個功能,那麼隨着 webpack 5 的升級,又有什麼不一樣的地方呢?

我們來建立一個三個文件,index.js、a.js、b.js

// a.js
const name = 'zhangSan';
const age = 18;

export { name, age };
// b.js
import * as data from'./a';
export { data };
// index.js
import * as common from'./b';
// 我們可以看到只是使用了 age,而沒有使用 name
console.log(common.data.age);

webpack 4 打包結果

但是我們打包出來的結果,卻是連 name 也打包進去。

webpack 5 打包結果

簡直完美秒殺。

總結

當然,在 webpack 4 中,Tree Shaking 對嵌套的導出模塊未使用代碼無法很好進行 Tree Shaking,當然我們也可以藉助一些 plugin 來實現,但是到了 webpack 5 得到了很大的改進。

模塊聯邦(Module Federation)

Webpack5 模塊聯邦讓 Webpack 達到了線上 Runtime 的效果,讓代碼直接在項目間利用 CDN 直接共享,不再需要本地安裝 Npm 包、構建再發布了!

容器項目

//這裏是容器的webpack模塊聯邦設置【也就是在該組件使用】
newModuleFederationPlugin({
  name: 'react1',
  library: { type: 'var', name: 'react1' },
  remotes: {
    RemoteComponent: 'RemoteComponent'
  },
}),
// 在html引入
<script src="http://localhost:3001/remoteEntry.js"></script>
// 這裏是它的代碼
importReact, { Fragment } from'react';
importReactDOMfrom'react-dom';

constButton = React.lazy(() =>import('RemoteComponent/Button'));

functionApp() {
  functiononClick() {
    console.log('這裏是遠程組件觸發的');
  }
  return (
    <div>
      <h1>這裏是測試模塊聯邦的項目</h1>
      <React.Suspense fallback='努力加載中💪...'>
        <Button onClick={onClick} content='content'></Button>
      </React.Suspense>
    </div>
  );
}

遠程組件項目

// 提供遠程組件的項目webpack模塊聯邦設置
newModuleFederationPlugin({
  name: 'RemoteComponent',
  library: { type: 'var', name: 'RemoteComponent' },
  // 使用此遠程組件加載的文件名稱
  filename: 'remoteEntry.js',
  exposes: {
  //此處提供了一個Button組件
    './Button': './src/components/Button',
  },
}),
// 這是遠程button組件
importReactfrom'react';

exportdefaultfunctionButton({ content, onClick = () => {} }) {
  return (
    <button onClick={onClick}>{ content }</button>
  )
}

實際效果

我們可以看到,點擊按鈕,成功觸發 onClick 事件。

Asset Modules

Asset Modules 通常被翻譯爲資源模塊,它指的是圖片和字體等這一類型文件模塊,它們無須使用額外的預處理器,webpack 通過一些配置就可以完成對它們的解析。

在 webpack 5 之前,沒有內置資源模塊,所以,我們通常使用,file-loader url-loader raw-loader 之類的 loader 去處理。

// 在webpack5中,可以直接使用內置的資源模塊就行了
module.exports = {
// ...
  module: {
    rules: [{
      test: /\.jpg$/,
      type: 'asset/resource'
    }]
  }
}
// 在webpack 4就需要使用 file-loader 之類的loader
module.exports = {
  module: {
    rules: [
      {
        test: /.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {}
          }
        ]
      }
    ]
  }
}

Asset Modules 它的值有四種,asset/resource(對應 file-loader)、asset/inline(對應 url-loader)、asset/source(對應 raw-loader)、asset。

結束

當然,webpack 5 的改變不止這些,比如,還有 不再爲 Node.js 模塊自動引用 polyfill、也內置了 terser 進行代碼壓縮......

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/l06gQrTw67X6mxeE2iJkgQ