Webpack5更新指南

Webpack5更新指南

2020-10-10 Webpack5 正式 realease 相較于 Webpack4 已經過了兩年多了.在這期間并沒有什么重大的改變,因為同學們并不喜歡重大的改變尤其是像 Webpack 這種你一年可能就用兩次. 但由于沒有去做一些重大的改變,我們不能去做一些重要的 api 和
架構上的改變來提升效率,所以 Webpack5 出現了.

傳送門

這次主要在這幾點上:

  • Improve build performance with Persistent Caching (通過使用持久性緩存來提高構建性能)
  • Improve Long Term Caching with better algorithms and defaults.(通過算法和默認設置來提升長期緩存)
  • Improve bundle size with better Tree Shaking and Code Generation.(通過更好的 Tree Shaking 和代碼生成來壓縮包大小)
  • Improve compatibility with the web platform. (提升網絡平臺的兼容性)
  • Clean up internal structures that were left in a weird state while implementing features in v4 - without introducing any breaking changes.(清除一些內部架構,這些架構在v4版本中很奇怪.但并不會引起重大的改變)
  • Prepare for future features by introducing breaking changes now, allowing us to stay on v5 for as long as possible. (為了以后的release,我們現在引入了一些重大的改變,使我們可以在v5停留盡可能長的時間)

既然官方都說了要待一段時間我們就好好學吧,反正早用早享受!!!

timg.gif

我們先從這幾個重大的變化娓娓道來

Improve build performance with Persistent Caching

傳送門

Webpack5官方并沒有將 Persistent Caching作為默認設置,而是需要我們去配置.因為Webpack5更主張安全而不是效率.不希望因為提升95%的表現而導致5%的出錯.

當我們設置cache.type為 filesystem時 相對于webpack4 我們多了以下幾點。

buildDependencies

傳送門

buildDependencies指定構建過程的代碼依賴性.讓webpack負責解析和遵循指定值的依賴項.

官方推薦設置為 [__filename].
[__filename] depends在你的config文件.
當你任何使用require()的module發生改變時Persistent Caching就會無效.

module.exports = {
  cache: {
    buildDependencies: {
      // This makes all dependencies of this file - build dependencies
      config: [__filename]
      // By default webpack and loaders are build dependencies
    }
  }
};

如果是類似fs.readFile的話就不會

version

傳送門

一些build的依賴是不能壓縮成文件的像從數據庫讀取數據或者環境變量.對于這些值我們可以使用version

我們可以通過傳遞不一樣的string來使Persistent Caching無效

如果你的config讀取環境變量GIT_REV并且使用DefinePlugin來嵌入打包. 我們就可以將GIT_REV作為依賴.

僅當將cache.type設置為filesystem時,cache.version才有意義

cache: {
    version: `${process.env.GIT_REV}`
}
name

傳送門
cache的名字,不同的名字將會導致不同的共存緩存。當具有多個應該具有獨立緩存的配置時,使用cache.name才有意義

僅當將cache.type設置為filesystem時,cache.name才有意義

store

傳送門
cache.store告訴了webpack什么時候存儲data在filesystem

'pack':當編譯器空閑時,將所有緩存項的數據存儲在單個文件中
僅當將cache.type設置為filesystem時,cache.store選項才可用

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

cacheDirectory

傳送門
緩存的基本目錄 默認node_modules/.cache/webpack

僅當將cache.type設置為filesystem時,cache.cacheDirectory選項才可用

最終路徑為cache.directory + cache.name

const path = require('path');

module.exports = {
  //...
  cache: {
    type: 'filesystem',
    cacheDirectory: path.resolve(__dirname, '.temp_cache')
  }
};
cacheLocation

傳送門
cache路徑 默認path.resolve(cache.cacheDirectory, cache.name).

僅當將cache.type設置為filesystem時,cache.cacheLocation才可用

const path = require('path');

module.exports = {
  //...
  cache: {
    type: 'filesystem',
    cacheLocation: path.resolve(__dirname, '.test_cache')
  }
};

Improve Long Term Caching with better algorithms and defaults.

傳送門

確定的 Chunk、模塊 ID 和導出名稱

這些是自動加入生產模式的

chunkIds: "deterministic" moduleIds: "deterministic" mangleExports: "deterministic"

該算法以確定性方式為modules和chunks 分配短(3或5位數字)數字ID,并為導出分配短(2個字符)名稱。這是包大小和長期緩存之間的折衷方案。

真正的content hash

之前只是使用內部結構的哈希值。當只有注釋被修改或變量被重命名時,這對長期緩存會有積極影響。這些變化在壓縮后是不可見的。

Improve bundle size with better Tree Shaking and Code Generation.(通過更好的 Tree Shaking 和代碼生成來壓縮包大小)

嵌套的 tree-shaking

傳送門
webpack 現在能夠跟蹤對導出的嵌套屬性的訪問。這可以改善重新導出命名空間 對象時的 Tree Shaking(清除未使用的導出和混淆導出)。

// inner.js
export const a = 1;
export const b = 2;

// module.js
export * as inner from './inner';
// or import * as inner from './inner'; export { inner };

// user.js
import * as module from './module';
console.log(module.inner.a);

在生產模式時,b會被刪除

內部模塊的 tree-shaking

傳送門

webpack 4 沒有分析模塊的導出和引用之間的依賴關系。webpack 5 有一個新的選項 optimization.innerGraph,在生產模式下是默認啟用的,它可以對模塊中的標志進行分析,找出導出和引用之間的依賴關系。

import { something } from './something';

function usingSomething() {
  return something;
}

export function test() {
  return usingSomething();
}

innerGraph會找出 something 只有在使用 test 導出時才會使用。這允許將更多的出口標記為未使用,并從代碼包中省略更多的代碼。
當設置"sideEffects": false時,可以省略更多的模塊。在這個例子中,當 test 導出未被使用時,./something 將被省略。
要獲得未使用的導出信息,需要使用 optimization.unusedExports。要刪除無副作用的模塊,需要使用optimization.sideEffects。可以分析以下標記:

  • 函數聲明
  • 類聲明
  • 默認導出export default 或定義變量以下的:
  • 函數表達式
  • 類表達式
  • 順序表達式
  • /#PURE/ 表達式
  • 局部變量
  • 引入的捆綁(bindings)

使用 eval() 將為一個模塊放棄這個優化,因為經過 eval 的代碼可以引用范圍內的任何標記。這種優化也被稱為深度范圍分析。

CommonJs Tree的 Shaking

傳送門
webpack used to opt-out from used exports analysing for CommonJs exports and require() calls.

webpack 5 增加了 一些CommonJs 構造的支持,允許消除未使用的 CommonJs 導出,并從 require() 調用中跟蹤引用的導出名稱。

以下結構是支持的:

  • exports|this|module.exports.xxx = ...
  • exports|this|module.exports = require("...") (reexport)
  • exports|this|module.exports.xxx = require("...").xxx (reexport)
  • Object.defineProperty(exports|this|module.exports, "xxx", ...)
  • require("abc").xxx
  • require("abc").xxx()
  • importing from ESM
  • require() a ESM
  • flagged exportType (special handling for non-strict ESM import):
  • Object.defineProperty(exports|this|module.exports, "__esModule", { value: true|!0 })
  • exports|this|module.exports.__esModule = true|!0
  • It's planned to support more constructs in future

當檢測到不可分析的代碼時,webpack 會放棄,并且完全不跟蹤這些模塊的導出信息(為了性能考慮)。

一般的Tree Shaking提升

傳送門
export * 已得到改進,可以跟蹤更多信息,并且不再將默認導出標記為已使用。

export * 當webpack確定出口沖突時,將顯示警告。

import()允許通過/ * webpackExports:[“ abc”,“ default”] * /魔術注釋來手動tree shake。

Improve compatibility with the web platform.

webpack 5停止了nodejs中的polyfill并且專注于前端兼容模塊。

我們的目標是提高與Web平臺的兼容性,在Web平臺上,Node.js核心模塊不可用。

參考文檔:

introducing-federated-modules-in-webpack-5
module-federation-guide-offical
persistent-caching-guide-offical
webpackv5-realease-changelog
精讀module-federation

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。