<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          webpack 最佳實踐

          共 31442字,需瀏覽 63分鐘

           ·

          2021-07-16 20:44

          前言

          本文講述的最佳實踐是從日常業(yè)務中總結(jié)而出的,不一定適合所有項目。畢竟每個公司或個人的項目不同,最佳實踐也會有所不同。但是可以從這篇文章借鑒吸收一點有用的東西,有問題的地方也歡迎大家積極吐槽指正

          為了避免出現(xiàn) 我這明明可以,你那怎么不行 的尷尬情況,這里列一下文章涉及到依賴的版本號。

          ├── webpack           5.39.1
          ├── webpack-cli       4.7.2
          ├── node              12.8.0
          ├── npm               6.10.2

          正文

          初始化項目

          1. mkdir test-app && cd test-app
          2. npm init

          首先添加一個入口文件 /src/index.js 和 webpack 配置文件 webpack.config.js,現(xiàn)在我們的目錄結(jié)構(gòu)如下

          test-app
              ├── src
              |    └── index.js
              ├── package.json
              ├── webpack.config.js

          安裝 webpack

          npm install webpack webpack-cli -D

          開始搞事情

          src/index.js 中隨便寫點東西

          class Test {
            constructor() {
              document.writeTest('hello world')
            }
          }

          new Test()

          先來打個包看看啥效果, 執(zhí)行命令 npx webpack

          1.png

          等待一段時間后,看到目錄有了變化, 新增了一個 dist 目錄,該目錄下有一個 main.js 文件

          test-app
            + ├── dist
            + |    └── main.js
              ├── src
              |    └── index.js
              ├── package.json
              ├── webpack.config.js

          讓我們來看看 main.js 里有點啥

          new class{constructor(){document.writeTest("hello world")}};

          這玩意都不用試,肯定不得行啊,得將 js 代碼轉(zhuǎn)成 es5 才行。首先安裝下babel-loader及幾個相關(guān)的依賴

          配置 babel

          • babel-loader
          • @babel/core
          • @babel/preset-env
          • @babel/plugin-transform-runtime
          • @babel/plugin-proposal-decorators
          • @babel/plugin-proposal-class-properties
          • @babel/plugin-proposal-private-methods
          • @babel/runtime
          • @babel/runtime-corejs3
          npm install babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime  @babel/plugin-proposal-decorators  @babel/plugin-proposal-class-properties @babel/plugin-proposal-private-methods -D
          npm install @babel/runtime @babel/runtime-corejs3 -s

          修改 webpack.config.js 文件, 添加 babel-loader 配置

          const path = require('path');

          module.exports = {
            entry'./src/index.js',
            output: {
              path: path.resolve(__dirname, 'dist'),
              filename'bundle.[contenthash:8].js',
            },
            module: {
              rules: [
                {
                  test/\.(jsx|js)$/,
                  use'babel-loader',
                  exclude/node_modules/,
                },
              ]
            }
          }

          根目錄下添加相應的 .babelrc 配置文件

          {
              "presets": ["@babel/preset-env"],
              "plugins": [
                  ["@babel/plugin-transform-runtime", {"corejs"3}],
                  ["@babel/plugin-proposal-decorators", { "legacy"true }],
                  ["@babel/plugin-proposal-class-properties", { "loose"true }],
                  ["@babel/plugin-proposal-private-methods", { "loose"true }]
              ]
          }

          再次執(zhí)行命令 npx webpack 來打個包。完成后查看目錄結(jié)構(gòu)

          test-app
              ├── dist
            + |    ├── bundle.b8ba1739.js
              |    ├── main.js
              ├── src
              |    └── index.js
            + ├── .babelrc
              ├── package.json
              ├── webpack.config.js

          查看構(gòu)建后的 bundle.b8ba1739.js 文件

          (()=>{"use strict";new function n(){!function(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),document.writeTest("hello world")}})();

          構(gòu)建產(chǎn)物看著沒什么問題了,接下來看下在瀏覽器中的實際效果。要看效果,肯定離不開 html 文件。

          瀏覽器中觀看效果

          作為一個伸手黨直接從社區(qū)嫖來一個插件 html-webpack-plugin,這個插件的作用是將打包產(chǎn)物引入到我們提前準備好的模板 .html 文件中,我們訪問這個文件就能直觀的看到效果了

          先來安裝下插件

          npm install html-webpack-plugin -D

          接著創(chuàng)建一個 public 目錄, 用來存放靜態(tài)資源。新增一個 index.html 模板,放在 public 目錄下

          test-app
              ├── dist
              |    ├── bundle.b8ba1739.js
              |    ├── main.js
              ├── src
              |    └── index.js
            + ├── public
            + |    └── index.html
              ├── .babelrc
              ├── package.json
              ├── webpack.config.js

          webpack.config.js 中配置 html-webpack-plugin

          // 省略 ...
          const HtmlWebpackPlugin = require('html-webpack-plugin');

          module.exports = {
            // 省略 ...
            plugins: [
              new HtmlWebpackPlugin({
                template: path.resolve(__dirname, './public/index.html'),
                inject'body',
                scriptLoading'blocking',
              }),
            ]
          }

          再次執(zhí)行命令 npx webpack 來打個包。打完包發(fā)現(xiàn) dist 目錄下多了一個 index.html 文件。瀏覽器中打開 index.html 看看對不對

          2.png

          作為一個 api 工程師,連 api 都能記錯。

          3.png

          修改下 src/index.js 代碼

          class Test {
            constructor() {
              document.write('hello world')
            }
          }

          new Test()

          再次執(zhí)行命令 npx webpack 來打個包。老步驟,先檢查下打包產(chǎn)物對不對

          test-app
              ├── dist
              |    ├── bundle.b8ba1739.js
           +  |    ├── bundle.dc044571.js
              |    ├── index.html
              |    ├── main.js
              ├── src
              |    └── index.js
              ├── public
              |    └── index.html
              ├── .babelrc
              ├── package.json
              ├── webpack.config.js

          看樣子應該沒錯,代碼修改了,打包后多了個 .js 文件。再看看效果對不對

          4.png

          界面上也出現(xiàn)了 hello world。到這里為止,算是利用 webpack 走通了一個最小流程。

          為什么說是最小,因為到目前為止這個配置在實際工作中 基本沒卵用 實用性不大。細心一點的人已經(jīng)看出來了,上面存在三個問題

          1. 每修改一次代碼,都要走一遍打包流程,然后自己手動打開 html 文件,預覽效果
          2. 第一次調(diào)用錯誤 api 的時候,報錯信息定位不精確
          3. 打包目錄下面 上次構(gòu)建產(chǎn)物 也仍舊存在,時間長了會存在越來越多的無用代碼

          作為一個懶人,第三點可以忍,第一點和第二點忍不了。我們一個個來解決

          實時更新并預覽效果

          針對第一點,查閱 webpack 官網(wǎng),發(fā)現(xiàn)官網(wǎng)就給指了一條明路

          5.png

          按照官網(wǎng)教程,首先安裝下 webpack-dev-server

          npm install webpack-dev-server -D

          再在 webpack.config.js 中添加相應的配置

          // 省略 ...
          module.exports = {
            // 省略 ...
            devServer: {
              port'3001'// 默認是 8080
              hottrue,
              stats'errors-only'// 終端僅打印 error
              compresstrue// 是否啟用 gzip 壓縮
              proxy: {
                '/api': {
                  target'http://0.0.0.0:80',
                  pathRewrite: {
                    '/api''',
                  },
                },
              },
            },
          }

          package.json > script 中添加一個命令

          "dev""webpack serve  --open",

          執(zhí)行 npm run dev,這個時候在動在瀏覽器中打開了 http://localhost:3001/ 頁面。光自動打開還不夠啊,我們的目標是每次修改后不用構(gòu)建就能在瀏覽器中實時查看。為了測試這個功能是否生效,我們?nèi)我庑薷?src/index.js 文件并保存。發(fā)現(xiàn)瀏覽器中內(nèi)容自動刷新生效了。

          想了解更多關(guān)于 devServer 的可以閱讀以下兩篇文章

          • 【W(wǎng)ebpack】devServer 實驗報告
          • 120 行代碼幫你了解 Webpack 下的 HMR 機制

          sourcemap 配置

          第一個問題好了,再來看看第二個問題 報錯信息定位不精確。我們?nèi)耘f在官網(wǎng)找找看,有沒有對應的解決方案。通過 1 小時的文檔閱讀和 7 小時的摸魚,終于在一天后找到了解決方法。

          我們在 webpack.config.js 中添加配置

          // 省略 ...
          module.exports = {
            // 省略 ...
            devtool'eval-cheap-module-source-map',
          }

          這個配置什么意思呢,它會告訴我們錯誤是在原始代碼的哪一行發(fā)生的。廢話不多說,先來看看效果

          6.png

          點進去看看是什么情況

          28.png
          7.png

          這么精準的定位,一天可以改100個 bug 了。

          但是!!!這玩意好歸好,生產(chǎn)環(huán)境可不能亂用。這里建議

          開發(fā)環(huán)境 最佳:eval-cheap-module-source-map生產(chǎn)環(huán)境 最佳:hidden-source-map

          什么?你上下嘴皮子吧嗒一合,說最佳就最佳?沒有拿得出手的理由我們是不會信的

          8.png

          造謠是不可能造謠的,這輩子都不會。我也是吸收了這篇文章 萬字長文:關(guān)于 sourcemap,這篇文章就夠了 的精華才總結(jié)出來的。

          一萬字的文章總結(jié)成兩句話,10 秒鐘吸收

          9.png

          世事總是這么奇妙,按照上面的思路,在解決第二個問題的時候又帶出了一個新的問題,某些配置可能需要區(qū)分環(huán)境來設(shè)置,不同的環(huán)境設(shè)置合適的配置。就像在解決一個bug A的過程中,發(fā)現(xiàn)了一個新的 bug B。看來在解決上面第三個問題之前,得先解決這個 區(qū)分環(huán)境配置 的問題了。

          拆分環(huán)境

          按照一般慣例,我們會有 開發(fā)測試預發(fā)生產(chǎn)幾個環(huán)境。但是我個人很多情況下 開發(fā)測試 環(huán)境是同一套配置,所以我這里直接省略 測試 這個環(huán)境。

          修改下目錄結(jié)構(gòu)

          test-app
            + ├── build
            + |    ├── webpack.base.js
            + |    ├── webpack.dev.js
            + |    ├── webpack.pre.js
            + |    ├── webpack.pro.js
              ├── dist
              ├──  ├── bundle.b8ba1739.js
              ├──  ├── bundle.dc044571.js
              |    ├── index.html
              |    ├── main.js
              ├── src
              |    └── index.js
              ├── public
              |    └── index.html
              ├── .babelrc
              ├── package.json

          從目錄中就可以看出一點東西,我們刪除了原先根目錄下的 webpack.config.js 文件。新增了一個 build 目錄。在 build 目錄下我們需要建一個 webpack.base.js 文件。用來存放各個環(huán)境公共的配置,畢竟不可能所有配置在各個環(huán)境中都不一樣。然后按照我們各自項目實際的需求來建立不同環(huán)境的配置文件。

          先修改公共配置文件 webpack.base.js。原先的 devServe 配置由于只有開發(fā)環(huán)境有;devtool 各個環(huán)境不一樣,所以這兩個配置從公共配置里移除了

          const path = require('path');
          const HtmlWebpackPlugin = require('html-webpack-plugin');

          const rootDir = process.cwd();

          module.exports = {
            entry: path.resolve(rootDir, 'src/index.js'),
            output: {
              path: path.resolve(rootDir, 'dist'),
              filename'bundle.[contenthash:8].js',
            },
            module: {
              rules: [
                {
                  test/\.(jsx|js)$/,
                  use'babel-loader',
                  include: path.resolve(rootDir, 'src'),
                  exclude/node_modules/,
                },
              ]
            },
            plugins: [
              new HtmlWebpackPlugin({
                template: path.resolve(rootDir, 'public/index.html'),
                inject'body',
                scriptLoading'blocking',
              }),
            ],
          }

          接下來配置各個環(huán)境的配置,這里主要用到一個 webpack-merge 插件,用來合并公共配置,執(zhí)行 npm install webpack-merge -D

          修改 webpack.dev.js

          const { merge } = require('webpack-merge');
          const baseConfig = require('./webpack.base');

          module.exports = merge(baseConfig, {
            mode'development',
            devtool'eval-cheap-module-source-map',
            devServer: {
              port'3001'// 默認是 8080
              hottrue,
              stats'errors-only'// 終端僅打印 error
              compresstrue// 是否啟用 gzip 壓縮
              proxy: {
                '/api': {
                  target'http://0.0.0.0:80',
                  pathRewrite: {
                    '/api''',
                  },
                },
              },
            },
          });

          因為這里不涉及到實際的項目開發(fā),所以這里預發(fā)生產(chǎn)兩個環(huán)境的文件先配置成一樣的,大家可以根據(jù)自己的實際需要來進行不同的配置。

          • webpack.pre.js
          • webpack.pro.js
          const { merge } = require('webpack-merge');
          const baseConfig = require('./webpack.base');

          module.exports = merge(baseConfig, {
            mode'production',
            devtool'hidden-source-map',
          });

          看到仔細的人已經(jīng)發(fā)現(xiàn),配置中多了一個 mode 屬性,這個會在后面解釋一波,這里先不講

          修改 package.json 中的命令

            "scripts": {
              "dev""webpack serve --config build/webpack.dev.js --open",
              "build:pro""npx webpack --config build/webpack.pro.js",
            },

          再次執(zhí)行 npm run dev 看看效果

          10.png

          看來是沒問題了,現(xiàn)在已經(jīng)成功把 webpack.config.js 文件根據(jù)環(huán)境進行拆分成了多個文件。

          現(xiàn)在來回顧下之前提出的第三個問題

          11.png

          這個項目小的時候其實問題不大,但是當項目大了之后,每次打包都增加幾百上千的文件,還是有點恐怖的。所以還是把這個問題也順帶解決下好了。

          打包時清除上次構(gòu)建產(chǎn)物

          我們的目標是每次打包時刪除上次打包的產(chǎn)物,保證打包目錄下所有文件都是新的,社區(qū)查找一番后,找到一個插件clean-webpack-plugin ,來看下這個插件的介紹

          12.png

          比較懶,所以直接上截圖了。老步驟,先安裝 npm install clean-webpack-plugin -D 然后直接將文檔中的示例代碼借鑒到我們的項目中。修改 webpack.base.js

          // 省略...
          const { CleanWebpackPlugin } = require('clean-webpack-plugin');

          module.exports = {
            // 省略...
            plugins: [
              new HtmlWebpackPlugin({
                template: path.resolve(rootDir, 'public/index.html'),
                inject'body',
                scriptLoading'blocking',
              }),
              new CleanWebpackPlugin(),
            ],
          }

          試下效果,執(zhí)行 npm run build:pro 打個包。查看目錄

          test-app
              ├── build
              |    ├── webpack.base.js
              |    ├── webpack.dev.js
              |    ├── webpack.pre.js
              |    ├── webpack.pro.js
              ├── dist
              |    ├── bundle.fd44c2eb.js
              |    ├── bundle.fd44c2eb.js.map
              |    ├── index.html
              ├── src
              |    └── index.js
              ├── public
              |    └── index.html
              ├── .babelrc
              ├── package.json

          dist 目錄下原先存在的 main.jsbundle.b8ba1739.js 等前幾次打包產(chǎn)物已經(jīng)自動清除了。到這里第三個問題也解決了

          功能完善

          添加 css 和 less 支持

          為什么不添加 sass 支持?因為我不用 sass

          首先,在 src 目錄下添加一個 index.less 文件

          .test {
            color: red;
          }

          修改 src/index.js 文件,在文件中引用剛才添加的 less 文件

          import './index.less'

          class Test {
            constructor() {
              this.renderDiv()
            }

            renderDiv() {
              const div = document.createElement('div')
              div.className = 'test'
              div.innerHTML = 'hello world'
              document.body.appendChild(div)
            }
          }

          new Test()

          執(zhí)行 npm run dev

          等待 10 分鐘后,頁面遲遲沒有加載任何東西,打開控制臺一看

          13.png

          英語 8 級的我立馬讀懂了報錯:"你 可能 需要 一個 什么什么 loader 來 處理 這個 文件 類型, 目前 沒有 loaders 被配置 來 process 這個 文件"

          再結(jié)合官網(wǎng)的說明

          14.png

          到了這里,我好像隱約明白了 webpack 的真諦:雖然很多時候我不行,但是很多大佬會讓我行。呸,什么叫不行?這叫 靈活可插拔,正是這種特性,讓 webpack 可靈活支持各種復雜場景的自定義配置。

          忘了正事兒,既然問題找到了,就好解決了,找到幾個處理 cssless 的 loader 就行

          首先安裝 loader

          npm install less style-loader css-loader less-loader -D

          再修改 webpack.base.js 文件

          // 省略...

          module.exports = {
            // 省略...
            module: {
              rules: [
                // 省略...
                {
                  test/\.(le|c)ss$/,
                  exclude/node_modules/,
                  use: ['style-loader''css-loader''less-loader']
                },
              ]
            },
            // 省略...
          }

          再次執(zhí)行 npm run dev,查看效果

          15.png

          css module

          這一塊是基于上面的模塊修改的,解決 css 命名混亂和沖突的。不需要的話可以直接跳過這一塊。

          修改 webpack.base.js

          // 省略...

          module.exports = {
            // 省略...
            module: {
              rules: [
                //  省略...
                {
                  test/\.(le|c)ss$/,
                  exclude/node_modules/,
                  use: [
                    'style-loader',
                    {
                      loader'css-loader',
                      options: {
                        modules: {
                          compileType'module',
                          localIdentName"[local]__[hash:base64:5]",
                        },
                      },
                    },
                    'less-loader'
                  ]
                },
              ]
            },
            // 省略...
          }

          執(zhí)行 npm run dev 來看看效果

          16.png

          class 樣式名稱后加上一個哈希串,具體的配置可以看 css-loader 官網(wǎng)

          css 自動添加前綴

          首先安裝插件

          npm install autoprefixer postcss postcss-loader -D

          修改 webpack.base.js 配置文件

          // 省略...
          const autoprefixer = require('autoprefixer');

          module.exports = {
            // 省略...
            module: {
              rules: [
                // 省略...
                {
                  test/\.(le|c)ss$/,
                  exclude/node_modules/,
                  use: [
                    // 省略...
                    'less-loader',
                    {
                      loader'postcss-loader',
                      options: {
                        postcssOptions: {
                          plugins: [
                            ["autoprefixer"],
                          ],
                        },
                      },
                    }
                  ]
                },
              ]
            },
            // 省略...
          }

          打包后抽離 css 文件

          首先安裝 mini-css-extract-plugin 插件

          npm install mini-css-extract-plugin -D

          修改 webpack.base.js 配置文件

          // 省略...
          const MiniCssExtractPlugin = require('mini-css-extract-plugin');

          module.exports = {
            // 省略...
            module: {
              rules: [
                // 省略...
                {
                  test/\.(le|c)ss$/,
                  exclude/node_modules/,
                  use: [
                    MiniCssExtractPlugin.loader,
                    // 省略...
                  ]
                },
              ]
            },
            plugins: [
              // 省略...
              new MiniCssExtractPlugin({
                filename'css/[name].css',
              }),
            ],
          }

          執(zhí)行 npm run build:pro 打個包看看效果。

          17.png

          可以看到 css 已經(jīng)被抽離出來了

          壓縮打包后的 css 文件

          首先安裝 optimize-css-assets-webpack-plugin 插件

          npm install optimize-css-assets-webpack-plugin -D

          修改 webpack.base.js 配置文件

          // 省略...
          const OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin');

          module.exports = {
            // 省略...
            plugins: [
              // 省略...
              new MiniCssExtractPlugin({
                filename'css/[name].css',
              }),
              new OptimizeCssPlugin(),
            ],
          }

          執(zhí)行 npm run build:pro 打個包看看效果。

          .test__1PSRs{color:red;transition-duration:.4s}

          可以看出 css 已經(jīng)被壓縮了

          復制靜態(tài)資源到打包目錄

          有些時候有些第三方的 js 插件沒有提供 npm 包,只提供了一個 cdn 地址或者一份文件需要自己下載下來。通常我們下載下來之后放在我們的 public/js 目錄下面,然后 public/index.html 文件里直接用 script 標簽引入。這個時候不管是 npm run dev 開發(fā)時,還是 npm run build:pro 構(gòu)建后,這個 js 文件都是找不到的。我們可以嘗試下

          public/js 新加一個 test.js 的空文件,啥內(nèi)容都不用。然后在 public/index.html 中引入這個文件

          <!DOCTYPE html>
          <html lang="en">
            <head>
              // 省略
            </head>

            <body>
              <div id="root"></div>
              <script src="./js/test.js"></script>
            </body>
          </html>

          執(zhí)行 npm run dev 查看效果

          18.png

          這里我們可以用 copy-webpack-plugin 這個插件,在構(gòu)建的時候,將 public/js 的靜態(tài)資源復制到 dist 目錄下,這樣文件就能找到了

          安裝插件 npm install copy-webpack-plugin -D

          修改 webpack.base.js 配置文件

          // 省略...
          const CopyWebpackPlugin = require('copy-webpack-plugin');

          const rootDir = process.cwd();

          module.exports = {
            // 省略...
            plugins: [
              new HtmlWebpackPlugin({
                template: path.resolve(rootDir, 'public/index.html'),
                inject'body',
                scriptLoading'blocking',
              }),
              new CleanWebpackPlugin(),
              new CopyWebpackPlugin({
                patterns: [
                  {
                    from'*.js',
                    context: path.resolve(rootDir, "public/js"),
                    to: path.resolve(rootDir, 'dist/js'),
                  },
                ],
              })
              new MiniCssExtractPlugin({
                filename'css/[name].css',
              }),
              new OptimizeCssPlugin(),
            ],
          }

          執(zhí)行 npm run dev 查看效果

          19.png

          靜態(tài)文件已經(jīng)可以正常加載了。

          資源加載器

          項目中難免要引入一些圖標、圖片等資源,在不做任何處理的情況下,我們嘗試下在代碼中引用圖片,修改 src/index.js 文件如下

          import wuhanjiayou from '../public/asset/a.jpeg'

          class Test {
            constructor() {
              this.renderImg()
            }

            renderImg() {
              const img = document.createElement('img')
              img.src = wuhanjiayou
              document.body.appendChild(img)
            }
          }

          new Test()

          執(zhí)行 npm run dev 看下效果,報了個熟悉的錯

          20.png

          按照以往的套路,直接引用社區(qū)的三件套 raw-loaderurl-loaderfile-loader,安裝依賴,配置依賴,一通操作下來就解決了問題。現(xiàn)在我們使用 webpack5就方便多了,不用安裝任何依賴,直接修改 webpack.base.js 配置文件

          // 省略...
          rules: [
              {
                  test/\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
                  type'asset',
              },
          ]

          沒錯,就是這么簡單。type 屬性還有其他幾個值,具體可以看 官方文檔

          配置已經(jīng)修改好了,執(zhí)行 npm run dev 再來看下效果

          21.png

          搞定!

          上面講到的東西基本夠小項目的日常開發(fā)需求了,常用的 loader 和 plugin 都已經(jīng)有所涉及。但是,如果你的項目特別復雜,需求又比較小眾,社區(qū)沒有現(xiàn)成的 loader 和 plugin 可以借鑒,那么只能自己動手實現(xiàn)一個了。

          22.png

          可能在一部分人眼中,loader 和 plugin 是比較神秘的,也不可能想著自己去造一個輪子。但是當碰到問題又沒有現(xiàn)成的解決方案的時候,那就不得不自己造了。

          看了這篇文章 Webpack - 手把手教你寫一個 loader / plugin 應該能很快上手

          項目優(yōu)化

          剛才也講到了,上面的一通操作基本夠小項目開發(fā)使用了。為什么是小項目?大項目不行嗎?當一個項目大到路由都有幾百個的時候,一次熱更新就需要十幾二十多秒,一次打包要半個小時。開發(fā)時,一次代碼改動保存就要等 20 秒,這擱誰誰都忍不了啊。這個時候就需要想點辦法來優(yōu)化。

          loader 配置優(yōu)化

          這個其實上面已經(jīng)做了。明確告訴 loader,哪些文件不用做處理(exclude),或者只處理哪些文件(include)。

          {
              test/\.(jsx|js)$/,
              use'babel-loader',
              // include: [path.resolve(rootDir, 'src')]
              // exclude: /node_modules/,
            },

          一般傾向于使用 include,但是如果怕漏處理一些文件的話,粗暴點,使用 exclude: /node_modules/ 也可以。

          這部分測試了下,提升速度不是很明顯,應該算錦上添花吧

          緩存

          先說下 webpack5 之前是怎么做的。

          利用 cache-loader 將結(jié)果緩存中磁盤中;利用 hard-source-webpack-plugin 將結(jié)果緩存在 node_modules/.cache 下提升二次打包速度;利用 DllReferencePlugin 將變化不頻繁的第三方庫提前單獨打包成動態(tài)鏈接庫,提升真正業(yè)務代碼的打包速度

          webpack5 自帶了持久化緩存,配置如下

          開發(fā)環(huán)境 webpack.dev.js

          cache: {
              type'memory'
          },

          生產(chǎn)環(huán)境 webpack.pro.js

          cache: {
              type'filesystem',
              buildDependencies: {
                config: [__filename]
              }
          },

          這個測試了下前后的打包時間

          23.png
          24.png

          數(shù)據(jù)是這個數(shù)據(jù):

          • 第一次: 12592 ms
          • 第二次: 920 ms但是我心里默數(shù)了下,二次打包大概在 3 秒左右,咱也不知道控制臺的計時邏輯是什么
          25.png

          如果在構(gòu)建時,你主動確定要放棄舊的緩存的話,可以傳一個新的 version 參數(shù)來放棄使用緩存

          cache: {
              type'filesystem',
              buildDependencies: {
                config: [__filename]
              },
              version'new_version'
          },

          代碼拆分

          optimization: {
              splitChunks: {
                chunks'all',
              }
          }

          這個在 mode: production 時是默認開啟的,但是默認情況下只會對按需加載的代碼進行分割。如果我們要對一開始就加載的代碼也做分割處理,就要進行如上配置。

          從官網(wǎng)截了一張圖:

          26.png

          大家的項目可能都有所不同,相對應的最佳的配置可能也有所不同,所以這里就補貼具體的配置了,大家有需要的可以看官網(wǎng)的文檔對自己的項目進行配置 官網(wǎng) optimization.splitChunks 更多配置、「Webpack」從 0 到 1 學會 code splitting

          mode

          mode: production 在上面出現(xiàn)了這么多次,也沒有具體說有哪些功能。其實當設(shè)置 mode: production 時,webpack 已經(jīng)默認開啟了一些優(yōu)化措施。

          27.png

          這里面的一些東西由于篇幅較大也不做一一說明了,反正只要記得 mode: production 已經(jīng)給我們做了一系列優(yōu)化,真的想知道有哪些優(yōu)化的,我找了篇文章,有興趣的可以看看 mode 詳解

          happypack

          利用 happypack 插件進行多線程打包,按照官網(wǎng)文檔進行配置

          // 省略...
          const Happypack = require('happypack');
          const os = require('os')
          const happyThreadPool = Happypack.ThreadPool({ size: os.cpus().length })

          // 省略...
          rules: [
            {
              test/\.(jsx|js)$/,
              // use: 'babel-loader',
              use'Happypack/loader?id=js',
              exclude/node_modules/,
            },
          ]

          plugins: [
              new Happypack({
                id'js'// 這個 id 值為上面 Happypack/loader?id=js 問號后跟的參數(shù)
                use: ['babel-loader'],
                threadPool: happyThreadPool
              }),
          ]

          由于本篇文章寫的是個 demo,沒有業(yè)務代碼,所以這個打包出來的時間基本沒變化甚至還多了 1 秒,這里就不貼效果圖了。這是因為happypack執(zhí)行也需要時間,如果項目比較小的話,就不需要配置了。js 處理完之后那就是要處理css了, 按照處理js的方式,ctrl+c/ctrl+v 處理css

          執(zhí)行 npm run build:pro

          ERROR in ./src/index.less
          Module build failed (from ./node_modules/Happypack/loader.js):
          Error: You forgot to add 'mini-css-extract-plugin' plugin (i.e. `{ plugins: [new MiniCssExtractPlugin()] }`), please read https://github.com/webpack-contrib/mini-css-extract-plugin#getting-started

          報錯說忘記添加了mini-css-extract-plugin插件,但是明明已經(jīng)添加了,經(jīng)過試驗,發(fā)現(xiàn)是 mini-css-extract-plugin 這個插件引起 happypack 報錯的。終于,在經(jīng)過 百度谷歌 等一系列騷操作后,我放棄了,沒找到解決方法

          尷尬.png

          現(xiàn)在擺在面前的就三條路:

          • 放棄使用 happypack
          • 使用 happypack 優(yōu)化jscss,放棄使用 mini-css-extract-plugin
          • 使用 happypack 優(yōu)化 js,放棄優(yōu)化 css,保留 mini-css-extract-plugin

          知道咋解決的或有更好的方式的可以在下方留言,讓我白嫖 借鑒下。

          thread-loader

          如果采用上面第一種,放棄使用 happypack,可以用 thread-loader 代替下。而且這個配置非常簡單。

          先安裝: npm install thread-loader -D,再修改配置

          // 省略...
          rules: [
            {
              test/\.(jsx|js)$/,
              use: ['thread-loader''babel-loader'],
              exclude/node_modules/,
            },
            {
              test/\.(le|c)ss$/,
              exclude/node_modules/,
              use: [
                MiniCssExtractPlugin.loader,
                'thread-loader',
                {
                  loader'css-loader',
                  options: {
                    modules: {
                      compileType'module',
                      localIdentName"[local]__[hash:base64:5]",
                    },
                  },
                },
                'less-loader',
                {
                  loader'postcss-loader',
                  options: {
                    postcssOptions: {
                      plugins: [
                        ["autoprefixer"],
                      ],
                    },
                  },
                }
              ],
            },
          ]

          到這里應該可以應付一般的項目了。由于這篇文章主要講述 webpack 的應用,所以很多知識點沒有細講,也沒有精力細講,但是很多涉及到的知識點都推薦了相應的文章,有興趣的朋友可以看一下。

          參考文獻:

          • webpack5
          • webpack4 升級到 5


          瀏覽 46
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩中文字幕免费在线观看 | 久久艹综合 | 色秘 乱码一区二区三区在线男奴 | 日美一级AV | 免费看A片视频网站 |