1. 程式人生 > >webpack 4.0.0-beta.0 新特性介紹

webpack 4.0.0-beta.0 新特性介紹

此處輸入圖片的描述近年來前端技術如雨後春筍般蓬勃發展,我們也在這個潮流下不斷地學習、成長。前端技術的不斷髮展,給我們提供了許多的便利。例如:JSX的出現為我們提供了一個清晰、直觀的方式來描述元件樹,LESS/SASS的出現提高了我們書寫css的能力,AMD/CommonJS/ES6 的出現為我們模組化開發提供了便利。然而,我們需要使用其它工具將這些工具轉化成原生語言以執行在瀏覽器上。為了能夠更好的將這些不同的資源整合到一起,我們就需要一個打包工具,webpack就是這個需求下的產物。webpack 可以看做是模組打包機。它做的事情是:分析你的專案結構,找到JavaScript模組以及其它的一些瀏覽器不能直接執行的拓展語言(Scss,TypeScript等),並將其打包為合適的格式以供瀏覽器使用。目前,webpack 總共釋出了三個穩定版本。從17年八月底開始,經歷了長達五個月的開發週期,webpack 團隊通過增加大量新特性、bug修復、問題改善並於近期釋出了 webpack 4.0.0 的 beta 版本。如果你對 webpack 感興趣,下面我們就來學習一下 webpack 4.0.0-beta.0 的新特性。P.S. 以下所有程式碼演示程式碼都是基於 webpack 4.0.0-beta.0。

1、安裝webpack v4.0.0-beta.0

如果你使用yarn:

yarn add webpack@next webpack-cli --dev

如果你使用npm:

npm install webpack@next webpack-cli --save-dev

2、webpack 4.0.0.beta.0 新特性介紹

下面是一些你肯定會感興趣的新特性。如果閱讀完本章後還覺得不過癮,你可以再這檢視完整的changelog。本章將從以下幾部分來介紹 webpack 4.0.0-beta.0。

2.1 環境

webpack 執行環境升級。已經不支援 Node.js 4 版本。原始碼升級到更高的 ECMAScript 版本。

根據 webpack package.json 配置中顯示 Node.js 最低支援版本:”node”: “>=6.11.5”

2.2 模組

webpack 模組型別及 .mjs 的支援:長久以來,JS是webapck中唯一的模組型別。正因此,開發者無法有效地打包其它型別的檔案。目前,webpack實現了五種模組型別,它們各有自己的優勢,可按需要使用(後面會詳細說明)。

  • javascript/auto: (webpack3中預設)支援所有的JS模組系統:CommonJS、AMD、ESM。
  • javascript/esm: EcmaScript模組,所有其他模組系統不可用(.mjs檔案中預設)。
  • javascript/dynamic: 不支援CommonJS和EcmaScript模組。
  • json: JSON資料,可以通過require和import匯入(.json檔案預設)。
  • webassembly/experimental: WebAssembly模式(目前處於實驗性階段,.wasm檔案預設)。

用法:module.rules 中的 type 就是新增加的屬性,用來支援不同的模組型別。

module:{
    rules:[{
        test:/\.special\.json$/,
        type:"javascript/auto",use:"special-loader"}]}

此外,現在webpack 按照 .wasm, .mjs, .js, 以及 .json 等副檔名的順序來解析。

javascript/esm 相比於 javascript/auto 處理ESM更加嚴格:具體表現在兩個方面:1. 匯入的名稱必須存在於匯入的模組中。2. 動態的模組(非ESM,例如CommonJS)只能通過預設 import 匯入,其他所有(包括名稱空間匯入)的匯入都會報錯。

2.3 用法

  • 必須在 “開發或者生產” 中選擇一種模式(這裡有一種隱藏模式 none,可以禁用一切功能)。1)生產模式不支援監聽,開發模式針對快速增量重建進行了優化。2)生產模式同樣支援模組串聯,即變數提升(此功能在webpack 3 中已經實現)。3)開發模式下支援註釋和提示,並且支援 eval 的source map。
  • 將 CLI 移動到 webpack-cli 中,你需要通過安裝 webpack-cli 使用 CLI。
  • 你可以使用 optimization.* 標誌來配置自己的自定義模式。
  • webpackInclude 和 webpackExclude 可以通過神奇的註釋來支援 import() ,他們允許在使用動態表示式時過濾檔案。
  • 使用 System.import() 會發出警告:1)可以使用 Rule.parser.system:true 關閉警告。2)你也可以使用 Rule.parser.system:false 關閉 System.import()。
  • 對於遷移到新的外掛系統的外掛 ProgressPlugin 現在顯示外掛名稱。
  • webpack 現在可以本地處理 JSON。如果用 loader 轉換 json 為 js,需要設定: type:”javascript/auto”。當然,不用 loader webpack 依然可以正常工作。

2.4 配置

  • 刪除了一些常用內建外掛:1)NoEmitOnErrorsPlugin -> optimization.noEmitOnErrors (生產模式預設)。2)ModuleConcatenationPlugin -> optimization.concatenateModules (生產模式預設)。3)NamedModulesPlugin -> optimization.namedModules (開發模式預設)。刪除了常用的 CommonsChunkPlugin -> optimization.splitChunks對於那些需要細粒度控制快取策略的人,可以通過 optimization.splitChunks和 optimization.runtimeChunk。 現在可以使用 module.rules[].resolve來配置解析。它與全域性配置合併。
  • optimization.minimize 用於控制minimizing的開關。 生產模式預設為開,開發模式預設為關。
  • optimization.minimizer 用於配置minimizers和選項。
  • 許多支援佔位符的配置選項現在也支援函式形式。
  • 錯誤的 options.dependencies 配置現在會丟擲異常。
  • sideEffects 可以通過 module.rules 覆蓋。
  • 新增 output.globalObject 配置選項以允許在執行時選擇全域性物件引用。
  • 無需顯式設定entry和output屬性,webpack預設設定entry屬性為./src,output的屬性為./dist。
  • 移除module.loaders。

2.5 優化

  • uglifyjs-webpack-plugin 升級到了 v 1,並且支援 ES6語法。
  • 可以在 package.json 中配置 sideEffects:false 。當設定這個欄位之後,標識在使用的庫裡沒有任何副作用。這意味著webpack可以從程式碼中安全地清除任何re-exports。
  • 使用JSONP陣列來代替JSONP函式 –> 非同步支援。
  • 引入新的 optimization.splitChunks 選項。
  • webpack 可以刪除無用程式碼,之前是由 Uglify 刪除無用的程式碼,現在 webpack 也可以刪除無用的程式碼。這可以有效防止在 import 無用的程式碼之後發生的崩潰。以下是一些內部優化:1)用 tap 呼叫替換 plugin 呼叫(新的外掛系統)。2)將許多廢棄的外掛遷移到新的外掛系統API。3)為 json 模組新增 buildMeta.exportsType:default。4)刪除了 Parser (parserStringArray, parserCalculatedStringArray) 中未使用的方法。

2.6 效能

  • 預設情況,UglifyJS 預設快取和並行化(並未完全實現快取和並行化,webpack5的里程碑)。
  • 釋出了一個新版本的外掛系統,所以事件鉤子和處理程式變的單一化。
  • 多個性能改進,特別是更快的增量重建。
  • 改進了RemoveParentModluesPlugin的效能。

2.7 不相容的改變(外掛、loader相關)

  • 新的外掛系統:1)外掛方法是向後相容的2)外掛現在應該這樣使用 Compiler.hooks.xxx.tap(<plugin name>, fn)
  • Chunk.chunks/parents/blocks 不再是陣列。在內部使用一個集合,並且有方法來訪問它。
  • Parser.scope.renamesParser.scope.definitions 不再是物件/陣列,而是Map/Set。
  • 解析器使用 StackedSetMap(類似於LevelDB的資料結構)而不是陣列。
  • 在應用外掛時不再設定 Compiler.options
  • 所有模組的構造引數都發生了變化。
  • options 合併到 ContextModuleresolveDependenciesoptions 物件中.
  • 更改並重命名 import() 的依賴關係
  • Compiler.resolvers 移入可通過外掛訪問的 Compiler.resolverFactory中。
  • Dependency.isEqualResource 已被替換為 Dependency.getResourceIdentifier
  • Template 方法都是靜態的。
  • 已經添加了一個新的 RuntimeTemplate 類,outputOptionsrequestShortener 已經被移動到這個類中。1)已經更新了許多方法來代替 RuntimeTemplate 的使用。2)我們計劃將訪問執行時的程式碼移動到這個新類中
  • Module.meta已被Module.buildMeta所取代
  • 已新增Module.buildInfo和Module.factoryMeta
  • Module的一些屬性已經被移動到新的物件中
  • 新增指向上下文選項的 loaderContext.rootContextloaders 可以使用它來建立相對於應用程式根目錄的東西。
  • 當啟用HMR時,將 this.hot 標誌新增到 loader 上下文中。
  • buildMeta.harmony 已被替換為 buildMeta.exportsType:namespace
  • chunk 圖已經改變:之前:Chunks 的連線與巢狀依賴關係有關。現在:ChunksGroups 的連線與引用依賴有關,按照順序串聯。之前:AsyncDependenciesBlocks 按順序引用 Chunks 列表。現在:AsyncDependenciesBlocks 引用一個 ChunkGroup。

★★ 注意:以上內容都是關於 loaders、plugins 重大的變化。

3、重點更新詳解

3.1 更好的預設值

直到今日,webpack 總是要求顯式地設定 entryoutput 屬性。webpack 4.0.0-beta.0 中,webpack 會自動設定你的 entry 屬性為 ./src 以及 output 的屬性為 ./dist。這意味著您不再需要配置檔案來啟動 webpack。接下來我們為你演示webpack 4.0.0-beta.0的便捷操作:

1、我們需要安裝好 webpack 之後,在 package.json 中新增如下指令碼即可啟動:

"scripts":{"build":"webpack"},

2、在工程中新增簡單示例程式碼如下圖(整個工程沒有 webpack 配置檔案,即可執行打包):

無配置示例

3、打包過程中我們發現有新特性的提示:

WARNING in configuration
The'mode' option has not been set.Set'mode' option to 'development'or'production' to enable defaults forthis environment.

這就是我們下節要說的內容模式設定

★★ 注意:入口預設為 ./src 如果缺少此資料夾會報錯!

> webpack --mode production
ERROR inEntrymodulenot found:Error:Can't resolve './src' in 'D:\workspace\github\Webpack-Example'

3.2 模式設定

以往的專案使用 webpack3 腳手架生成專案初始模板都會有兩個甚至三個配置檔案,比如webpack.base.conf.jswebpack.prod.conf.jswebpack.dev.conf.js 而現在可以做到一個配置檔案都不需要,直接在啟動命令中傳入引數 --mode development | production 達到區分不同模式的效果。

接下來修改 package.json 設定不同的模式:

"scripts":{"dev":"webpack --mode development","build":"webpack --mode production"},

重新執行 npm run devnpm run build 即可看到不同的打包結果:不同模式打包我們可以看到兩種模式的結果完全不同,下面我們會更深入的按照我們真實的需求來講解一些常用配置。

接下來這個配置是最常用到的,我們使用 webpack 的主要目的之一就是為了更好的支撐前段模組化的能力,既然需要模組化當然少不了程式碼分割,目前程式碼分割有以下幾種:

  • 通過 entry 分割不同入口,常用於多頁應用;
  • 通過 CommonsChunkPlugin 外掛來分割不同功能模組;
  • 通過動態 import 來分割。

下面我們主要講解 webpack 4.0.0-beta.0 版本的重大變化刪除了 CommonsChunkPlugin 外掛。

3.3 刪除 CommonsChunkPlugin

webpack 4.0.0-beta.0刪除了 CommonsChunkPlugin,以支援兩個新的選項(optimization.splitChunksoptimization.runtimeChunk)。

從webpack 4.0.0-beta.0 開始分割 Chunk 將不在使用 CommonsChunkPlugin 外掛,而是使用 optimization 配置項,具體的實現原理可以參考 CommonsChunkPlugin

由於還沒有正式官方文件出來,以下是我們通過實踐出的 optimization 配置方法:其中用到了新增的 splitChunks 屬性,此屬性看字面意思就明白是分割程式碼塊的選項,其下可配置項已在下面示例程式碼中列出(有興趣的朋友可以自行實踐):

entry:{
     vendor:['lodash']},...

optimization:{
     splitChunks:{
     chunks:"initial",// 必須三選一: "initial" | "all"(預設就是all) | "async" 
     minSize:0,// 最小尺寸,預設0
     minChunks:1,// 最小 chunk ,預設1
     maxAsyncRequests:1,// 最大非同步請求數, 預設1
     maxInitialRequests :1,// 最大初始化請求書,預設1
     name:function(){},// 名稱,此選項可接收 function
     cacheGroups:{// 這裡開始設定快取的 chunks
         priority:0,// 快取組優先順序
         vendor:{// key 為entry中定義的 入口名稱
             chunks:"initial",// 必須三選一: "initial" | "all" | "async"(預設就是非同步) 
             test:/react|lodash/,// 正則規則驗證,如果符合就提取 chunk
             name:"vendor",// 要快取的 分隔出來的 chunk 名稱 
             minSize:0,
             minChunks:1,
             enforce:true,
             maxAsyncRequests:1,// 最大非同步請求數, 預設1
             maxInitialRequests :1,// 最大初始化請求書,預設1
             reuseExistingChunk:true// 可設定是否重用該chunk(檢視原始碼沒有發現預設值)}}}},

以上就是 optimization.splitChunks 的所有可用的配置項屬性。

總結

以上就是我們初步整理的關於 webpack 4.0.0-beta.0 的新特性,包含了一部分的官方更新日誌的翻譯,還有我們自己試驗的一些屬性。當然如果你有興趣,也可以等到正式的官方文件釋出之後進行實踐。如果上面的資訊不能夠完全滿足你的興趣,還請關注官方日誌。在未來不到一個月的時間裡,webpack 將對外掛、載入器以及整個生態系統進行更加嚴格的測試,併發布最終的官方穩定版本。如果你喜歡 webpack,你可以參與使用 webpack 4.0.0-beta.0。測試階段發現、解決的問題越多,正式版本才會更加穩定。

示例程式碼

京東前端

擴充套件閱讀