一、大概思路
(一)開發(fā)階段的打包構(gòu)建
- 配置打包的入口文件和輸出目錄等信息。
- 清空構(gòu)建目錄舊文件奶浦。處理js文件略就。
- 處理打包js/css/vue/圖片字體等捎迫。
- 將打包結(jié)果注入html。
- 啟動(dòng)服務(wù)器預(yù)覽頁(yè)面表牢,并監(jiān)聽變化窄绒。
- 增加eslint檢測(cè)。
- 配置sourceMap等信息崔兴。
(二)發(fā)布階段的打包構(gòu)建
- 配置打包的入口文件和輸出目錄等信息彰导。
- 清空構(gòu)建目錄舊文件蛔翅。處理js文件。
- 處理打包js/css/vue/圖片字體等(發(fā)布階段還需要對(duì)css/js進(jìn)行壓縮混淆)位谋。
- 拷貝public資源山析。
- 將打包結(jié)果注入html。
- 增加eslint檢測(cè)掏父。
- 配置sourceMap等信息笋轨。
二、“開發(fā)階段打包構(gòu)建”具體實(shí)現(xiàn)
(一)準(zhǔn)備工作
- 請(qǐng)確保自己本地已有npm或yarn等包管理工具赊淑,本文用npm做演示爵政。
- 下載該演示項(xiàng)目,或者自行vue-cli創(chuàng)建一個(gè)項(xiàng)目陶缺。
- 在該文件夾下空白處“按shift+鼠標(biāo)右鍵”钾挟,選中“在此處打開命令行/powershell窗口”打開命令行窗口,或者自行通過(guò)命令窗口cd到該文件目錄下组哩。
- 命令行輸入
npm init
回車等龙,自行填寫信息一路回車,最后生成package.json配置文件伶贰。 - 命令行輸入
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ì)版本見最后附錄)黍衙。 - 在示例項(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/圖片/字體
-
處理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處理)。
-
處理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)碼插件都放在這里面。 -
處理vue: 安裝vue處理需要的loader和依賴奸远,
npm install vue vue-loader vue-template-compiler -D
制肮,vue-loader還要搭配插件VueLoaderPlugin使用。 -
處理字體和圖片:安裝依賴
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)聽文件變化自動(dòng)重新打包但需要手動(dòng)刷新,可以用browser-sync temp --file "**/*"
實(shí)現(xiàn)自動(dòng)刷新墅拭。但由于又要寫入磁盤再讀出磁盤活玲,會(huì)比較慢。 - webpack-dev-server能自動(dòng)運(yùn)行打包編譯和監(jiān)聽刷新谍婉,將打包內(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):
- 不需要啟動(dòng)服務(wù)器調(diào)試。
- 構(gòu)建的輸出目錄不同楣黍,sourceMap等配置不同匾灶。
- 由于無(wú)法訪問(wèn)本地資源,需要將public等不編譯資源一起拷貝到輸出目錄租漂。
- 為避免源碼泄露和文件過(guò)大加載過(guò)慢阶女,css等資源要進(jìn)行壓縮混淆處理,而不是簡(jiǎn)單地注入哩治。
(一)準(zhǔn)備工作
由于開發(fā)階段和發(fā)布階段有很多類似操作秃踩,所以我們可以將部分公共配置抽離出來(lái)復(fù)用,然后通過(guò)不同變量和命令來(lái)執(zhí)行不同的打包操作业筏。
- 新建
webpack.common.js吞瞪、webpack.dev.js、webpack.prod.js
三個(gè)文件驾孔,分別用于存放公共配置芍秆、開發(fā)階段配置、發(fā)布階段配置翠勉。 - 將之前的
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
-
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"
},
- 命令行輸入
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'])
],
})
(五)壓縮混淆資源
- 之前我們的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'})] : []),
}
- 上面將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"
}
}