抓住2019年的尾巴,迎接2020年的到來~
給自己的2019年畫上一個完美的句號。
引言
webpack
對于現在的前端開發的你來說,不算陌生,你或許沒有真正去了解過它是如何使用的,但你的項目中確實使用過它,因為你項目的打包編譯都跟他息息相關~
前陣子剛好在研究webpack
以及其源碼相關的知識,如果你跟我一樣,好奇webpack
又是怎么工作的?那些奇奇怪怪的配置都是什么東西?分別代表什么意思?
那你不妨花幾分鐘閱讀一下,跟我一起學習回顧一下如何從0到1去了解webpack
的知識, 配置你項目需要的webpack
~
pass
:本文以 webpack4
為例~
什么是webpack?
什么是 webpack
?
官方文檔 是這么說:
webpack
是一個現代 JavaScript
應用程序的靜態模塊打包器(module bundler)
。當 webpack
處理應用程序時,它會遞歸地構建一個依賴關系圖(dependency graph)
,其中包含應用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle
。
其實,它就是一個模塊化打包工具,它所做的事情就是分析你的項目結構,找到JavaScript
模塊并對其進行代碼轉換(scss
轉換為css
、Typescript
轉換為 Javscript
),文件優化(壓縮JavaScript
、CSS
、HTM
L、圖片等),模塊合并 (把模塊分類合并成一個文件)等一系列的操作,最終打包為合適的格式在讓你的項目可以在瀏覽器中運行~
盜用官網的一張圖,其主要工作原理就如下圖所示~
核心概念
在真正上手 webpack
之前,我們需要對其幾個 核心概念 有所了解
Entry
:入口路徑,webpack
執行構建的第一步的輸入文件。Module
:模塊,在webpack
里一切皆模塊,一個模塊對應著一個文件,webpack
會從配置的Entry
開始遞歸找出所有依賴的模塊。Chunk
:代碼塊,一個Chunk
由多個模塊組合而成,用于代碼合并與分割。Loader
:模塊轉換器,用于把模塊原內容按照需求轉換成新內容,例如scss
到css
的轉換等,構建模塊的第一步就是使用loader來加載并處理模塊內容Plugin
:擴展插件,webpack
的重要組成部分,其webpack
源碼的很多核心功能也都是插件實現的,由于webpack
提供了在不同的生命周期內提供了很多不同的hooks
鉤子函數,插件的工作原理就是在webpack
構建流程中的不同的(hooks
)時機注入擴展邏輯來改變構建結果或做個性化操作。Output
:輸出結果,在webpack
經過一系列處理后最終代碼后輸出配置。
整個流程串起來大概就是:
webpack
啟動后會從Entry
里配置的Module
開始遞歸解析 Entry
依賴的所有 Module
。 每找到一個 Module
,就會根據配置的Loader
去找出對應的轉換規則,對 Module
進行轉換后,再解析出當前 Module
依賴的 Module
。
這些模塊會以 Entry
為單位進行分組,一個 Entry
和其所有依賴的 Module
被分到一個組也就是一個Chunk
。最后 webpack
會把所有 Chunk
轉換成文件輸出,在這整個流程中 webpack
會在不同的生命周期內執行配置的 Plugin
里定義的邏輯。
了解了上面的一些概念和流程之后,接下來,我們一步步來配置,打包我們的項目~
初始化項目
創建文件夾
首先,我們創建一個你喜歡的文件夾,并通過 npm init -y
來初始化項目配置,并在其目錄下創建一個我們源代碼的目錄src
和一個打包后的文件輸入目錄dist
。
創建入口文件 index.js
然后我們在 src
目錄下創建一個 index.js
文件,作為我們的打包入口文件,并寫上我們熟悉的 console.log('hello world');
作為打包內容。
安裝webpack
webpack4
之后將 webpack
和 cli
分成了兩個包,我們需要通過 npm install webpack webpack-cli -D
安裝我們所需的 webpack
依賴。
ok~ 準備就緒!
遺憾的是,你還是不能直接進行打包,因為我們的 webpack
是在項目下安裝的,所以不能直接運行,想要正確運行webpakc
我們可以有下面2種方式:
- 使用
npx
命令,可以直接運行node_modules/.bin
目錄下的命令 - 通過配置
package.json
中的scripts
腳本命令進行執行
為了貼近我們的項目,這里我們選擇第二種方式
配置package.json
腳本
我們打開package.json
文件,并在 scripts
中配置下面的代碼:
"dev" : "webpack --mode development",
"build" : "webpack --mode production",
dev
表示開發模式,build
是生產模式,不同在于 dev
會有很多方便我們開發調試的功能,比如代碼不壓縮混淆,有開發服務器之類的,我們學習階段采用 dev
即可~
創建配置文件
這時候,我們已經可以通過 npm run dev
命令打包我們的代碼,并在dist
目錄下看到我們打包后的 main.js
文件了~
你可能很詫異的蹦出一句:
因為到此,你發現自己什么都還沒配置,咋就可以打包了!!
這是因為 webapck4
為了簡化我們開發人員繁瑣的配置工作,在內部寫好了一套配置,驚不驚喜,意不意外!!
那我這肯定不能答應了,不然不就打我臉了么!
要想加載自己的配置,我們需要在我們的項目根目錄下創建 webpack.config.js
文件,并創建我們的基礎配置。
//path
const path = require('path');
//配置信息
module.exports = {
//入口文件
entry : './src/index.js' ,
//出口文件
output : {
//打包后路徑,只能寫絕對路徑
path : path.resolve(__dirname,'dist'),
//打包后文件名
filename : '[name].[hash].js'
},
//模塊轉換規則
module : {
},
//插件
plugins : [
],
//開發服務器
devServer : {
}
}
我們注意到 output
中的 filename
中有一個 [name]
,[hash]
,其中name
是 entry
的名字,默認是 main
,hash
是打包根據內容后計算出的一個 hash
值,保證文件的唯一性,可以通過[hash:8]
表示取其前8位。
現在運行 npm run dev
在 dist
目錄下就會打包出類似 main.47bfc309d4ba9b75d346.js
的文件。
這里,我們為了方便,先將其改成 main.js
創建index.html
文件
為了方便我們在瀏覽器測試,我們在我們的 dist
目錄創建一個 index.html
,并引入我們編譯好的main.js
文件,如下:
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webpack</title>
</head>
<body>
<div id="app">webpack</div>
<script src="main.js"></script>
</body>
</html>
我們在 index.js
文件下加上這么一句話:
document.querySelector('#app').style.color='red';
測試一下打包后的文件好不好使。
運行 npm run dev
,打開我們的 index.html
預覽,不出意外的話,結果應該和我一樣,頁面的 webpack
文字變紅,控制臺輸出 hello world
;
至此,我們才將我們的項目基礎配置搞定~
加載css
如果我們現在想加入 css
文件,優化我的樣式,首先在 src
目錄下創建 stylesheets
目錄,并添加 index.css
文件,我們就先以 body { background : #f2f2f2; }
為例,之后在 index.js
中通過 import './stylesheets/index.css'
的方式導入樣式文件。
如果現在我們直接進行打包肯定會報錯,因為 css
文件并不是 js
模塊,webpack
在打包的時候沒法直接處理,需要借助轉換工具,這轉換工具就是 Loader
。
- 什么是
Loader
?
Loader
就是文件轉換器,通過使用不同的Loader
,webpack
就可以把不同的文件都轉成js
文件,比如CSS
、ES6/7
、JSX
等,它通常有下面幾個配置項:
-
test
:匹配處理文件的擴展名的正則表達式 -
use
:loader
名稱,就是你要使用模塊的名稱 -
include/exclude
:手動指定必須處理的文件夾或屏蔽不需要處理的文件夾 -
query
:為loaders
提供額外的設置選項
接下來,我們來使用 style-loader
,css-loader
來處理我們的 css
文件。
執行 npm install style-loader css-loader -D
進行安裝 loader
在 webpack.config.js
中的module
下面添加解析規則:
module : {
rules : [{
test : /\.css$/,
use : ['style-loader','css-loader']
}]
},
通常來說,loader
有下面三種書寫方式,上面是通過 use
方式,還有兩種方式分別是 直接使用 loader
和使用 use + loader
:
//直接使用loader
module: {
rules: [{
test: /\.css/,
loader:['style-loader','css-loader']
}]
}
//use + loader 的方式
module: {
rules: [{
test: /\.css/,
include: path.resolve(__dirname,'src'),
exclude: /node_modules/,
use: [{
loader: 'style-loader',
options: {
insert:'top'
}
},'css-loader']
}]
}
要注意的是配置多個 loader
是 有順序 的,webpack
會安裝配置的 loader
順序 從右向左 執行的,配置的時候要格外注意!
拿我們上面的 style-loader
和 css-loader
來說,兩個loader
配置的順序不可調換,因為 css-loader
是解析處理css
里的url
路徑,并將css
文件轉換成一個模塊,style-loader
是 將css
文件變成style
標簽插入到head
中的。
現在我們 npm run dev
試試,打包沒有報錯,預覽 index.html
也成功生效,很贊!
配置開發服務器
到此你有沒有發現,我們在平時的開發過程中,怎么沒有遇到說讓我每次通過預覽dist
下的 index.html
來看我們打包效果的,這是由于我們平時的開發中會在自己本地起一個服務器,來幫我們做這件事。
現在,我們也來試試~
- 通過
npm i webpack-dev-server –D
安裝我們的開發服務器依賴 - 修改我們的啟動腳本,將原來的
package.json
中的dev
腳本修改為webpack-dev-server --open
,其中--open
是自動打開瀏覽器的意思
此時,直接運行 npm run dev
是看不到我們預期的效果的,因為我們還沒有對我們的服務器進行配置。
我們在 webpack.config.js
的 devServer
下添加如下配置:
devServer : {
contentBase : path.resolve(__dirname,'dist'),
host : 'localhost' ,
port : 8000 ,
compress : true
}
-
contentBase
配置開發服務運行時的文件根目錄,也就是靜態資源訪問地址 -
host
開發服務器監聽的主機地址 -
port
開發服務器監聽的端口,默認是 8080 -
compress
開發服務器是否啟動gzip
等壓縮
ok,運行 npm run dev
,是不是效果非常棒!
要注意的是,webpack dev server
產生的打包文件是在 內存中!,是 內存中!,硬盤是訪問不到的,怎么驗證這一點呢?
很簡單,你可以刪除掉你dist
目錄下的 main.js
,重新運行 npm run dev
,你可以看到 dist
目錄下并沒有 main.js
,但你訪問 localhost:8000
確實能正確訪問,并且訪問 http://localhost:8000/main.js
也能看到打包后的源碼,證明它產生的打包文件確實是在你的 內存中。
注意,我們這里打包出來的只有一個 main.js
文件和一個index.css
文件,index.html
文件是我們手動添加進去的,不是打包產生的,如果刪掉 index.html
是無法正確訪問頁面的,內存里可沒有 index.html
文件。
我們可以在終端看到以下這些內容:
這些都是我們在啟動開發服務器的時候 webpack
給我們的頁面注入的 websocket
連接,你可以在你的頁面調試器的 network
中的 ws
里看到,
其重要作用就是,監控你文件的變化,可以幫助你重新刷新頁面,讓你看到更改后的效果,你可以修改一下 index.js
文件試試~
自動生產HTML文件
我們之前是在 dist
目錄下寫好了 index.html
文件,并在里面通過 script
標簽引入我們打包后的內容,即 main.js
~
還記得我們之前打包后的 filename
中可以加入一個 hash
值也區別不同的文件,如果 hash
值發生變化了,我們的 index.html
豈不是找不到資源了?所以我們希望自動能產出HTML
文件,并在里面引入產出后的資源,這樣就不必為上面的問題擔心了。
我們刪除掉 dist
目錄下的 index.html
文件,并在 src
目錄下創建一個 index.html
文件,我們稱它為模板,以它為模板產生 html
文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>webpack</title>
</head>
<body>
<div id="app">webpack</div>
</body>
</html>
這時,我們需要接觸到第一個插件 html-webpack-plugin
!
之前也說了,插件在 webpack
中有很重要的作用,在 webpack
的構建流程中,plugin
用于處理更多其他的一些構建任務,模塊代碼轉換的工作由 loader
來處理,除此之外的其他任何工作都可以交由 plugin
來完成。
- 首先我們需要通過
npm install html-webpack-plugin -D
去安裝它。 - 然后在
webpack.config.js
中plugins
下去配置它(需要先通過require
引入)
//自動產出HTML模版
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
hash: true,
minify: {
removeAttributeQuotes: true,
removeComments: true
}
})
其中 template
是指定模板文件,filename
是指定產出后的文件名,hash
是為了避免緩存,可以在產出的資源后面添加hash
值,minify
是 壓縮相關的配置,minify.removeAttributeQuotes
是為了去掉屬性的雙引號,minify.removeComments
是為了壓縮文件,刪除模板中的注釋。
此時,我們運行 npm run dev
訪問 localhost:8000
發現已經可以正常訪問了,但是 dist
目錄下卻沒有任何東西,因為我們之前提到了,開發服務器打包的文件是寫入內存中的,不是硬盤里。
為了方便我們看效果,我們在 package.json
中的 scripts
中在增加一行 "dev-build": "webpack --mode development"
用來打包我們開發環境的代碼。
運行 npm run dev-build
腳本,完成之后可以發現 dist
目錄已經打包出來了 index.html
文件 和 main.[hash].js
文件,打開 index.html
文件可以發現標簽的雙引號已經沒去掉了,并且引入的腳本也自動加上了 ?[hash]
值。
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=UTF-8>
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Title</title>
</head>
<body>
<div id=app>webpack</div>
<script type=text/javascript src=main.e6570abab6c2814d1608.js?e6570abab6c2814d1608></script></body>
</html>
預覽 index.html
文件,一切也都正常。
pass
:webpack4
以后,如果你看到終端輸入有下面這么怪異的一行,
而正巧你又是一個 強迫癥患者,在 webpack.config.js
中添加 stats: { children: false }
即可。
支持圖片
前端項目中肯定少不了圖片資源,如果我們直接在 css
或者 js
文件中引入圖片資源去打包,那么肯定是通不過了,因為 webpack
無法識別圖片資源,因為圖片也不是一個有效的模塊。
此時,我們需要引入這個兩個 loader
去解決它, file-loader url-loader
,file-loader
解決CSS
等文件中的引入圖片路徑問題,url-loader
當圖片小于limit
的時候會把圖片base64
編碼,大于limit
參數的時候還是使用file-loader
進行拷貝
- 通過
npm install file-loader url-loader -D
下載依賴 - 在
src
目錄下創建一個images
文件夾,存放幾張你喜歡的圖片 - 在
index.js
和index.css
中引入圖片,并將其插入到頁面中去(我這里以本地的avatar.jpg
和scene.jpg
為例)
//index.js
import Avatar from './images/avatar.jpg'
let img = new Image();
img.src = Avatar;
document.body.appendChild(img);
//index.css
body{
background-color: #f2f2f2;
background-image: url("../images/scene.jpg");
background-repeat: no-repeat;
}
- 在
webpack.config.js
中的module
下面添加如下配置
{
test:/\.(png|jpg|gif|svg|bmp)$/,
use:{
loader: 'url-loader',
options: {
limit: 10 * 1024,
outputPath: 'images/'
}
}
}
options
中的 limit
就是圖片的限制,這里我指定的是 10kb
,小于 10kb
的圖片會以 base64
編碼輸出,outputPath
指定了拷貝文件輸出目錄,默認是dist
目錄下。
現在我們 npm run dev-build
走一波~
也不報錯,運行 index.html
文件,也很正常!
編譯less 和 sass
現在開發過程中,為了簡化我們書寫 css
的過程,我們一般項目中引入了 less
和 sass
這樣的預加載器~
同樣的你不處理之前 webpack
是不認識 less
和 sass
文件的,畢竟它不是一個 js
模塊,我們通過需要借助 less-loader
和 sass-loader
來處理這些文件~
- 通過運行
npm install less less-loader -D
npm install node-sass sass-loader -D
分別安裝loader
- 在
webpack.config.js
中添加loader
解析規則
{
test: /\.less/,
use: ['style-loader', 'css-loader', 'less-loader']
}, {
test: /\.scss/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
這樣,你就可以放心在你的項目里引入 css
預處理了~
分離css
因為CSS
的下載和js
可以并行,當一個HTML
文件很大的時候,那么頁面加載肯定會非常慢,那么我們希望可以把CSS
單獨提取出來加載,為每個包含 CSS
的 JS
文件創建一個 CSS
文件,按需加載。
我們需要 mini-css-extract-plugin
這么一個插件
- 通過
npm install mini-css-extract-plugin -D
安裝模塊依賴 - 在
webpack.config.js
中plugins
下去配置一下
new MiniCssExtractPlugin({
filename: 'css/[name].[hash].css',
chunkFilename: "css/[id].css"
})
除此之外,我們的還需要做一個操作就是將我們之前處理css
的 style-loader
改寫成下面這種形式:
{
test: /\.css$/,
use: [{
loader: MiniCssExtractPlugin.loader
}, 'css-loader']
},{
test: /\.less/,
use: [{
loader: MiniCssExtractPlugin.loader
}, 'css-loader', 'less-loader']
}, {
test: /\.scss/,
use: [{
loader: MiniCssExtractPlugin.loader
}, 'css-loader', 'sass-loader']
}
趁熱打鐵,趕緊來試試,npm run dev-build
進行打包~
預覽 index.html
頁面,打開控制臺network
可以發現下載文件的時候多出了一個 main.css
文件,并且我們 html
的 head
頭,已經換成了 link
方式,并且你的 dist
目錄下會多出一個 css
的文件夾,里面存放打包后的 css
文件。
tips
: 如果你在外部的css
文件中文件中引入圖片,而圖片放在了images
目錄下,那么打包上線后的圖片會出現 404
的情況,你可以查看打包后的 css
文件,就可以反向是路徑的問題,需要配置一下 publicPath
即可~
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '/'
}
}
注意,這個一般是在 服務器 上會出現,本地打包后沒有起服務也是看不到的。
處理CSS3屬性前綴
我們在書寫 css
的時候,為了瀏覽器的兼容性,有時候我們必須加入-webkit
,-ms
,-o
,-moz
這些瀏覽器前綴,但我們又不想去書寫這些繁瑣的東西,這時候可以交給我們 postcss
來處理~
postcss
的主要功能只有兩個:
- 第一個就是前面提到的把
CSS
解析成JavaScript
可以操作的 抽象語法樹結構(Abstract Syntax Tree,AST)
- 第二個就是調用插件來處理
AST
并得到結果
我們首先通過 npm install postcss-loader autoprefixer -D
來安裝依賴
想要這個 postcss
正常工作,我們需要配置兩個東西
- 在根目錄下創建
postcss.config.js
配置文件,表示使用autoprefixer
來進行補全
module.exports={
plugins:[require('autoprefixer')]
}
- 在
webpack.config.js
中修改并添加對css
處理的loader
{
test: /\.css$/,
use: [{
loader: MiniCssExtractPlugin.loader
}, 'css-loader', 'postcss-loader'],
include: path.join(__dirname, './src'),
exclude: /node_modules/
}
這里我在我的 index.css
中添加了如下測試代碼:
//index.css
::placeholder {
color: orange;
}
并在我的 index.js
中創建了一個 input
控件:
//index.js
let input = document.createElement('input');
document.body.appendChild(input);
運行 npm run dev-build
打包,預覽 index.html
,打開調試工具的的 sources
板塊,查看 main.css
, 發現對應的前綴已添加,并且我頁面的 input
已經變成了 orange
~
轉義ES6/ES7
雖然 es6
和 es7
的代碼我們已經或多或少都在項目中,但是大部分瀏覽器對于 es6
和 es7
代碼的支持度并不高,很大部分的瀏覽器還是只能解析 es5
的代碼,為了讓我們能正常使用 es6
、es7
的代碼,我們需要借助 webpack
對其進行轉義,轉成 es5
代碼。
我們需要借助 babel
這個工具,它是一個編譯JavaScript
的平臺,可以把ES6/ES7
的代碼轉義為ES5
代碼。
- 通過
npm install babel-loader @babel/core @babel/preset-env -D
安裝依賴 - 在
webpack.config.js
中添加babel-loader
,因為babel-loader
只是告訴了webpack
怎么處理ES6
,ES7
代碼,但它并不會將ES6
,ES7
代碼翻譯成向后兼容版本的代碼,因此需要指定一個preset
,它包含了代碼轉換的規則
{
test: /\.js$/,
loader : 'babel-loader' ,
exclude:'/node_modules/'
}
- 在我們的項目根目錄創建一個
.babelrc
的文件來配置,用來配置我們的babel
相關
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": [
"> 1%",
"last 2 versions"
]
},
"debug":true //調試使用
}
]
]
}
- 我們在
index.js
文件中添加以下代碼測試一下,并打包測試一下:
const test = (n)=> {
return new Promise(function (resolve) {
setTimeout(()=>{
resolve([1,2,3,4].map(v=>v * v ))
},n*1000)
}).then(res=>{
console.log(res);
})
}
console.log(test)
查看打包后的文件,發現轉換的不夠徹底,只能針對語法進行了轉換,對于 Promise
、map
這些高級用法并沒有被轉換,這肯定是不行的,我們還要想辦法把這些新的特性,兼容到低版本的瀏覽器里。
我們還需要 babel
提供的另一個工具—— polyfill
,
-
npm install @babel/polyfill -D
安裝它 - 在我們的入口文件
index.js
最頂部添加import '@babel/polyfill'
- 運行
npm run dev-build
編譯打包,雖然控制臺好想沒啥變化,但是我們的打包的文件main.js
發生了很大變化,很明顯的一點,體積大了好幾十倍
這是由于為了兼容低版本瀏覽器,polyfill
里面添加了很多輔助代碼來幫助實現比如 Promise
和 map
這些新特性,默認情況下會被添加到每一個需要它的文件中,并且會全局注入,造成全局污染,如果我們在開發框架之類的,可能會發生沖突。
我們加了 debug
可以在終端看到,確實是加入了不少插件:
為了解決這個問題,我們引入 @babel/runtime
這個模塊,來避免重復導入的問題
如果是寫第三方庫或者框架
- 運行
npm install @babel/runtime @babel/plugin-transform-runtime -D
安裝模塊依賴 - 配置
@babel/runtime
,并修改一下preset-env
的配置,加上useBuiltIns: 'usage'
,表示會根據業務需求自動轉換需要轉換的新語法
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"targets": {
"browsers": [
"> 1%",
"last 2 versions"
]
},
"debug":true //調試使用
}
]
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": false,
"helpers": true,
"regenerator": true,
"useESModules": true
}
]
]
}
- 配置完成,ok,我們再來運行
npm run dev-build
打包一次試試
終端日志可以看到注入的輔助代碼大幅度較少,文件的大小也大幅度減少,贊!
拷貝靜態文件
我們有些項目中的文件,不是 js
,也不是 css
, 圖片之類的,比如 README.md
這些靜態資源,我也希望能打包到我的項目里,怎么辦呢?
其實就是文件的拷貝操作,我們只需要將這些文件拷貝到目標目錄下即可,我們可以利用 copy-webpack-plugin
這個插件
- 運行
npm run copy-webpack-plugin -D
安裝插件 - 在項目目錄下創建一個
static/README.md
的測試文件 - 修改
webpack.config.js
, 將插件添加到配置里去
new CopyWebpackPlugin({
from: path.resolve(__dirname,'src/static'),
to:path.resolve(__dirname,'dist/static')
})
from
是靜態資源目錄源地址,to
是要拷貝文件的目標地址,so easy~
npm run dev-build
打包運行!
可以發現我們的 dist
目錄已經將 src/static
的文件拷貝到了 dist/static
中
打包前清空
我們修改了文件之后,每次打包都會在 dist
目錄下產生一個新的 main.[hash].js
, 隨著我們打包次數的增加,dist
目錄下會生產出一堆的 main.[hash].js
,不出意外,你的dist
目錄應該已經有不少了~
為了保證我們每次看到的都是最新的打包資源,而不受之前打包文件的干擾,這里我們需要引入另一個插件—— clean-webpack-plugin
- 通過
npm install clean-webpack-plugin -D
下載插件 - 在
webpack.config.js
中plugins
下去配置它
plugins:[
new CleanWebpackPlugin()
]
pass
:該插件引入方式是稍微有點不同,通過以下這種方式引入:
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
現在,每次打包前都會先清空 dist
目錄下的文件,然后才產出打包后的文件,這樣看起來就清晰多了!
服務器代理
我們在開發時,有時候希望在同域名下發送 API
請求 ,那么代理某些 URL
會很有用,代理 API
的配置對于 webpack
來說,配置就非常簡單了,只需要在 proxy
中添加代理規則即可
proxy : {
"/api/test": {
target: 'http://lohost:3000/',
secure: false,
changeOrigin: true,
pathRewrite: {
'^/api/test': '/test'
}
}
上面這行配置,就可以將 /api/test
開頭的接口地址,會被代理到 http://localhost:3000/test
下,如果是https
接口,需要配置 secure
這個參數 為 true
,如果接口跨域,需要配置changeOrigin
這個參數為 true
壓縮JS和CSS
我們現在打包出來的文件無論是 js
和 css
都是源文件,我們希望在打包的時候壓縮我們的代碼,一來是為了安全,二來是可以減少我們打包文件的體積。
我們選擇使用terser-webpack-plugin
來壓縮js
文件,替換掉之前的 uglifyjs-webpack-plugin
,解決uglifyjs
不支持es6
語法問題,使用 optimize-css-assets-webpack-plugin
來壓縮 css
文件
- 運行
npm install terser-webpack-plugin optimize-css-assets-webpack-plugin -D
安裝插件 - 在
webpack.config.js
中引入并配置插件
new TerserPlugin({
parallel: true,
cache: true
}),
new OptimizeCSSAssetsPlugin({
assetNameRegExp:/\.css$/g,
cssProcessor:require('cssnano')
})
TerserPlugin
中的 parallel
代表開啟多進程,cache
代表設置緩存,OptimizeCSSAssetsPlugin
中加載了一個 cssnano
的東西, cssnano
是PostCSS
的CSS
優化和分解插件,會自動采用格式很好的CSS
,并通過許多優化,以確保最終的生產環境盡可能小。
現在我們在繼續打包一次!
查看我們打包后的文件,可以發現 js
和 css
文件都沒打包成了一行,搞定!
結語
ok~ 看到這里,想必你對 webpack
已經有了一個比較完善的認識,對常見的一些配置打包的 loader
或者 plugin
都有一定的了解了,總結會發現,套路基本都差不多,需要什么 loader
和 plugin
只要去對應去查找即可~
emmm
,其實 webpack
的功能非常強大,配置也是相當的多樣化,這里只是列舉了一些比較常見的功能,對你來說也只是一個拋磚引玉的作用,它的內部實現也是相當的復雜,想要真正弄懂 webpack
,還是需要多下一番苦功夫的~
對了,2019年還有幾個小時就結束了~
2020年,加油~