實(shí)現(xiàn)vue-cli(二):webpack實(shí)現(xiàn)項(xiàng)目打包

一、大概思路

(一)開發(fā)階段的打包構(gòu)建
  1. 配置打包的入口文件和輸出目錄等信息。
  2. 清空構(gòu)建目錄舊文件。處理js文件。
  3. 處理打包js/css/vue/圖片字體等。
  4. 將打包結(jié)果注入html。
  5. 啟動(dòng)服務(wù)器預(yù)覽頁(yè)面,并監(jiān)聽(tīng)變化。
  6. 增加eslint檢測(cè)。
  7. 配置sourceMap等信息。
(二)發(fā)布階段的打包構(gòu)建
  1. 配置打包的入口文件和輸出目錄等信息。
  2. 清空構(gòu)建目錄舊文件。處理js文件。
  3. 處理打包js/css/vue/圖片字體等(發(fā)布階段還需要對(duì)css/js進(jìn)行壓縮混淆)。
  4. 拷貝public資源。
  5. 將打包結(jié)果注入html。
  6. 增加eslint檢測(cè)。
  7. 配置sourceMap等信息。

二、“開發(fā)階段打包構(gòu)建”具體實(shí)現(xiàn)

(一)準(zhǔn)備工作
  1. 請(qǐng)確保自己本地已有npm或yarn等包管理工具,本文用npm做演示。
  2. 下載該演示項(xiàng)目,或者自行vue-cli創(chuàng)建一個(gè)項(xiàng)目。
  3. 在該文件夾下空白處“按shift+鼠標(biāo)右鍵”,選中“在此處打開命令行/powershell窗口”打開命令行窗口,或者自行通過(guò)命令窗口cd到該文件目錄下。
  4. 命令行輸入npm init回車,自行填寫信息一路回車,最后生成package.json配置文件。
  5. 命令行輸入npm install webpack webpack-cli -D安裝webpack打包構(gòu)建工具(注意:版本不一致可能會(huì)導(dǎo)致報(bào)錯(cuò),本篇演示用的版本是"webpack": "5.36.2""webpack-cli": "3.3.12",詳細(xì)版本見(jiàn)最后附錄)。
  6. 在示例項(xiàng)目下新建webpack.config.js作為webpack的配置文件。
(二)配置打包入口和輸出等信息

在webpack.config.js中添加以下代碼,命令行輸入npx webpack運(yùn)行,默認(rèn)會(huì)去執(zhí)行webpack.config.js文件,如果成功生成temp/main.js文件則成功(會(huì)有報(bào)錯(cuò)后面解決)。

const path = require('path')

module.exports = {
  entry: './src/main.js',
  output: {
    filename: '[name]_[contenthash:8].js', // 生成文件的名字
    path: path.join(__dirname, 'temp') // 生成文件放在哪,output.path必須是絕對(duì)路徑
  },
  mode: 'none', // 設(shè)置webpack運(yùn)行模式,有production/development/none三種取值,不同模式會(huì)內(nèi)置不同功能
}
(三)清空輸出目錄的舊文件

如果多運(yùn)行幾次打包命令npx webpack就會(huì)發(fā)現(xiàn),生成的index.js越來(lái)越多,而我們用到的其實(shí)只有最新的那個(gè)。為了避免冗余,我們可以使用插件在每次打包之前先刪除下目錄里的舊文件。npm install clean-webpack-plugin -D安裝刪除文件的插件,然后增加plugins配置。配置完后再執(zhí)行打包npx webpack則只會(huì)保留最新的文件。

const path = require('path')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')

module.exports = {
  entry: './src/main.js',
  output: {
    filename: '[name]_[contenthash:8].js', // 生成文件的名字
    path: path.join(__dirname, 'temp') // 生成文件放在哪,output.path必須是絕對(duì)路徑
  },
  mode: 'none', // 設(shè)置webpack運(yùn)行模式,有production/development/none三種取值,不同模式會(huì)內(nèi)置不同功能
  plugins: [
    new CleanWebpackPlugin(),
  ],
}
(四)添加loader處理css/js/vue/圖片/字體
  1. 處理css:由于webpack默認(rèn)只對(duì)js進(jìn)行打包處理,所以要單獨(dú)對(duì)css進(jìn)行處理。安裝css處理所需要的loader,npm install style-loader css-loader less less-loader -D。其中css-loader只會(huì)處理css,并不會(huì)將css代碼嵌入到最后打包內(nèi)容里,需要再用style-loader將css嵌入到style里。
  • 多個(gè)loader時(shí)執(zhí)行順序是從下到上依次執(zhí)行,所以反過(guò)來(lái)先寫style-loader再css-loader(先處理再將結(jié)果插入,若有l(wèi)ess要先轉(zhuǎn)成css再用css-loader處理)。
  1. 處理js:webpack對(duì)js的處理只是打包合并,之所以能解析import export也是對(duì)模塊化做了支持,對(duì)于一些es6新語(yǔ)法特性還需要用babel進(jìn)行轉(zhuǎn)化。npm install babel-loader @babel/core @babel/preset-env -D安裝相關(guān)依賴,記得設(shè)置@babel/preset-env才能轉(zhuǎn)碼成功,因?yàn)檗D(zhuǎn)碼插件都放在這里面。
  2. 處理vue: 安裝vue處理需要的loader和依賴,npm install vue vue-loader vue-template-compiler -D,vue-loader還要搭配插件VueLoaderPlugin使用。
  3. 處理字體和圖片:安裝依賴npm install file-loader url-loader -D。一般較小的資源可以用url-loader轉(zhuǎn)為base64進(jìn)行加載,當(dāng)資源較大base64會(huì)影響打包體積影響運(yùn)行速度,所以超過(guò)大小用file-loader加載對(duì)應(yīng)路徑資源。
  • 注意:在file-loader v4.3.0版本之后默認(rèn)使用了esModule語(yǔ)法,所以會(huì)導(dǎo)致圖片的路徑變成[object module]。解決方案可以修改圖片的引用方式<img src="require('./assets/logo.png').default"/>,更簡(jiǎn)單的直接給loader設(shè)置esModule: false。
const path = require('path')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  entry: './src/main.js',
  output: {
    filename: '[name]_[contenthash:8].js', // 生成文件的名字
    path: path.join(__dirname, 'temp') // 生成文件放在哪,output.path必須是絕對(duì)路徑
  },
  mode: 'none', // 設(shè)置webpack運(yùn)行模式,有production/development/none三種取值,不同模式會(huì)內(nèi)置不同功能
  module: {
    rules: [
      {
        test: /\.vue$/i,
        use: 'vue-loader',
      },
      {
        test: /\.js$/i,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env'],
            ],
          },
        },
      },
      {
        test: /\.(css|less)$/i,
        use: [
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/i,
        use: {
          loader: 'url-loader', // 用url-loader將較小的資源轉(zhuǎn)出base64加載,較大的會(huì)影響打包體積影響運(yùn)行速度
          options: {
            limit: 10 * 1024, // 超過(guò)10kb大小用file-loader加載
            name: 'img/[name].[contenthash:8].[ext]', // 指定file-loader處理生成路徑名字
            esModule: false, // 解決圖片路徑變成[object module]的問(wèn)題
          },
        },
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
        use: {
          loader: 'url-loader', // 用url-loader將較小的資源轉(zhuǎn)出base64加載,較大的會(huì)影響打包體積影響運(yùn)行速度
          options: {
            limit: 10 * 1024, // 超過(guò)10kb大小用file-loader加載
            name: 'font/[name]_[contenthash:8].[ext]', // 指定file-loader處理生成路徑名字
            esModule: false, // 解決字體路徑變成[object module]的問(wèn)題
          },
        },
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new VueLoaderPlugin(),
  ],
}

經(jīng)過(guò)上述處理,再運(yùn)行npx webpack此時(shí)已經(jīng)沒(méi)有報(bào)錯(cuò)了。接下來(lái)我們就將打包出來(lái)的結(jié)果注入到html中并啟動(dòng)服務(wù)器預(yù)覽看是否正常。

(五)將打包結(jié)果注入html
  • npm install html-webpack-plugin -D安裝webpack處理html的插件。plugin和loader是webpack兩個(gè)核心。loader一般用于對(duì)文件內(nèi)容進(jìn)行編譯,并將處理結(jié)果直接插入到編譯后的文件。而plugin可以對(duì)文件進(jìn)行增刪改等其他loader做不到的事情,比如刪除和拷貝文件。
  • webpack中還提供了definePlugin可以用于為全局注入變量,然后在html等文件中訪問(wèn)該變量,值必須是可運(yùn)行的js語(yǔ)句,即eval(變量值)不報(bào)錯(cuò),所以如果值是字符串得加雙引號(hào)否則認(rèn)為是變量會(huì)報(bào)錯(cuò)。
    依據(jù)此可以實(shí)現(xiàn)不同運(yùn)行環(huán)境下加入不同值,比如mode: 'production'時(shí),會(huì)默認(rèn)注入process.env.NODE_ENV = 'production'用于判斷當(dāng)前運(yùn)行環(huán)境。但上面我們?cè)O(shè)置了mode: 'none'所以要自己注入這個(gè)變量。
const HtmlWebpackPlugin = require('html-webpack-plugin')
const Webpack = require('webpack')

module.exports = {
  ...,
  plugins: [
    new CleanWebpackPlugin(),
    new VueLoaderPlugin(),
    new Webpack.DefinePlugin({
      BASE_URL: '"../public/"', // 必須是可運(yùn)行的js語(yǔ)句,即eval(BASE_URL)不報(bào)錯(cuò),所以此處得加雙引號(hào)否則認(rèn)為是變量會(huì)報(bào)錯(cuò)
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV) || '"development"', // 直接讀取node環(huán)境中的變量,如果未定義則設(shè)置為development
      },
    }),
    new HtmlWebpackPlugin({
      title: '測(cè)試標(biāo)題', // 打包后html里的title
      filename: 'index.html', // 打包后的文件名
      template: './public/index.html', // 依據(jù)哪個(gè)模板文件來(lái)生成最后的html
    }),
  ],
}

增加上述代碼之后命令行輸入npx webpack打包,會(huì)生成temp下對(duì)應(yīng)文件,瀏覽器手動(dòng)打開temp/index.html,如果頁(yè)面顯示正常即成功。

(六)服務(wù)器啟動(dòng)并自動(dòng)刷新
  • 運(yùn)行webpack的時(shí)候加個(gè)--watch,能監(jiān)聽(tīng)文件變化自動(dòng)重新打包但需要手動(dòng)刷新,可以用browser-sync temp --file "**/*"實(shí)現(xiàn)自動(dòng)刷新。但由于又要寫入磁盤再讀出磁盤,會(huì)比較慢。
  • webpack-dev-server能自動(dòng)運(yùn)行打包編譯和監(jiān)聽(tīng)刷新,將打包內(nèi)容寫入緩存而不是磁盤,減少了磁盤讀寫。默認(rèn)會(huì)將構(gòu)建輸出的資源作為加載文件,如果沒(méi)構(gòu)建的資源要自己配置額外資源路徑。安裝插件npm install webpack-dev-server -D,并增加以下配置。
  • 由于自動(dòng)刷新整個(gè)頁(yè)面會(huì)丟失原操作和文本,但有時(shí)我們希望保留原來(lái)輸入框的內(nèi)容只變更改動(dòng)的地方,此時(shí)就需要熱更新。模塊熱更新HMR(hot module replacement)可以實(shí)時(shí)替換改變的模塊但不影響整體運(yùn)行狀態(tài)。通過(guò)設(shè)置hot: true可以開啟熱更新。
module.exports = {
  ...,
  devServer: {
    contentBase: ['public', '.'], // 額外指定找不到的資源(比如public里沒(méi)打包到temp的靜態(tài)資源)去哪里找
    port: 8080,
    open: true, // 是否自動(dòng)啟動(dòng)瀏覽器
    // hot: true, // 如果hot處理代碼有報(bào)錯(cuò),則仍然會(huì)自動(dòng)刷新整個(gè)頁(yè)面
    hotOnly: true, // 只做熱更新,無(wú)論有無(wú)報(bào)錯(cuò)也不自動(dòng)刷新整個(gè)頁(yè)面
  },
}

如果用的是webpack-dev-server4,已經(jīng)取消了hotOnly和contentBase,可以將配置改成如下

module.exports = {
  ...,
  devServer: {
    static: {
      directory: './public'
    }, // 額外指定找不到的資源(比如public里沒(méi)打包到temp的靜態(tài)資源)去哪里找
    port: 8080,
    open: true, // 是否自動(dòng)啟動(dòng)瀏覽器
    hot: true, // 如果hot處理代碼有報(bào)錯(cuò),則仍然會(huì)自動(dòng)刷新整個(gè)頁(yè)面
  },
}

命令行運(yùn)行npx webpack-dev-server啟動(dòng)服務(wù)器,修改文件會(huì)自動(dòng)編譯刷新則代表成功。若出現(xiàn)Cannot find module 'webpack-cli/bin/config-yargs'報(bào)錯(cuò),要修改webpack-cli版本,因?yàn)閣ebpack-cli早在4.0版本后就移除了yargs,版本兼容沒(méi)做好,可以在命令行輸入npm install webpack-cli@3 -D將webpack-cli還原到3.3.12版本的版本,再次執(zhí)行npx webpack-dev-server就可以了。

(七)sourceMap配置錯(cuò)誤定位

由于現(xiàn)在運(yùn)行的文件是經(jīng)過(guò)編譯的,跟我們開發(fā)時(shí)寫的代碼差異比較大,如果有報(bào)錯(cuò)信息只能定位到編譯后的代碼上,而無(wú)法定位到我們開發(fā)的具體代碼位置,這點(diǎn)不利于我們調(diào)試和處理問(wèn)題。source map源碼地圖指的是編譯后代碼和源碼的對(duì)應(yīng)關(guān)系,解決編譯之后無(wú)法查看的問(wèn)題。webpack提供了devtool可以讓我們配置sourceMap模式。

常用的sourceMap模式有eval-source-map、cheap-eval-source-map、cheap-module-eval-source-map等。eval-source-map生成了source-map文件能定位問(wèn)題行和列,cheap-eval-source-map生成了簡(jiǎn)單source-map文件只能定位,cheap-module-eval-source-map是定位編譯前文件所在。即帶cheap不能定位列信息;帶module是和沒(méi)loader加工過(guò)的源代碼一模一樣。

開發(fā)階段建議使用cheap-module-eval-source-map,因?yàn)橐话忝啃胁怀^(guò)80不需要定位列,且需要看源代碼,雖然要定位編譯前文件所在行處理多啟動(dòng)慢,但只有第一次慢后面修改不再重復(fù)處理不會(huì)慢。發(fā)布階段建議用none,即不暴露源代碼,因?yàn)橐话銘?yīng)該在開發(fā)階段就把錯(cuò)誤調(diào)試處理完畢。實(shí)在擔(dān)心上線后有報(bào)錯(cuò)要調(diào)試,可以用nosources-source-map只提供錯(cuò)誤的行列信息但顯示給用戶空白代碼,這樣再到自己源代碼里找行列就可以定位到錯(cuò)誤位置。

module.exports = {
  ...,
  devtool: 'eval-cheap-module-source-map', // 此處寫法和官方文檔不一樣,因?yàn)閣ebpack5之后的devtool檢測(cè)規(guī)則是^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$
}
(八)增加eslint檢測(cè)

eslint主要用于檢測(cè)代碼風(fēng)格和語(yǔ)法是否符合規(guī)范,能讓團(tuán)隊(duì)的代碼保持統(tǒng)一規(guī)范方便維護(hù)。命令行輸入npm install eslint安裝eslint,然后npx eslint --init生成eslint配置文件。npm install eslint-loader -D安裝對(duì)應(yīng)loader再增加下面loader配置。

{
  test: /\.(js|vue)$/i,
  exclude: '/node_modules/', // node_modules下的文件不需要eslint檢測(cè)
  use: 'eslint-loader',
  enforce: 'pre', // 強(qiáng)制最先執(zhí)行這個(gè)loader
},

此時(shí)在main.js里寫一些語(yǔ)法錯(cuò)誤,運(yùn)行npx webpack-dev-server會(huì)看到eslint報(bào)錯(cuò)即代表成功。下面報(bào)錯(cuò)表示在main.js文件的第1行第22列缺少了分號(hào)。

D:\project\test\webpack_example\src\main.js
   1:22  error  Missing semicolon                                                          semi

如果覺(jué)得有些檢測(cè)不符合團(tuán)隊(duì)的開發(fā)習(xí)慣,可以前往剛才init生成的.eslinterc配置文件里修改rules。具體的配置規(guī)則可以前往"https://eslint.cn/docs/rules/關(guān)鍵字"查看,比如上面的關(guān)鍵詞是最后的semi(表示是否最后加分號(hào)),可以前往"https://eslint.cn/docs/rules/semi"查看修改配置規(guī)則。

// 修改.eslintrc
{
    "rules": {
        "semi": ["error", "never"], // 不需要分號(hào)結(jié)尾
        "linebreak-style": ["error", "windows"] // 采用windows的CRLF換行
    }
}

至此,開發(fā)階段的webpack打包構(gòu)建已經(jīng)配置完畢。

三、“發(fā)布階段打包構(gòu)建”具體實(shí)現(xiàn)

發(fā)布階段的構(gòu)建大致跟開發(fā)階段一樣,但由于發(fā)布的內(nèi)容是面向客戶的,有一些要做優(yōu)化。主要區(qū)別在以下幾點(diǎn):

  1. 不需要啟動(dòng)服務(wù)器調(diào)試。
  2. 構(gòu)建的輸出目錄不同,sourceMap等配置不同。
  3. 由于無(wú)法訪問(wèn)本地資源,需要將public等不編譯資源一起拷貝到輸出目錄。
  4. 為避免源碼泄露和文件過(guò)大加載過(guò)慢,css等資源要進(jìn)行壓縮混淆處理,而不是簡(jiǎn)單地注入。
(一)準(zhǔn)備工作

由于開發(fā)階段和發(fā)布階段有很多類似操作,所以我們可以將部分公共配置抽離出來(lái)復(fù)用,然后通過(guò)不同變量和命令來(lái)執(zhí)行不同的打包操作。

  1. 新建webpack.common.js、webpack.dev.js、webpack.prod.js三個(gè)文件,分別用于存放公共配置、開發(fā)階段配置、發(fā)布階段配置。
  2. 將之前的webpack.config.js的內(nèi)容復(fù)制到webpack.common.js里,然后webpack.dev.js先直接簡(jiǎn)單引入導(dǎo)出。
const common = require('./webpack.common.js')

module.exports = common
  1. npm install cross-env -D安裝兼容設(shè)置環(huán)境變量的庫(kù)(window和mac不兼容NODE_ENV=development這樣設(shè)置變量),然后在package.json里的script增加以下配置(即先設(shè)置當(dāng)前環(huán)境變量,再根據(jù)對(duì)應(yīng)配置文件進(jìn)行打包):
"scripts": {
    ...,
    "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.dev.js",
    "build": "cross-env NODE_ENV=production webpack --config webpack.prod.js"
  },
  1. 命令行輸入npm run dev,則會(huì)直接運(yùn)行package.json中scripts.dev的命令,如果能跟之前一樣正常打開頁(yè)面則成功。
(二)抽離devServer

首先npm install webpack-merge -D安裝webpack中專門用于合并配置信息的庫(kù)(比Object.assign多做了一些特殊處理),然后將webpack.common.js文件里的devServer剪切到webpack.dev.js里。再次運(yùn)行npm run dev看是否正常。

// webpack.dev.js
const common = require('./webpack.common.js')
const {merge} = require('webpack-merge') // 版本不一樣,有些是直接merge = 有些要{merge} =

module.exports = merge(common, {
  devServer: {
    contentBase: ['public', '.'], // 額外指定找不到的資源(比如public里沒(méi)打包到dist的靜態(tài)資源)去哪里找
    port: 8080,
    open: true, // 是否自動(dòng)啟動(dòng)瀏覽器
    // hot: true, // 如果hot處理代碼有報(bào)錯(cuò),則仍然會(huì)自動(dòng)刷新整個(gè)頁(yè)面
    hotOnly: true, // 只做熱更新,無(wú)論有無(wú)報(bào)錯(cuò)也不自動(dòng)刷新整個(gè)頁(yè)面
    // overlay: { // 這里配置 html 頁(yè)面是否顯示 eslint 錯(cuò)誤信息蒙版 
    //   errors: true,
    //   warnings: true,
    // },
  },
})
(三)根據(jù)環(huán)境變量配置不同內(nèi)容

新建webpack_config.js文件(記得是_不是.,因?yàn)?code>webpack.config.js是webpack的默認(rèn)運(yùn)行文件),寫入以下內(nèi)容:

const path = require('path')
module.exports = {
  dev: {
    mode: 'development',
    outputPath: path.join(__dirname, 'temp'),
    devtool: 'eval-cheap-module-source-map',
  },
  build: {
    mode: 'production',
    outputPath: path.join(__dirname, 'dist'),
    devtool: 'nosources-source-map',
  },
}

更改webpack.common.js的以下四處內(nèi)容,再次運(yùn)行npm run dev跟之前一樣正常打開頁(yè)面則成功。

let config = require('./webpack_config.js')
config = process.env.NODE_ENV === 'production' ? config.build : config.dev

module.exports = {
  ...,
  output: {
    filename: '[name]_[contenthash:8].js', // 生成文件的名字
    path: config.outputPath, // 生成文件放在哪,output.path必須是絕對(duì)路徑
  },
  mode: 'none', // 此處修改為config.mode,為了方便演示暫時(shí)還用none
  devtool: config.devtool,
  plugins: [
    ...,
    new Webpack.DefinePlugin({
      ...,
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV || config.env), // 要是eval能運(yùn)行的語(yǔ)句,所以用JSON.stringify包裹字符串
      },
    }),
  ],
}
(四)拷貝public下的資源

npm install copy-webpack-plugin -D安裝插件,在webpack.prod.js寫入以下內(nèi)容。然后命令行輸入npm run build打包,看到生成dist目錄下各文件,點(diǎn)擊index.html頁(yè)面正常打開即代表成功。

const common = require('./webpack.common.js')
const {merge} = require('webpack-merge')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = merge(common, {
  plugins: [
    new CopyWebpackPlugin({patterns: [{from: 'public', to: 'public'}]}), // 拷貝public到對(duì)應(yīng)目錄,舊版本是new CopyWebpackPlugin(['public'])
  ],
})
(五)壓縮混淆資源
  1. 之前我們的css都是直接通過(guò)style-loader注入的,這樣不方便進(jìn)行專門的css處理、按需加載和HMR熱更新。我們可以用mini-css-extract-plugin來(lái)將css提取到單獨(dú)的文件中,npm install mini-css-extract-plugin -D安裝插件,更改以下文件內(nèi)容:
// webpack_config.js
module.exports = {
  dev: {
    ...,
    extract: false,
  },
  build: {
    ...,
    extract: true,
  },
}
// webpack.common.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  module: {
    rules: [
      {
        test: /\.(css|less)$/i,
        use: [
          config.extract ? MiniCssExtractPlugin.loader : 'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
    ],
  },
  plugins: [
    ...,
  ]
  .concat(config.extract ? [new MiniCssExtractPlugin({filename: '[name]_[contenthash:8].css'})] : []),
}
  1. 上面將css單獨(dú)提取出來(lái)后,我們就可以對(duì)css和js進(jìn)行專門的處理壓縮了。其實(shí)webpack本身就會(huì)對(duì)js的打包進(jìn)行一些優(yōu)化處理,但其他資源需要我們自行處理。npm install optimize-css-assets-webpack-plugin -D安裝壓縮css的插件,正常也是將該插件放在plugin選項(xiàng),但官方建議放在optimization里的minimizer中,這樣可以統(tǒng)一控制是否要開啟壓縮,比如mode: 'production'會(huì)自動(dòng)開啟minimizer。
  • 注意:當(dāng)我們配置了minimizer此項(xiàng)后,會(huì)導(dǎo)致webpack認(rèn)為我們要自定義處理,則不會(huì)再自動(dòng)壓縮js,所以需要npm install terser-webpack-plugin -D然后手動(dòng)添加js壓縮插件terser-webpack-plugin
// webpack.prod.js增加下面內(nèi)容
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserWebpackPlugin(), // js壓縮插件
      new OptimizeCssAssetsWebpackPlugin(),
    ],
  },
}

至此,發(fā)布階段的webpack打包構(gòu)建也已經(jīng)配置完成。更多定制化的功能可以前往webpack官網(wǎng)查看。

四、附錄

最后,附上本篇演示使用的各個(gè)包的版本號(hào)。如果操作中遇到版本不兼容問(wèn)題,可以嘗試使用下方的版本:

{
  "devDependencies": {
    "@babel/core": "^7.14.0",
    "@babel/preset-env": "^7.14.1",
    "babel-loader": "^8.2.2",
    "clean-webpack-plugin": "^4.0.0-alpha.0",
    "copy-webpack-plugin": "^8.1.1",
    "cross-env": "^7.0.3",
    "css-loader": "^5.2.4",
    "eslint": "^7.26.0",
    "eslint-config-airbnb-base": "^14.2.1",
    "eslint-friendly-formatter": "^4.0.1",
    "eslint-loader": "^4.0.2",
    "eslint-plugin-html": "^6.1.2",
    "eslint-plugin-import": "^2.22.1",
    "eslint-plugin-vue": "^7.9.0",
    "eslint-plugin-vue-libs": "^4.0.0",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^5.3.1",
    "less": "^4.1.1",
    "less-loader": "^8.1.1",
    "mini-css-extract-plugin": "^1.6.0",
    "optimize-css-assets-webpack-plugin": "^5.0.4",
    "style-loader": "^2.0.0",
    "terser-webpack-plugin": "^5.1.1",
    "url-loader": "^4.1.1",
    "vue-loader": "^15.9.6",
    "vue-style-loader": "^4.1.3",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^5.36.2",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.2",
    "webpack-merge": "^5.7.3"
  },
  "dependencies": {
    "vue": "^2.6.12"
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容