一、常用plugin
-
html-webpack-plugin:生成一個html檔案,該檔案會自動引入所有生成的bundle。
const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { ...... plugins: [ new HtmlWebpackPlugin({ // 以 public/index.html 為模板建立檔案 // 新的html檔案有兩個特點:1. 內容和原始檔一致 2. 自動引入打包生成的js等資源 template: path.resolve(__dirname, "public/index.html"), }) ] }
-
mini-css-extract-plugin:將css檔案打包到單獨的檔案,而不是打包到js中。
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { ...... module: { rules: [ { // 用來匹配 .css 結尾的檔案 test: /\.css$/, // use 陣列裡面 Loader 執行順序是從右到左 use: [MiniCssExtractPlugin.loader, "css-loader"], } ] }, ...... plugins: [ // 提取css成單獨檔案 new MiniCssExtractPlugin({ // 定義輸出檔名和目錄 filename: "static/css/main.css", }), ] }
-
css-minimizer-webpack-plugin:css壓縮
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); module.exports = { ...... plugins: [ // css壓縮 new CssMinimizerPlugin() ] }
-
image-minimizer-webpack-plugin:壓縮圖片
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); module.exports = { ...... optimization: { minimizer: [ // css壓縮也可以寫到optimization.minimizer裡面,效果一樣的 new CssMinimizerPlugin(), // 當生產模式會預設開啟TerserPlugin,但是我們需要進行其他配置,就要重新寫了 new TerserPlugin({ parallel: threads, // 開啟多程序 }), // 壓縮圖片 new ImageMinimizerPlugin({ minimizer: { implementation: ImageMinimizerPlugin.imageminGenerate, options: { plugins: [ ["gifsicle", { interlaced: true }], ["jpegtran", { progressive: true }], ["optipng", { optimizationLevel: 5 }], [ "svgo", { plugins: [ "preset-default", "prefixIds", { name: "sortAttrs", params: { xmlnsOrder: "alphabetical", }, }, ], }, ], ], }, }, }), ], }, }
-
@vue/preload-webpack-plugin:在空閒時間載入後續需要使用的資源
const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin"); module.exports = { plugins: [ new PreloadWebpackPlugin({ rel: "preload", // preload相容性更好 as: "script", // rel: 'prefetch' // prefetch相容性更差 }), ] }
-
workbox-webpack-plugin:提供離線訪問功能,內部透過 Service Workers 技術實現
const WorkboxPlugin = require("workbox-webpack-plugin"); module.exports = { plugins: [ new WorkboxPlugin.GenerateSW({ // 這些選項幫助快速啟用 ServiceWorkers // 不允許遺留任何“舊的” ServiceWorkers clientsClaim: true, skipWaiting: true, }), ] }
-
terser-webpack-plugin:壓縮和最佳化JavaScript程式碼
二、loader和plugin的不同
- 作用不同
- Webpack將一切檔案視為模組,但是webpack原生是隻能解析js檔案,如果想將其他檔案也打包的話,就會用到
loader
。 所以Loader的作用是讓webpack擁有了載入和解析非JavaScript檔案的能力。 - Plugin可以擴充套件webpack的功能,讓webpack具有更多的靈活性。 在 Webpack 執行的生命週期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機透過 Webpack 提供的 API 改變輸出結果。
- Webpack將一切檔案視為模組,但是webpack原生是隻能解析js檔案,如果想將其他檔案也打包的話,就會用到
- 用法不同
- Loader在
module.rules
中配置,也就是說他作為模組的解析規則而存在。 型別為陣列,每一項都是一個Object
,裡面描述了對於什麼型別的檔案(test
),使用什麼載入(loader
)和使用的引數(options
) - Plugin在
plugins
中單獨配置。 型別為陣列,每一項是一個plugin
的例項,引數都透過建構函式傳入。
- Loader在
三、webpack的構建流程
- 初始化引數:Webpack從配置檔案(如webpack.config.js)和Shell語句中讀取引數,並進行合併,得出最終的構建引數。這些引數為後續步驟提供了必要的配置資訊。
- 開始編譯:使用初始化引數中得到的配置,Webpack會初始化一個Compiler物件。這個物件會載入所有配置的外掛,並執行其run方法,從而開始執行編譯過程。
- 確定入口:Webpack會根據配置檔案中的entry配置找出所有的入口檔案。入口檔案是構建過程的起點,Webpack會從這些檔案開始解析依賴關係。
- 編譯模組:從入口檔案開始,Webpack會遞迴地解析每個模組,並根據配置檔案中的loader配置對模組進行轉換。這些loader可以將不同型別的檔案(如CSS、圖片等)轉換為JavaScript模組,以便Webpack能夠處理。同時,Webpack還會找出每個模組所依賴的其他模組,並遞迴地對這些依賴模組進行相同的處理,直到所有入口依賴的檔案都經過了處理。
- 完成編譯:經過loader的轉換後,Webpack得到了每個模組被翻譯後的內容以及它們之間的依賴關係。這些依賴關係會以特定的格式(如AST語法樹)儲存在記憶體中,為後續步驟提供必要的資訊。
- 輸出資源:根據入口檔案和模組之間的依賴關係,Webpack會將這些模組組裝成多個包含多個模組的chunk。然後,Webpack會將每個chunk轉換為單獨的檔案,並加入到輸出列表中。在這個過程中,Webpack還可以根據配置進行程式碼分割、最佳化等操作。
- 輸出完成:確定輸出內容後,Webpack會根據配置檔案中的輸出路徑和檔名,將檔案寫入到指定的檔案系統中。這標誌著整個構建過程的結束。
四、如何用webpack最佳化前端效能
- 利用快取
- Webpack 5 引入了持久化快取,透過生成一個唯一的雜湊值來標識模組,只要模組的內容不變,就可以使用快取的模組,避免重複編譯。
- 確保
output.deterministic
配置為true
,以便確保輸出內容的確定性,從而有效利用快取。 - 使用
contenthash
替代hash
,以便只在內容變化時更新輸出檔名。
- Tree Shaking
- 利用 ES6 模組的靜態結構特性,自動去除無用的程式碼,減少最終打包的體積
- 確保你的程式碼使用 ES6 模組語法,並且
optimization.usedExports
和optimization.sideEffects
配置正確
- 程式碼分割
- 使用
import()
語法進行動態匯入,將程式碼拆分成多個塊(chunks),按需載入 - 配置
optimization.splitChunks
以最佳化程式碼分割策略
- 使用
- 壓縮和最佳化輸出
- 使用 TerserPlugin 進行 JavaScript 程式碼的壓縮
- 對於 CSS,可以使用 CssMinimizerPlugin
- 啟用
compression
外掛,如CompressionWebpackPlugin
,進行 gzip 或 Brotli 壓縮
- 利用模組聯邦(Module Federation)
- Webpack 5 引入了模組聯邦,允許在不同的構建之間共享程式碼,而無需複製或安裝相同的依賴
- 最佳化載入器
- 減少不必要的載入器使用,只針對需要的檔案型別使用載入器
- 嘗試使用更快的載入器或並行處理載入器(如
thread-loader
或happypack
)
- 使用 DLL Plugin
- DLL Plugin 可以將特定的依賴模組提前構建,在後續構建中複用,減少構建時間
- 利用 Webpack Dev Server
- 在開發環境中使用 Webpack Dev Server,它提供了熱模組替換(HMR)功能,可以在不重新整理整個頁面的情況下更新模組,提高開發效率。
- 監控和分析構建
- 使用
webpack-bundle-analyzer
外掛來分析打包後的檔案結構和大小,找出可能的最佳化點
- 使用