自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Webpack5 實(shí)踐 - 構(gòu)建效率倍速提升!

開發(fā) 開發(fā)工具
對(duì)于前端構(gòu)建工具 Webpack、babel、eslint 等的每一次升級(jí),就像剛剛經(jīng)歷一場(chǎng)地震似得,最不想面對(duì)的就是處理各種 API 的不兼容性,有時(shí)還會(huì)出現(xiàn)一些奇奇怪怪的問(wèn)題,為什么還要升呢?并不是為了給自己找事,還是要講究投入產(chǎn)出比的,也就是最終的收益是要大于產(chǎn)出比的。

 [[409156]]

本文轉(zhuǎn)載自微信公眾號(hào)「五月君」,作者五月君。轉(zhuǎn)載本文請(qǐng)聯(lián)系五月君公眾號(hào)。  

對(duì)于前端構(gòu)建工具 Webpack、babel、eslint 等的每一次升級(jí),就像剛剛經(jīng)歷一場(chǎng)地震似得,最不想面對(duì)的就是處理各種 API 的不兼容性,有時(shí)還會(huì)出現(xiàn)一些奇奇怪怪的問(wèn)題,為什么還要升呢?并不是為了給自己找事,還是要講究投入產(chǎn)出比的,也就是最終的收益是要大于產(chǎn)出比的。

前段在團(tuán)隊(duì)內(nèi)部對(duì) Webpack v5 帶來(lái)的一些新特性做一些 Research,相較于一些項(xiàng)目的構(gòu)建工具版本(Webpack v3)做了一個(gè)對(duì)比,在構(gòu)建效率這塊是有質(zhì)的飛躍的,同樣相對(duì)于 Webpack v4 也是有很大提升的。本文是本次升級(jí)過(guò)程中的實(shí)踐(踩坑)記錄,分享一些值得關(guān)注的功能、一些重大的改變、遇到的一些 NPM 組建兼容性問(wèn)題,希望能給予讀者朋友一些參考和幫助。

先上一張腦圖,涵蓋本文主題!

構(gòu)建效果對(duì)比

基于一些項(xiàng)目做了一些測(cè)試,首次構(gòu)建相較于之前提速將近 2 倍多,二次構(gòu)建差不多 2s 左右,效果更顯著,修改文件后的增量構(gòu)建,差不多也在幾秒鐘可完成,整體構(gòu)建效率提升還是很明顯的,除此之外打包后的文件大小也比之前小了一些,但之間的差距不是特別的大,重點(diǎn)還是構(gòu)建效率大幅提升。

構(gòu)建效率上之所以有這么大的性能提升,這與它的基于文件系統(tǒng)的持久化緩存是有很大幫助的,下文會(huì)講解。內(nèi)部的項(xiàng)目數(shù)據(jù)就不便再這里展示了,文末提供了一些來(lái)自社區(qū)的實(shí)踐,也可以看到一些數(shù)據(jù)對(duì)比。

下面,基于之前 Research 時(shí)寫的一些 Demo 可以對(duì)比下使用了持久化緩存在初次構(gòu)建、二次無(wú)文件改動(dòng)構(gòu)建、改動(dòng)文件后增量構(gòu)建三種情況下的效果對(duì)比,也可以顯著的看到一些效果。

代碼壓縮(生產(chǎn)環(huán)境)

JavaScript 代碼壓縮

Webpack5 在生產(chǎn)環(huán)境下默認(rèn)使用自帶的 TerserPlugin 插件(無(wú)需安裝)來(lái)做代碼壓縮,這個(gè)插件也被認(rèn)為是在代碼壓縮方面性能是較好的。無(wú)需再借助 UglifyjsPlugin、ParallelUglifyPlugin 這些插件了。

如果你使用的是 webpack4 版本需要手動(dòng)安裝 yarn add terser-webpack-plugin -D 并將插件添加到生產(chǎn)環(huán)境的配置文件中。

以下是使用示例,在 Webpack v5 的生產(chǎn)環(huán)境默認(rèn)開啟。

  1. const TerserPlugin = require("terser-webpack-plugin"); 
  2.  
  3. module.exports = { 
  4.   optimization: { 
  5.     minimize: true
  6.     minimizer: [new TerserPlugin()], 
  7.   }, 
  8. }; 

支持做一些自定義的配置:文件過(guò)濾、并發(fā)運(yùn)行等,詳細(xì)參見 Webpack 文檔 TerserWebpackPlugin[1]。

  • test:匹配需要壓縮的文件。
  • include:匹配包含的目錄。
  • exclude:匹配不需要包含的目錄。
  • parallel:多進(jìn)程并發(fā)運(yùn)行,默認(rèn) os.cpus().length - 1。
  1. module.exports = { 
  2.   optimization: { 
  3.     minimize: true
  4.     minimizer: [ 
  5.       new TerserPlugin({ 
  6.         test: /\.js(\?.*)?$/i, 
  7.         include: /\/includes/, 
  8.         exclude: /\/excludes/, 
  9.         parallel: true 
  10.         // more ... 
  11.       }), 
  12.     ], 
  13.   }, 
  14. }; 

CSS 文件分離

CSS 壓縮之前先做的一項(xiàng)工作是 CSS 和 JS 文件分離,如果是從 Webpack v3 升級(jí)到 v5 會(huì)遇到一些問(wèn)題,之前使用的是 extract-text-webpack-plugin 在 webpack v5 會(huì)收到廢棄提醒,建議使用 **MiniCssExtractPlugin** 這個(gè)插件,本插件基于 webpack v4 的新特性(模塊類型)構(gòu)建。

與 extract-text-webpack-plugin 相比,擁有這些特性:異步加載、沒(méi)有重復(fù)的編譯(性能提升)、更容易使用、特別針對(duì) CSS 開發(fā)。

下面是一個(gè)配置,這里還有些優(yōu)化,生產(chǎn)模式使用 mini-css-extract-plugin 插件分離 JS/CSS 文件實(shí)現(xiàn)并行加載,而開發(fā)環(huán)境選擇 style-loader 它可以使用多個(gè)標(biāo)簽將 CSS 插入到 DOM 中,并且反應(yīng)會(huì)更快。

  1. const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 
  2. module.exports = { 
  3.   module: { 
  4.     rules: [ 
  5.       { 
  6.         test: /\.css$/i, 
  7.         use: [ 
  8.           devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 
  9.           'css-loader' 
  10.         ], 
  11.       }, 
  12.     ], 
  13.   }, 
  14.   plugins: [new MiniCssExtractPlugin()], 
  15. }; 

關(guān)于 CSS 分割插件的更詳細(xì)配置 Webpack 文檔 mini-css-extract-plugin[2]。

CSS 打包后加載圖片 404?

生產(chǎn)環(huán)境我們使用 mini-css-extract-plugin 插件分離 CSS 文件,如果你在 CSS 里引用了圖片,可能會(huì)遇到為什么打包后 CSS 里引用的圖片加載時(shí) 404 了?

在 Webpack 的 output 選項(xiàng)中有一個(gè) publicPath 配置,它指定了應(yīng)用程序中所有資源的基礎(chǔ)路徑。

  1. module.exports = { 
  2.   output: { 
  3.     publicPath: 'auto' 
  4.   } 

Webpack loader 的 options 選項(xiàng)中也有一個(gè) publicPath 配置,為 CSS 內(nèi)的圖片、文件等外部資源指定一個(gè)自定義的公共路徑,默認(rèn)值為 output.publicPath。如果出現(xiàn)打包后 CSS 內(nèi)圖片 404 的可以檢查下這里的配置是否有問(wèn)題。

  1. const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 
  2. module.exports = { 
  3.   module: { 
  4.     rules: [ 
  5.       { 
  6.         test: /\.css$/i, 
  7.         use: [ 
  8.           devMode ? 'style-loader' : { 
  9.             loader: MiniCssExtractPlugin.loader, 
  10.             options: { 
  11.               publicPath: '../' 
  12.             } 
  13.           }, 
  14.         ], 
  15.       }, 
  16.     ], 
  17.   }, 
  18.   plugins: [new MiniCssExtractPlugin()], 
  19. }; 

CSS 代碼壓縮

CSS 壓縮之前會(huì)使用 optimize-css-assets-webpack-plugin 這個(gè)插件,在 webpack v5 之后推薦使用 css-minimizer-webpack-plugin 這個(gè)插件。

  1. const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); 
  2. module.exports = { 
  3.   optimization: { 
  4.     minimizer: [ 
  5.       new CssMinimizerPlugin(), 
  6.     ], 
  7.   }, 
  8. }; 

性能提升核心緩存優(yōu)化

之前通過(guò) cache-loader、babel-loader?cacheDirectory 在配置 cacheDirectory:true 實(shí)現(xiàn)將編譯結(jié)果寫入磁盤或者通過(guò) hard-source-webpack-plugin 插件。

Webpack5 自帶緩存能力,會(huì)緩存生成的 webpack module 和 chunk,對(duì)于二次構(gòu)建有了很大的性能提升。通過(guò) cache 屬性配置,分為內(nèi)存和文件兩種緩存方式,默認(rèn)在生產(chǎn)環(huán)境是禁用的,需自行開啟。

基于內(nèi)存緩存

當(dāng)在開發(fā)環(huán)境默認(rèn)設(shè)置為 memory,基于內(nèi)存的緩存,除了下面的方式配置外,也可通過(guò) cache: true 配置。

  1. module.exports = { 
  2.   cache: { 
  3.     type: 'memory' 
  4.   }, 
  5. }; 

基于 FileSystem 的持久化緩存

基于內(nèi)存的緩存,只有在服務(wù)運(yùn)行中,才有效,每次的單獨(dú)構(gòu)建是利用不了緩存的,webpack5 對(duì)于緩存另一個(gè)比較好的功能是提供了基于文件系統(tǒng)的持久化緩存。

基于文件系統(tǒng)的持久化緩存無(wú)論在單獨(dú)構(gòu)建或連續(xù)構(gòu)建(可以指熱更新操作)中都可應(yīng)用,首先它會(huì)查看內(nèi)存緩存,如果未命中,則降級(jí)到文件系統(tǒng)緩存。

應(yīng)用很簡(jiǎn)單,設(shè)置 type:filesystem。默認(rèn)情況下它位于 node_modules/.cache/webpack/ 目錄,我們還可以通過(guò) name 屬性修改它的名稱,例如,我們通過(guò)不同的環(huán)境 NODE_ENV 來(lái)區(qū)別不同環(huán)境的緩存。

當(dāng) type 設(shè)置為 filesystem 后,有很多屬性是可以配置的,參見 Webpack 文檔 cache[3]。

  1. module.exports = { 
  2.   cache: { 
  3.     type: 'filesystem'
  4.     buildDependencies: { 
  5.       config: [__filename], 
  6.     }, 
  7.     name: `${ process.env.NODE_ENV || 'development'}-cache` 
  8.   } 

緩存失效

基于內(nèi)存的緩存每一次重新運(yùn)行都是一次新的構(gòu)建。需要注意的是持久化緩存,當(dāng)你修改了文件或傳遞了一些參數(shù),發(fā)現(xiàn)最終展現(xiàn)的效果沒(méi)有被更改,通常這與持久化緩存的緩存策略相關(guān)。

出于性能考慮,緩存會(huì)跳過(guò) node_modules 認(rèn)為這會(huì)極大降低 webpack 執(zhí)行速度,建議是不要手動(dòng)編輯 node_modules。通常也不會(huì)這么干直接去修改 node_modules。

有些操作也會(huì)使緩存失效,例如:當(dāng) NPM 升級(jí) loader、plugin、更改配置等。

Webpack 提供了 buildDependencies、name、version 三種方式可以使構(gòu)建緩存失效。

方法一:cache.buildDependencies

buildDependencies 指定構(gòu)建過(guò)程中受影響的代碼依賴,默認(rèn)為 webpack/lib,當(dāng) node_modules 中的 webpack 或其依賴項(xiàng)發(fā)生任何變化,當(dāng)前的緩存即失效。

還有一個(gè)是指定的配置文件 config: [__filename] 或配置文件的依賴項(xiàng)發(fā)生變化,也會(huì)失效。

  1. module.exports = { 
  2.   cache: { 
  3.     type: 'filesystem'
  4.     buildDependencies: { 
  5.       defaultWebpack: ["webpack/lib/"], 
  6.       config: [__filename], 
  7.     }, 
  8.     name: `${ process.env.NODE_ENV || 'development'}-cache` 
  9.   } 

方法二:cache.version

如果是把構(gòu)建工具封裝為一個(gè)單獨(dú)的工具包,類似于 react-scripts 這種的,理論上每次升級(jí)工具包,就需要重新編譯的,之前在一次本地測(cè)試時(shí)發(fā)現(xiàn)工具包升級(jí)后緩存沒(méi)有失效,如果出現(xiàn)這種情況的可以在 cache 里加上 version 配置指向 package.json 里的 version。

  1. module.exports = { 
  2.   cache: { 
  3.     type: 'filesystem'
  4.     version: `${packageJson.version}` 
  5.   } 

有時(shí)配置文件或者代碼沒(méi)有修改,但是會(huì)依賴于命令行傳遞值想使緩存失效,同樣也可在 version 上加上這些命令行傳遞的值做為版本控制。

  1. module.exports = { 
  2.   cache: { 
  3.     type: 'filesystem'
  4.     version: `${process.env.CLI_VALUE}` 
  5.   } 

當(dāng) version 依賴于多個(gè)值時(shí),可以將多個(gè)值做個(gè) md5 生成一串唯一的字符串做為版本也可。

方法三:cache.name

name 屬性比較好的是可以保存多個(gè)緩存目錄,例如通過(guò) process.env.NODE_ENV 區(qū)分不同的環(huán)境。

  1. module.exports = { 
  2.   cache: { 
  3.     type: 'filesystem'
  4.     name: `${ process.env.NODE_ENV || 'development'}-cache` 
  5.   } 

持久化緩存這塊也有很多的東西可以講,詳情參見 [譯] webpack 5 之持久化緩存[4]。

長(zhǎng)期緩存優(yōu)化

Webpack 5 新增了長(zhǎng)期緩存算法,以確定性的方式為模塊和分塊分配短的(3 或 5 位)數(shù)字 ID,這是包大小和長(zhǎng)期緩存之間的一種權(quán)衡,生產(chǎn)環(huán)境默認(rèn)開啟以下配置。在減小文件打包大小同時(shí)也利于瀏覽器長(zhǎng)期緩存(不會(huì)因?yàn)閯h除或新增一個(gè)模塊而導(dǎo)致大量緩存文件失效)。

  1. // production default 
  2. module.exports = { 
  3.   optimization: { 
  4.     moduleIds: 'deterministic'
  5.     chunkIds: 'deterministic' 
  6.     mangleExports: 'deterministic' 
  7.   } 

Webpack v5 VS v4 模塊 ID

Webpack v4 及之前的 moduleId 默認(rèn)是自增的,例如 0.xxx.js、1.xxx.css、2.xxx.js 如果更改模塊數(shù)量(即使內(nèi)容沒(méi)有變化),也會(huì)導(dǎo)致模塊文件重新發(fā)生改變,不利于長(zhǎng)期緩存。

不同的版本也提供了不同的解決方案,webpack v4 之前使用 HashedModuleIdsPlugin 插件覆蓋默認(rèn)的模塊 ID 規(guī)則,在 webpack v4 中可以配置 optimization.moduleIds = 'hashed' 解決。這幾種方案都是使用模塊路徑生成的 hash 做為 moduleId。

Webpack v5 生產(chǎn)環(huán)境默認(rèn) optimization.moduleIds='deterministic' 無(wú)需更改。

Webpack v5 VS v4 Chunk ID

webpack v4 及之前的 chunkId 默認(rèn)也是遞增的,如果在 entry 配置中新增或刪除一個(gè)元素,chunkId 也會(huì)隨著遞增或遞減。

webpack v4 之前使用 NamedChunksPlugin 插件覆蓋默認(rèn)的 chunkId 規(guī)則,在 webpack v4 中可以配置 optimization.chunkIds = 'named' 解決。

Webpack v5 生產(chǎn)環(huán)境默認(rèn) optimization.chunkIds='deterministic' 無(wú)需更改。

真正的內(nèi)容哈希

另外,當(dāng)使用 [contenthash] 時(shí),webpack5 將使用真正的文件內(nèi)容做為哈希值,這個(gè)類似于協(xié)商緩存 Etag,不一樣的是還有一些優(yōu)化,如果你只是刪除了代碼中的一些注釋或重新命名變量,而這種情況代碼邏輯是沒(méi)有修改的,這些變化在壓縮后是不可見的,不會(huì)導(dǎo)致 [contenthash] 也發(fā)生變化。

如果是從 webpack v3 升級(jí)到 v5 的,HashedModuleIdsPlugin、NamedChunksPlugin 這些插件是可以去掉的,webpack v5 環(huán)境默認(rèn)開啟新的算法,無(wú)需再配置。

參考文檔 Webpack release 日志記錄 — 重大變更:長(zhǎng)期緩存[5]。

原生支持資源模塊

Webpack v5 內(nèi)置了資源模塊(assert),用來(lái)處理資源文件(圖片、字體等),在之前是通過(guò)配置額外的 loader,例如 raw-loader、file-loader、url-loader 實(shí)現(xiàn)的。

Webpack v4 資源文件處理

下面是一段 webpack v4 及之前版本的資源文件處理配置,當(dāng)匹配的文件大小如果小于 limit 限制,將其處理成 data URI 內(nèi)聯(lián)到 bundle 中,否則生成文件(使用 file-loader)輸出到目錄中,url-loader 內(nèi)置了 file-loader 對(duì)文件的處理。

  1.   test: /\.(jpe?g|png|gif|svg)$/, 
  2.   use: [ 
  3.     { 
  4.       loader: 'url-loader'
  5.       options: { 
  6.         limit: 1024 * 10 
  7.       } 
  8.     } 
  9.   ] 
  10. }, 

Webpack v5 新的資源文件處理

Webpack v5 不再需要安裝 url-loader 處理資源文件,內(nèi)置了資源模塊類型,通過(guò) type 定義,用來(lái)替換之前需要額外配置 loader 的方式。

  • asset/resource:將文件打包輸出并導(dǎo)出 URL,類似于 file-loader。
  • asset/inline:導(dǎo)出一個(gè)資源的 data URI,編碼到 bundle 中輸出,類似于 url-loader。
  • asset/source:導(dǎo)出資源的源代碼,類似于 raw-loader。
  • asset:提供了一種通用的資源類型,根據(jù)設(shè)置的 Rule.parser.dataUrlCondition.maxSize 自動(dòng)的在 asset/resource、asset/inline 之間做選擇,小于該大小指定的文件視為 inline 模塊類型,否則視為 resource 模塊類型。

下面是一個(gè)示例,大于 4kb 的輸出到目錄 static 中。

  1.   test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i, 
  2.   type: "asset"
  3.   parser: { 
  4.     dataUrlCondition: { 
  5.       maxSize: 4 * 1024 // 4kb 
  6.     } 
  7.   }, 
  8.   generator: { 
  9.     filename: 'static/[hash][ext][query]' 
  10.   } 
  11. }, 

參考文檔 Webpack 文檔 Assert module[6]。

強(qiáng)大的 tree-shaking 能力

tree-shaking 是一個(gè)術(shù)語(yǔ),翻譯為中文為 “樹搖”,想想一下一顆長(zhǎng)滿果子的樹木,其中有些已經(jīng)熟透了,當(dāng)搖晃樹木時(shí)是不是一部分會(huì)被搖掉。

[[409157]]

圖片來(lái)源:https://cdn.pixabay.com/photo/2019/05/16/23/39/apple-tree-4208594_1280.jpg

對(duì)于我們代碼層面來(lái)說(shuō),那些上下文未引用的 JavaScript 代碼,也可以通過(guò)工具移除(“搖掉”),實(shí)現(xiàn)打包體積的優(yōu)化。

嵌套的 tree-shaking

在這種情況下,可以刪除未使用的變量 b,生產(chǎn)環(huán)境默認(rèn)開啟。

  1. // inner.js 
  2. export const a = 1; 
  3. export const b = 2; 
  4.  
  5. // module.js 
  6. export * as inner from './inner'
  7.  
  8. // user.js 
  9. import * as module from './module'
  10. console.log(module.inner.a); 

內(nèi)部模塊 tree-shaking

Webpack v5 還增加了模塊導(dǎo)出和引用之間的依賴關(guān)系分析,通過(guò)配置 optimization.innerGraph 控制,生產(chǎn)環(huán)境默認(rèn)開啟。

以下示例,something 只有在使用 test 導(dǎo)出時(shí)才會(huì)使用。

  1. import { something } from './something'
  2.  
  3. function usingSomething() { 
  4.   return something; 
  5.  
  6. export function test() { 
  7.   return usingSomething(); 

支持 CommonJS Tree Shaking

新增 CommonJS 模塊的導(dǎo)出和引用之間的依賴分析,下例,可以刪除未使用的變量 b。

  1. // inner.js 
  2. exports.a = 1; 
  3. exports.b = 2; 
  4.  
  5. // module.js 
  6. exports.inner = require('./inner'); 
  7.  
  8. // user.js 
  9. const module = require('./module'); 
  10. console.log(module.inner.a); 

參考 Webpack 文檔 tree-shaking[7]。

Node.js 調(diào)用 webpack API

之前在團(tuán)隊(duì)內(nèi)部,基于 webpack 這些構(gòu)建工具封裝了適合團(tuán)隊(duì)內(nèi)部的構(gòu)建工具模塊,是通過(guò) API 調(diào)用的,有些問(wèn)題還是要注意下。

生產(chǎn)環(huán)境

調(diào)用 webpack() 創(chuàng)建一個(gè) compiler 實(shí)例,之后調(diào)用 run() 方法執(zhí)行,需要注意的是在完成之后記得關(guān)閉 compiler,這樣低優(yōu)先級(jí)的工作(比如持久緩存)就有機(jī)會(huì)完成,否則,有時(shí)候會(huì)發(fā)現(xiàn)每次都是重新構(gòu)建沒(méi)有利用上緩存。

下例中的 stats 參數(shù)可以獲取到代碼編譯過(guò)程產(chǎn)生的錯(cuò)誤和警告、計(jì)時(shí)信息、module 和 chunk 信息,如果想達(dá)到 cli 環(huán)境下的日志輸出格式,調(diào)用 stats.toString() 方法即可。

  1. const compiler = webpack(config); 
  2. return new Promise((resolve, reject) => { 
  3.   compiler.run((err, stats) => { 
  4.     if (err) { 
  5.       return reject(err); 
  6.     } 
  7.  
  8.     console.log(stats.toString({ 
  9.       chunks: false
  10.       colors: true 
  11.     })); 
  12.  
  13.     compiler.close(closeErr => { 
  14.       if (closeErr) { 
  15.         console.log(chalk.red(`compiler close failed with message ${closeErr.message}`)); 
  16.       } 
  17.     }); 
  18.  
  19.     return resolve(stats); 
  20.   }); 
  21. }); 

開發(fā)環(huán)境

與生產(chǎn)環(huán)境 API 調(diào)用不同,開發(fā)環(huán)境我們需要熱更新,在創(chuàng)建一個(gè) compiler 后需要調(diào)用 webpack-dev-server 插件。

還有個(gè)問(wèn)題是 devServer 中的配置選項(xiàng)將被忽略,但可以將配置選項(xiàng)作為第二個(gè)參數(shù)傳入。

  1. const compiler = webpack(config); 
  2. const devServerOptions = Object.assign({}, config.devServer, { 
  3.   port: port, 
  4.   host: DEFAULT_HOST, 
  5.   opentrue
  6. }); 
  7. const server = new WebpackDevServer(compiler, devServerOptions); 
  8. server.listen(port, DEFAULT_HOST); 

參考文檔 Webpack 文檔 Node.js API 接口[8]。

原生 Web Worker 支持

從 webpack 5 開始,使用 Web Workers 代替 worker-loader,這種語(yǔ)法也是為了實(shí)現(xiàn)不使用 bundler 就可以運(yùn)行代碼。

Web Worker 是解決一些密集型的任務(wù),例如一些加解密、圖片處理等一些耗時(shí)的計(jì)算任務(wù)可以放置于工作線程處理,處理完畢在通知到主線程,在處理的過(guò)程不會(huì)影響用戶在界面上的一些其它操作。

  1. const worker = new Worker(new URL('./worker-calculate.js', import.meta.url)); 
  2. worker.postMessage({ 
  3.   question: 
  4.     'The Answer to the Ultimate Question of Life, The Universe, and Everything.'
  5. }); 
  6. worker.onmessage = ({ data: { answer } }) => { 
  7.   console.log(answer); 
  8. }; 
  9.  
  10. // worker-calculate.js 
  11. self.onmessage = ({ data: { question } }) => { 
  12.   self.postMessage({ 
  13.     answer: 42, 
  14.   }); 
  15. }; 

Web Workers 可以在瀏覽器中的原生 ECMAScript 模塊中使用,也可以用于 Node.js 中,如果采用 ESM 模塊規(guī)范,Node.js 需要 >= 12.17.0。

  1. import { Worker } from 'worker_threads'
  2. new Worker(new URL('./worker.js', import.meta.url)); 

Node.js 通過(guò) worker_threads 模塊提供支持,在 Node.js 中如果你使用 CommonJS 規(guī)范在 v10.0.5 版本就已經(jīng)支持了。

  1. const { Worker } = require('worker_threads'); 

更多詳情參考 webpack 文檔 Web Workers[9]。

其它 NPM 組件兼容性問(wèn)題

開發(fā)環(huán)境熱更新

如果是從 webpack v3.x 升級(jí)的,會(huì)發(fā)現(xiàn)之前的熱更新方式會(huì)報(bào)如下錯(cuò)誤。

  1. Error: Cannot find module 'webpack/bin/config-yargs' 

Webpack v5 使用 webpack serve 啟動(dòng)開發(fā)環(huán)境,解決這個(gè)問(wèn)題就是重新安裝 webpack-cli、還有 webpack-dev-server 也是需要安裝的。

  1. // For webpack-cli 3.x: 
  2. "scripts": { "start:dev""webpack-dev-server" } 
  3.  
  4. // For webpack-cli 4.x: 
  5. "scripts": { "start:dev""webpack serve" } 

問(wèn)題參考 cannot-find-module-webpack-bin-config-yargs。

compiler.plugin is not a function with InterpolateHtmlPlugin

可能會(huì)遇到以下錯(cuò)誤:

  1. TypeError: compiler.plugin is not a function 
  2.     at InterpolateHtmlPlugin.apply (/Users/qufei/Documents/code/f-designer-tool-webpack5-test/node_modules/react-dev-utils/InterpolateHtmlPlugin.js:25:14) 

單獨(dú)安裝插件 yarn add -D interpolate-html-plugin 替換 InterpolateHtmlPlugin = require('react-dev-utils/interpolate-html-plugin'); 為 const InterpolateHtmlPlugin = require('interpolate-html-plugin');

最后確保 InterpolateHtmlPlugin 出現(xiàn)在插件列表中的 HtmlWebpackPlugin 之后。

webpack.NamedModulesPlugin is not a constructor with NamedModulesPlugin

當(dāng)開啟 HMR 的時(shí)候使用該插件會(huì)顯示模塊的相對(duì)路徑,該插件已廢棄,在 Webpack4 中建議設(shè)置為 optimization.namedModules,但是在 Webpack5 也被廢棄,如果需要請(qǐng)改為 optimization.moduleIds: 'named',在 Webpack5 中的建議是 “請(qǐng)考慮將 optimization.moduleIds 和 optimization.chunkIds 從你 webpack 配置中移除。使用默認(rèn)值會(huì)更合適,因?yàn)樗鼈儠?huì)在 production 模式 下支持長(zhǎng)效緩存且可以在 development 模式下進(jìn)行調(diào)試。” 參見 https://webpack.docschina.org/migrate/5/#clean-up-configuration

移除 Node.js 模塊 Polyfills

Webpack5 移除了 Node.js 模塊的 Polyfills,更專注于前端模塊兼容。認(rèn)為這會(huì)在構(gòu)建時(shí)給 bundle 附加龐大的 Polyfills,大部分情況下也并非必須的,如果你的模塊或你安裝的第三方模塊引用了 cypto、process 這些模塊,就會(huì)看到報(bào)錯(cuò)。

  1. process is not a function 
  2. xxx is not a function 

參考 automatic-nodejs-polyfills-removed,對(duì)于 webpack v5,可以從 webpack.config.js 的相應(yīng)插件部分引用 process/browser。

參考 webpack-bundle-js-uncaught-referenceerror-process-is-not-defined。

  1. const webpack = require('webpack'
  2. module.exports = { 
  3.   plugins: [ 
  4.     // fix "process is not defined" error: 
  5.     // (do "npm install process" before running the build) 
  6.     new webpack.ProvidePlugin({ 
  7.       process: 'process/browser'
  8.     }), 
  9.   ] 

compiler.plugin is not a function with react-dev-utils/WatchMissingNodeModulesPlugin

  1. new WatchMissingNodeModulesPlugin(), 
  2.  
  3. // 運(yùn)行之后報(bào)錯(cuò) 
  4. // TypeError: compiler.plugin is not a function 
  5. //      at WatchMissingNodeModulesPlugin.apply (/Users/xxx/node_modules/react-dev-utils/WatchMissingNodeModulesPlugin.js:20:14) 

這個(gè)錯(cuò)誤是在 Webpack 4 upgrade PR,升級(jí) react-dev-utils yarn add react-dev-utils -D。

babel-eslint has been deprecated

之前在使用 eslint 代碼檢查時(shí),如果有用到 eslint 不支持的試驗(yàn)性特性時(shí)會(huì)需要用到 babel-eslint,但是這個(gè)項(xiàng)目已經(jīng)廢棄了,到官網(wǎng)會(huì)看到這樣一句話:

  1. babel-eslint is now @babel/eslint-parser. This package will no longer receive updates. 

現(xiàn)在推薦使用 @babel/eslint-parser 代替。

更多新功能

  • Top Level Await 支持:目前在 Webpack v5 計(jì)劃中屬于試驗(yàn)性支持,可通過(guò)開啟 experiments.topLevelAwait 配置支持,這對(duì)于文件頭部初始化資源很有用,無(wú)需讓 await 必須在 async 里面。參考 Webpack v5 配置#experiments。
  • 模塊聯(lián)邦(Federated Modules):是 webpack v5 增加的一個(gè)新功能,為前端項(xiàng)目打包模式提供了新的方式,對(duì)多個(gè)不存在依賴關(guān)系的多個(gè)項(xiàng)目可以獨(dú)立構(gòu)建組成一個(gè)應(yīng)用程序,從開發(fā)者的角度看,模塊可以從遠(yuǎn)程構(gòu)建中導(dǎo)入。這通常稱為微前端,也并不僅限于此。更多可參考 Webpack 提供的單獨(dú)指南 module-federation,也可看看下面的社區(qū)實(shí)踐。
  • 原生支持 WebAssembly 構(gòu)建:webpack v5 原生支持了 WebAssembly 的代碼構(gòu)建,只需開啟 experiments.syncWebAssembly 配置即可,這個(gè)功能也屬于試驗(yàn)性支持。
  • ... 更多功能參考 webpack v5 release 日志。

來(lái)自社區(qū)實(shí)踐

  • 字節(jié):Webpack5 新特性業(yè)務(wù)落地實(shí)戰(zhàn)
  • 騰訊:構(gòu)建效率大幅提升,webpack5 在企鵝輔導(dǎo)的升級(jí)實(shí)踐
  • 螞蟻:調(diào)研 Federated Modules,應(yīng)用秒開,應(yīng)用集方案,微前端加載方案改進(jìn)等
  • 百度:Webpack 5 升級(jí)實(shí)驗(yàn)
  • 飛書:Webpack5 上手測(cè)評(píng)

因?yàn)槲⑿艑?duì)外鏈的限制,文中有些鏈接不能打開,可以 “閱讀原文” 查看。

參考資料

[1]Webpack 文檔 TerserWebpackPlugin: https://webpack.docschina.org/plugins/terser-webpack-plugin/

[2]Webpack 文檔 mini-css-extract-plugin: https://webpack.docschina.org/plugins/mini-css-extract-plugin

[3]Webpack 文檔 cache: https://webpack.docschina.org/configuration/other-options/#cache

[4][譯] webpack 5 之持久化緩存: https://juejin.cn/post/6844903967793627149

[5]Webpack release 日志記錄 — 重大變更:長(zhǎng)期緩存: https://webpack.docschina.org/blog/2020-10-10-webpack-5-release/#major-changes-long-term-caching

[6]Webpack 文檔 Assert module: https://webpack.docschina.org/guides/asset-modules/

[7]Webpack 文檔 tree-shaking: https://www.webpackjs.com/guides/tree-shaking/

[8]Webpack 文檔 Node.js API 接口: https://webpack.docschina.org/api/node/

[9]webpack 文檔 Web Workers: https://webpack.docschina.org/guides/web-workers/

 

責(zé)任編輯:武曉燕 來(lái)源: 五月君
相關(guān)推薦

2022-01-20 10:56:53

Webpack5持久化緩存

2022-04-13 08:04:40

項(xiàng)目應(yīng)用程序代碼

2021-12-24 08:01:44

Webpack優(yōu)化打包

2022-09-02 09:09:25

項(xiàng)目ReactES6

2021-09-27 08:16:38

Webpack 前端Cache

2022-09-23 15:23:08

webpack5改變代碼

2023-04-27 08:35:20

Webpack 4性能優(yōu)化

2021-12-19 07:21:48

Webpack 前端插件機(jī)制

2021-12-21 14:00:25

WebpackDevServer的開發(fā)

2015-11-11 16:36:22

OceanStor存儲(chǔ)華為

2017-03-24 10:56:21

Webpack技巧建議

2017-05-02 16:29:11

Webpack技巧建議

2015-11-05 17:58:22

2025-02-04 10:00:30

Spring支付系統(tǒng)

2023-11-03 15:33:22

Docker鏡像云計(jì)算

2009-07-20 09:51:55

提升Windows20企業(yè)部署

2019-10-18 15:35:16

Python編程語(yǔ)言高級(jí)用法

2021-10-25 10:23:49

Webpack 前端Tree shakin
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)