webpack面試2

平平丶淡淡發表於2024-03-14

一、常用plugin

  1. 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"),
            })
        ]
    }
    
  2. 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",
        	}),
        ]
    }
    
  3. css-minimizer-webpack-plugin:css壓縮

    const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
    
    module.exports = {
        ......
        plugins: [
            // css壓縮
            new CssMinimizerPlugin()
        ]
    }
    
  4. 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",
                              },
                            },
                          ],
                        },
                      ],
                    ],
                  },
                },
              }),
            ],
      	},
    }
    
  5. @vue/preload-webpack-plugin:在空閒時間載入後續需要使用的資源

    const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin");
    
    module.exports = {
        plugins: [
            new PreloadWebpackPlugin({
                rel: "preload", // preload相容性更好
                as: "script",
                // rel: 'prefetch' // prefetch相容性更差
            }),
        ]
    }
    
  6. workbox-webpack-plugin:提供離線訪問功能,內部透過 Service Workers 技術實現

    const WorkboxPlugin = require("workbox-webpack-plugin");
    
    module.exports = {
        plugins: [
            new WorkboxPlugin.GenerateSW({
                // 這些選項幫助快速啟用 ServiceWorkers
                // 不允許遺留任何“舊的” ServiceWorkers
                clientsClaim: true,
                skipWaiting: true,
            }),
        ]
    }
    
  7. terser-webpack-plugin:壓縮和最佳化JavaScript程式碼

二、loader和plugin的不同

  • 作用不同
    1. Webpack將一切檔案視為模組,但是webpack原生是隻能解析js檔案,如果想將其他檔案也打包的話,就會用到loader。 所以Loader的作用是讓webpack擁有了載入和解析非JavaScript檔案的能力。
    2. Plugin可以擴充套件webpack的功能,讓webpack具有更多的靈活性。 在 Webpack 執行的生命週期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機透過 Webpack 提供的 API 改變輸出結果。
  • 用法不同
    1. Loadermodule.rules中配置,也就是說他作為模組的解析規則而存在。 型別為陣列,每一項都是一個Object,裡面描述了對於什麼型別的檔案(test),使用什麼載入(loader)和使用的引數(options
    2. Pluginplugins中單獨配置。 型別為陣列,每一項是一個plugin的例項,引數都透過建構函式傳入。

三、webpack的構建流程

  1. 初始化引數:Webpack從配置檔案(如webpack.config.js)和Shell語句中讀取引數,並進行合併,得出最終的構建引數。這些引數為後續步驟提供了必要的配置資訊。
  2. 開始編譯:使用初始化引數中得到的配置,Webpack會初始化一個Compiler物件。這個物件會載入所有配置的外掛,並執行其run方法,從而開始執行編譯過程。
  3. 確定入口:Webpack會根據配置檔案中的entry配置找出所有的入口檔案。入口檔案是構建過程的起點,Webpack會從這些檔案開始解析依賴關係。
  4. 編譯模組:從入口檔案開始,Webpack會遞迴地解析每個模組,並根據配置檔案中的loader配置對模組進行轉換。這些loader可以將不同型別的檔案(如CSS、圖片等)轉換為JavaScript模組,以便Webpack能夠處理。同時,Webpack還會找出每個模組所依賴的其他模組,並遞迴地對這些依賴模組進行相同的處理,直到所有入口依賴的檔案都經過了處理。
  5. 完成編譯:經過loader的轉換後,Webpack得到了每個模組被翻譯後的內容以及它們之間的依賴關係。這些依賴關係會以特定的格式(如AST語法樹)儲存在記憶體中,為後續步驟提供必要的資訊。
  6. 輸出資源:根據入口檔案和模組之間的依賴關係,Webpack會將這些模組組裝成多個包含多個模組的chunk。然後,Webpack會將每個chunk轉換為單獨的檔案,並加入到輸出列表中。在這個過程中,Webpack還可以根據配置進行程式碼分割、最佳化等操作。
  7. 輸出完成:確定輸出內容後,Webpack會根據配置檔案中的輸出路徑和檔名,將檔案寫入到指定的檔案系統中。這標誌著整個構建過程的結束。

四、如何用webpack最佳化前端效能

  1. 利用快取
    • Webpack 5 引入了持久化快取,透過生成一個唯一的雜湊值來標識模組,只要模組的內容不變,就可以使用快取的模組,避免重複編譯。
    • 確保 output.deterministic 配置為 true,以便確保輸出內容的確定性,從而有效利用快取。
    • 使用 contenthash 替代 hash,以便只在內容變化時更新輸出檔名。
  2. Tree Shaking
    • 利用 ES6 模組的靜態結構特性,自動去除無用的程式碼,減少最終打包的體積
    • 確保你的程式碼使用 ES6 模組語法,並且 optimization.usedExportsoptimization.sideEffects 配置正確
  3. 程式碼分割
    • 使用 import() 語法進行動態匯入,將程式碼拆分成多個塊(chunks),按需載入
    • 配置 optimization.splitChunks 以最佳化程式碼分割策略
  4. 壓縮和最佳化輸出
    • 使用 TerserPlugin 進行 JavaScript 程式碼的壓縮
    • 對於 CSS,可以使用 CssMinimizerPlugin
    • 啟用 compression 外掛,如 CompressionWebpackPlugin,進行 gzip 或 Brotli 壓縮
  5. 利用模組聯邦(Module Federation)
    • Webpack 5 引入了模組聯邦,允許在不同的構建之間共享程式碼,而無需複製或安裝相同的依賴
  6. 最佳化載入器
    • 減少不必要的載入器使用,只針對需要的檔案型別使用載入器
    • 嘗試使用更快的載入器或並行處理載入器(如 thread-loaderhappypack
  7. 使用 DLL Plugin
    • DLL Plugin 可以將特定的依賴模組提前構建,在後續構建中複用,減少構建時間
  8. 利用 Webpack Dev Server
    • 在開發環境中使用 Webpack Dev Server,它提供了熱模組替換(HMR)功能,可以在不重新整理整個頁面的情況下更新模組,提高開發效率。
  9. 監控和分析構建
    • 使用 webpack-bundle-analyzer 外掛來分析打包後的檔案結構和大小,找出可能的最佳化點

相關文章