如果此篇對您有所幫助,在此求一個star。項目地址: OrcasTeam/my-cli
webpack-dev-server使用
什么是webpack-dev-server
使用vue-cli 、react-cli腳手架時,執行yarn start
命令會啟動一個本地服務器,瀏覽器訪問服務器就可以預覽代碼,並且代碼文件更新后頁面會重新加載數據,非常方便,這個功能就叫做dev-server。
在webpack中,由webpack-dev-server提供。
webpack-dev-server 庫作用開啟一個服務器。瀏覽器訪問服務器時,與瀏覽器使用WebSocket進行長鏈接。
並且webpack-dev-server 會開啟webpack監聽本地代碼文件功能。當本地代碼文件更新后,進行重新打包編譯,webpack-dev-server 通過WebSocket將更新模塊信息推送給瀏覽器。瀏覽器根據此次編譯信息,去獲取最新代碼,一個大致這樣的操作。
🐋 webpack本身就支持監聽文件變化,webpack-dev-server只是默認開啟webpack的監聽屬性。
webpack-dev-server庫並不復雜,不過里面涉及到的東西有些多。
關於webpack-dev-server庫,想深入的介紹下。
在此分為兩篇來介紹:
- 介紹webpack-dev-server屬性配置,並且介紹部分屬性源碼中的設置
- 稍微介紹webpack-dev-server流程和原理。
webpack-dev-server 安裝
webpack-cli/bin/config-yargs 的問題
截至到寫此篇時,webpack-dev-server的最新版本是3.11.2

有使用過此版本的朋友會知道,webpack-dev-server@3.11.2與webpack@5.X共同使用時會具有一個錯誤:Cannot find module 'webpack-cli/bin/config-yargs
這個問題個人感覺是官方有些坑了。
先來安裝webpack-dev-server@3.11.2,看看這個錯誤。
yarn add -D webpack-dev-server@3.11.2
使用過webpack-dev-server的朋友都會知道,執行webpack-dev-server的命令為:webpack-dev-server
官方NPM文檔中也是webpack-dev-server
命令

一般都會將yarn start
命令設置為:webpack-dev-server
,
🐋 在這里將
yarn start:dev
命令設置為:webpack-dev-server
。主要是為了這個錯誤

此時,如果不出意外的話, 執行yarn start:dev
就可以執行webpack-dev-server。
但是,執行就會碰到那個錯誤:

錯誤提示是找不到webpack-cli庫中的config.yargs模塊。感覺會有不少剛學習webpack並且搜索能力稍微弱一些的朋友會卡在這。
🐋 配置使用的webpack-cli@4.5.0和webpack@5.24.0
這個錯誤其實很簡單,直接在issues就可以找到答案。

原來是使用了新的執行命令了:webpack serve
。現在將新命令進行配置

此時使用yarn start
執行就可以成功執行。默認啟動的是8080端口

那么這到底怎么回事呢?通過查看源碼和測試webpack-dev-server@4.0.0beta.0個人略有些猜測。
先看一下webpack-dev-server@3.11.2中 /bin/webpack-dev-server.js 文件模塊中一段代碼。
/bin/webpack-dev-server.js會是使用webpack-dev-server
命令執行的文件模塊

在 /bin/webpack-dev-server.js 文件模塊中加載了webpack-cli庫中的 /bin/ [config/] config-yargs 和 /bin/ [utils/] convert-argv 。
但是在版本 代碼結構進行了巨大的改變,已經去掉了這兩個文件模塊,所以也就導致了報錯。

這個問題就是目前處於迭代期的原因。
在之前使用webpack@4.X版本時,使用的webpack-cli@3.X和webpack-dev-server@3.X
現在更新到了webpack@5.X,webpack-cli也進行了大版本的更新:webpack-cli@4.X。並且內部結構發生了巨大的變化。
但是webpack-dev-server的新版本還沒有開發完成,並且webpack-dev-server@3.X代碼沒有修復這個問題。
webpack-cli@4.X中加入了webpack serve
這個新命令。webpack serve
也是以后webpack推薦的命令。
webpack-dev-server
這個,命令問題在webpack-dev-server@4.X中修復了。不過目前webpack-dev-server@4.X只有一個webpack-dev-server@4.0.0beta.0。
還沒有穩定版本

在webpack-dev-server@4.0.0beta.0的代碼可以看到 /bin/webpack-dev-server.js 文件模塊中沒有了上面兩段代碼。

在webpack-dev-server@4.0.0beta.0文檔中的命令改為了webpack serve
。不過webpack-dev-server
依然可以使用。

🐋🐋🐋 webpack-cli@4.X版本開始,webpack團隊將dev-server的命令改為了
webpack serve
。webpack與webpack-cli都進行了大版本的更新。webpack-dev-server目前新版本還沒有開發完成。所以暫時就出了這么一個問題
webpack serve
命令在 webpack-cli@4.0.0版本文檔中可以找到。

webpack serve
關於webpack serve
命令的執行,執行入口文件與webpack
命令一樣,都是 webpack 庫的 /bin/index.js 。在此文件模塊中調用了webpack-cli庫模塊。
然后在webpack-cli庫根據其命令參數調用@webpack-cli庫中的 /serve/lib/index.js ,在此模塊文件中啟動 webpack-dev-server服務器。這些代碼都是webpack-cli@4.X版本新增加的。詳細內容在下一篇介紹。

🐋🐋 webpack、webpack-cli、webpack-dev-server跨庫調用都是根據模塊路徑調用。所以只要某個庫文件結構稍微改動,就會像
webpack-dev-server
命令這樣直接報錯。 不過在新版本代碼進行了優化,通過約定名稱進行跨庫調用。盡可能降低了耦合度。
🐋 @webpack-cli是webpack-cli@4.X依賴的一個庫。
webpack-dev-server@3.X 和webpack@5.X WebSocket問題
執行yarn start
后,會開啟一個8080端口的服務器。
但是webpack@5.X和webpack-dev-server@3.X一起使用時WebSocket還有問題
上面簡單說過WebSocket是與瀏覽器建立長鏈接,通過WebSocket向瀏覽器推送信息進行改變瀏覽器狀態。
下面來做一個測試,運行yarn start
后,使用瀏覽器訪問。

此時如果將代碼更新,會發現瀏覽器並沒有同步更新,並且瀏覽器WS窗口沒有推送數據
🐋 WS“:WebSocket數據顯示窗口


后來我對源碼進行了調試,發現根本就沒有連接WebSocket Server。
最后在github中找到了答案。
原因是package.json文件中的browserslist屬性,將此屬性去掉就可以進行推送。

這是webpack-dev-server@3.X的一個問題。但是按照官方給出的解釋好像只會在webpack-dev-server@4.X中修復這個問題。

我也使用webpack-dev-server@4.0.0beta.0版本進行了測試,這個bug被修復了。
版本選擇
目前webpack@5.X穩定版才4個月,並且webpack-dev-server還沒有對應新版本的穩定版。所以webpack@5.X還只能供學習使用。
在此直接使用webpack@5.24.0+webpack-cli@4.5.0+webpack-dev-server@4.0.0beta.0版進行學習。
webpack-dev-server@4.0.0beta.0 屬性配置相對webpack-dev-server@3.X稍微有些變動,在此也會稍微提一提webpack-dev-server@4.0.0beta.0與webpack-dev-server@3.X屬性對應關系和差異性。
yarn add -D webpack-dev-server@4.0.0beta.0
🐋🐋 webpack-dev-server@4.0.0beta.0 提供了比較完善的錯誤提示,當設置了錯誤屬性時,webpack-dev-server@4.0.0beta.0能夠給出詳細提示信息。
webpack-dev-server配置
webpack-dev-server屬性是配置在webpack配置文件中的devServer屬性。webpack-dev-server執行時會讀取這個屬性來做配置。
由於webpack-dev-server只是開發時使用的一個功能,所以配置屬性寫在webpack.dev.js文件中就可以
const path = require('path');
const { merge } = require('webpack-merge');
const { config } = require('./config');
const common = require('./webpack.common');
// 使用node.js的導出,將配置進行導出
module.exports = merge([
common(true),
{
mode: 'development',
devServer:{
// 服務器host,默認為localhost,
host: '127.0.0.1',
// 服務器端口號,
// 默認為8080
port: 7777,
// string | boolean
// 啟動后是否打開瀏覽器
// 默認為false,如果設置為true, 啟動時會自動打開瀏覽器
// 當為字符串時,打開指定瀏覽器
open: true, // 'chrome'
// 打開瀏覽器后默認打開的頁面
// string | Array<string>
// 當設置為Array時,會打開多個頁面
openPage: '', // ['', 'index.html'], //'index.html',
// 是否啟用gzip壓縮,
// 默認為false
compress: true,
// 是否啟動熱更新(HMR)
// 默認為false,
// 熱更新使用的是webpack中HotModuleReplacementPlugin
hot: true,
// 設置允許訪問的IP地址,設置為true,則不允許任何IP訪問,
// 也可以設置為數組,與webpack-devser@3.X 的allowedHosts一樣
// 此屬性相當於webpack-devser@3.X 的allowedHosts屬性
firewall: true,
// 是否設置HTTP/2服務器。
// 對於nodeV10以上的版本 由於spdy有問題
// 所以如果將此屬性設置為true,則默認使用https作為服務
http2: false,
// // 是否使用https安全連接
// // boolean 或者 object
// // 當為object時,可以設置安全證書
// // 默認為false,但是當開啟http2屬性時,會默認使用https 默認情況下, dev-server使用HTTPS為HTTP/2提供服務
// https: {
// // 證書,證書屬性也可以設置在devServer下,當https設置為boolean時, 與https同級設置
// key: '',//fs.readFileSync('/path/to/server.key'),
// cert: '',//fs.readFileSync('/path/to/server.crt'),
// ca: '',//fs.readFileSync('/path/to/ca.pem'),
// },
// 服務器代理配置,當前后端分離開發時,前端請求API需要指定地址
// 此屬性可以設置代理的IP地址
// 例如如下,當api請求 /api/user真實地址為http://localhost:3000/user
// 詳情使用請參考官網https://webpack.js.org/configuration/dev-server/#devserverproxy
proxy: {
'/api':{
target: 'http://localhost:3000',
// pathRewrite屬性可以設置前綴,如果不設置pathRewrite: /api/user真實地址為http://localhost:3000/api/user
pathRewrite: {'^/api' : ''},
// HTTPS設置為無效證書
// secure: false
}
},
// 服務器返回時加入的response的自定義header
headers: {
'X-Custom-Foo': 'bar'
},
// 靜態文件屬性
// 此屬性是對webpack-devser@3.X某些屬性的匯總
static: {
// 要掛載在服務器上靜態文件的本地目錄
// 默認為為當前工作目錄
// 建議使用絕對地址
// 例如設置為 /assets后, 會加載使用本地/assets目錄下的靜態文件到服務器
// 相當於webpack-dev-server@3.X的 contentBase屬性
directory: path.join(config.root),
// 掛載到服務器中間件的可訪問虛擬地址
// 例如設置為/static,在訪問服務器靜態文件時,就需要使用/static前綴
// 相當於webpack-dev-server@3.X的 contentBasePublicPath屬性
publicPath: '/',
// 設置掛在靜態文件時使用的參數
// 相當於webpack-dev-server@3.X的 staticOptions屬性
staticOptions: undefined,
// 是否加入serve-index中間件,默認為true
// 相當於webpack-dev-server@3.X的 // 是否可以在瀏覽器訪問靜態文件列表。
// 默認為true,webpack-dev-server使用的是serve-index中間件實現這一功能
// 相當於webpack-dev-server@3.X的 serveIndex屬性
serveIndex: true,
// 是否使用chokidar庫進行監聽文帝靜態文件變化。
// webpack使用的是文件系統的的變化通知,但是有時候可能會不管用,例如使用網絡文件系統
// 所以可以設置屬性使用chokidar庫進行輪詢檢測文件變化。
// 此屬性可以設置為boolean類型也可以設置為對象類型指定輪詢時間(毫秒數)
// 相當於webpack-dev-server@3.X的 watchOptions屬性
watch: {
poll: 3000
},
},
// 設置WebSocket客戶端的一些屬性
client: {
// 推送客戶端日志級別,
// 屬性具有 "none" | "error" | "warn" | "info" | "log" | "verbose"
// 例如設置error ,WS並不是推送打包警告和消息, WS客戶端會將日志打印在控制台上
// 如果設置為none, 就算打包失敗也不會有消息
// 相當於webpack-dev-server@3.X的 clientLogLevel屬性
logging: 'verbose',
// 是否在瀏覽器控制台打印打包進度,
// 相當於webpack-dev-server@3.X的 progress屬性
progress: true,
// 相當於webpack-dev-server@3.X的 sockPath屬性
// path: '',
// 相當於webpack-dev-server@3.X的 sockHost屬性
// host: '',
// 相當於webpack-dev-server@3.X的 sockPort屬性
// port: '',
},
public: undefined,
// webpack-dev-middleware中間件使用的屬性
dev:{
// 設置服務器response加入的自定義header信息
// 此屬性在webpack-dev-middleware中間件使用
headers:{
// 響應頭添加數據
'X-Dev-Header': 'X-Dev-Header',
serverSideRender: false,
},
// 設置webpack-dev-middleware中間件的mimeTypes
// 相當於webpack-dev-server@3.X的 mimeTypes屬性
// 相當於webpack-dev-server@3.X的 mimeTypes屬性
mimeTypes:{
},
// 是否將打包結果寫入到磁盤之中
// 默認為false
// 相當於webpack-dev-server@3.X的 writeToDisk屬性
writeToDisk: true,
// 設置打包文件存儲的目錄地址。此屬性由webpack-dev-middleware設置
// 例如當設置為/public,那么訪問服務器所有信息都需要加入/public前綴
// 相當於webpack-dev-server@3.X的 publicPath屬性
publicPath: '/',
// 設置根目錄所指向的頁面。
// 例如localhost:8080可以直接訪問到index.html是因為默認值為index.html
// 默認值也是index.html
// 相當於webpack-dev-server@3.X的 index屬性
index: 'index.html',
// none" | "summary" | "errors-only" | "errors-warnings" | "minimal" | "normal" | "detailed" | "verbose" | boolean | object { … }
// 設置打包文件日志輸出級別,會輸出在服務器終端
// 相當於webpack-dev-server@3.X的 stats屬性
stats: 'minimal',
// 自定義打包文件的輸出流
// 默認情況下,輸入流為memory
outputFileSystem: undefined,
methods: undefined,
serverSideRender: undefined
},
// 設置編譯出錯或警告后,頁面是否會直接顯示信息, boolean | {}
// 默認為false,當失敗后會顯示空白頁
// 設置為true后,編譯失敗會顯示錯誤/警告的覆蓋層,也可以設置為object,顯示多種類型信息
overlay: {
warning:true,
errors: true
},
// 是否要注入WebSocket客戶端。也就是是否要進行長鏈接通訊
// boolean | function (compilerConfig) => boolean
// 將此屬性設置為false,那么hot、overlay等功能都會失效
// 默認為true, 有興趣的諸君可以設置為false測試一下
injectClient: true,
// 是否注入HMR, 這個屬性是injectClient的子集。只影響熱更新
injectHot: true,
// 是否開啟自動刷新瀏覽器功能
// 此屬性優先級低於hot
liveReload: false,
// 是否開啟ZeroConf網絡
bonjour: false,
// 是否將所有404頁面都跳轉到index.html
// boolean | object
// 當此屬性設置為true或為object時並且使用HTML5 API時 所有404頁面會跳轉到index.html
// 使用的connect-history-api-fallback庫 設置為對象,則會將此對象傳參給connect-history-api-fallback庫
historyApiFallback: false,
// 是否使用局域網IP打開頁面
useLocalIp: false,
// 是否監聽node中stdin.end事件, 關閉服務器
stdin: false,
// 終止信號,設置為true時 監聽['SIGINT', 'SIGTERM'];事件,事件觸發后結束進程
// 目前dev-server強制將此屬性設置為true了,所以改為false不管用。
setupExitSignals: true,
// 設置WebSocket
// 可以設置使用的WebSocket庫。內置的庫為sockjs和ws
// 還可以自定義設置WebSocket Server和WebSocket Client
transportMode:{
// 設置使用的WebSocket, 值為 sockjs或者ws
// sockjs 使用的sockjs庫
// ws 使用的ws庫
// webpack-dev-server@4.X使用的是WS webpack-dev-server@3.X 使用的是sockjs
// 目前在webpack-dev-server@4.X使用sockjs會出錯, webpack-dev-server@3.X使用WS也會報錯
server: 'ws'
},
// 自定義中間件鈎子屬性
// 優先於server內部中間件執行
// 相當於webpack-devser@3.X 的before函數
onBeforeSetupMiddleware: (app, server, compiler) =>{
//console.log('我是before', compiler.options)
},
// server內部執行完所有中間件后執行當前中間件
// 相當於webpack-devser@3.X 的after函數
onAfterSetupMiddleware: (app, server, compiler) =>{
},
// dev-server提供的當服務器啟動后執行的鈎子函數
onListening: (server) => {
// const port = server.listeningApp.address().port;
// console.log('Listening on port:', port);
},
},
}
])
-
host:服務器啟動使用的host地址
屬性可設置為:String
默認值:localhost
-
port:服務器啟動使用的端口號
屬性可設置為:Number
默認值:8080
-
open:啟動服務器后是否自動打開瀏覽器,
屬性可設置為:String、Boolean
屬性值為Boolean:是否打開默認瀏覽器
屬性值為String:設置打開指定的瀏覽器,例如:chrome
默認值:false
-
openPage:自動打開瀏覽器時的路由地址。
屬性可設置為:String、Array
屬性值為String:打開指定的地址
屬性值為Array:打開數組中的所有地址。
默認值:index.html
-
compress:是否啟動gzip壓縮數據。
使用的compression中間件進行壓縮。
默認值:false
-
hot:是否啟動熱更新(HMR)。
熱更新(HMR)技術是代碼更新后,瀏覽器只加載需要更新的數據。熱更新(HMR)屬性是必備屬性之一。
熱更新(HMR)真正執行的是webpack中HotModuleReplacementPlugin
默認值:false
-
firewall:是否啟用防火牆
屬性可設置為:Boolean、Array
屬性值為Boolean:是否啟用防火牆,為true,則不允許其它任意主機訪問;為false,則允許其它主機訪問
屬性值為Array:設置可以訪問的IP地址。 相當於 webpack-dev-server@3.X中allowedHosts
默認值:true
🐋 此屬性就是webpack-dev-server@3.X的allowedHosts屬性
-
https:是否使用HTTPS安全連接方式。
屬性可設置為:Boolean、Object
屬性值為Boolean:是否使用HTTPS連接方式
屬性值為Object:設置HTTPS安全證書信息
默認值:false
-
http2:是否使用HTTP/2
當此屬性設置為true時,默認會使用HTTPS安全連接方式。也就是https會設置為true
默認值:false。
-
proxy:服務器代理配置。
前后端分離時,前端請求API需要指定地址,此屬性可以配置IP地址,當訪問指定請求時就請求配置的IP地址。
例如在請求 /api 的接口時會訪問http://localhost:3000。具體可參考官網:devserverproxy。
當然也可以不使用此屬性,直接使用一個靜態字符串或者配置文件。看個人編碼習慣
-
headers:設置服務器Response消息內自定義header信息。
屬性可設置為:Object
默認值:null
-
static:對靜態文件屬性的配置
屬性可設置為:Object、Array
屬性值為Object:配置靜態文件屬性
屬性值為Array:配置多個靜態文件屬性
webpack-dev-server@3.X不具有此屬性。此屬性只是將webpack-dev-server@3.X中關於靜態文件配置的屬性進行匯總封裝
-
directory:設置服務器掛在靜態文件的 本地目錄。
例如設置為 /assets 后, 會加載使用本地 /assets 目錄下的靜態文件到服務器
屬性可設置為:String
默認值:/ package.json文件所在地址。
🐋 此屬性就是webpack-dev-server@3.X的contentBase屬性
-
publicPath:靜態文件掛載到服務器中的虛擬地址,
例如設置為 /static 后, 那么使用靜態文件時必須加入 /static 前綴
屬性可設置為:String
默認值:/
🐋 此屬性就是webpack-dev-server@3.X的contentBasePublicPath屬性
-
staticOptions:服務器掛載靜態文件時使用到的參數
webpack-dev-server掛在靜態文件使用的是 express.static(directory,staticOptions) 中間件,此屬性進行 express.static(directory,staticOptions) 使用的參數,具體請參考express框架
屬性可設置為:Object
-
serveIndex: 是否可以在瀏覽器訪問靜態文件列表。
webpack-dev-server使用的是serve-index庫作為瀏覽器訪問靜態文件功能。
屬性可設置為:Boolean
默認值:true
🐋 此屬性就是webpack-dev-server@3.X的serveIndex屬性
-
watch:是否使用輪詢方式檢查文件變化。
webpack默認使用的是文件系統的變化通知。但是在特殊情況下(例如網絡文件系統)時消息通知會失效
所以可以使用輪詢方式進行檢查文件變化。使用的chokidar來做輪詢檢測
屬性可設置為:Boolean、Object
屬性值為Boolean:是否開啟輪詢檢測
屬性值為Object:配置輪詢參數,例如配置輪詢時間等
默認值:false
🐋 此屬性就是webpack-dev-server@3.X的watchOptions屬性
-
client:WebSocket客戶端屬性的設置。
屬性可設置為:Object
webpack-dev-server@3.X不具有此屬性。此屬性只是將webpack-dev-server@3.X中關於WebSocket客戶端配置屬性的匯總封裝
-
logging:WebSocket客戶端在瀏覽器控制台中輸出日志級別。
屬性可設置為:"none" | "error" | "warn" | "info" | "log" | "verbose"
默認值:info
例如設置為verbose 便會將所有日志輸出在瀏覽器控制台;none則不會輸出任何日志
🐋此屬性就是webpack-dev-server@3.X的clientLogLevel屬性
-
progress:是否將打包進度輸出在瀏覽器控制台中(瀏覽器控制台是否顯示打包進度)
屬性可設置為:Boolean
默認值:false
🐋此屬性就是webpack-dev-server@3.X的progress屬性
-
-
dev:設置webpack-dev-middleware中間件使用的一些配置屬性。
屬性可設置為:Object
webpack-dev-server@3.X不具有此屬性。此屬性只是將webpack-dev-server@3.X中關於webpack-dev-middleware使用屬性的匯總封裝
-
headers:設置服務器Response消息內自定義header信息。
webpack-dev-server@3.X 中devServer.headers在兩個地方使用到了。而webpack-dev-server@4.X進行了拆分,此屬性只負責webpack-dev-middleware中間件。只不過最后結果都一致。
屬性可設置為:Object
-
mimeTypes:設置webpack-dev-middleware mimeTypes屬性,具體請參考webpack-dev-middleware文檔 。
🐋此屬性就是webpack-dev-server@3.X的 mimeTypes屬性
-
writeToDisk:是否將打包編譯文件寫入磁盤
webpack-dev-middleware默認會將打包編譯文件寫入到內存流,以達到更快的訪問速度。
屬性可設置為:Boolean
默認值:false
🐋此屬性就是webpack-dev-server@3.X的writeToDisk屬性
-
publicPath:設置打包編譯文件存放的目錄地址
例如設置為 /public ,那么在訪問打包編譯生成的文件資源時都需要添加 /public 前綴
屬性可設置為:String
默認值:/
🐋🐋 static.publicPath和dev.publicPath屬性設置不一樣, static.publicPath
static.publicPath 代表靜態文件在服務器中存儲的地址,代碼使用靜態文件時需要添加目錄前綴
dev.publicPath 代表將代碼編譯打包的目錄地址,瀏覽器訪問時需要添加目錄前綴
🐋 此屬性就是的publicPath屬性
-
index:根目錄所指向的文件。
此屬性就是能夠在瀏覽器訪問根目錄指向index.html的原因。
屬性可設置為:String
默認值:index.html
🐋 此屬性就是webpack-dev-server@3.X的index屬性
-
stats:設置打包文件時日志輸出級別。
啟動dev-server時會在控制台中看到好多打包信息:文件大小、文件名稱等信息,就是使用此屬性進行控制。
屬性可設置為:“none" | "summary" | "errors-only" | "errors-warnings" | "minimal" | "normal" | "detailed" | "verbose" | boolean | object { … }
默認值:normal
🐋 此屬性就是webpack-dev-server@3.X的stats屬性
-
outputFileSystem:控制打包文件的輸出流。
默認輸出流是內存流,之將文件編譯打包至內存中,此屬性可以更改輸出流。
-
-
-
overlay:打包編譯時出現錯誤/警告時,是否直接顯示在頁面。
此屬性在webpack-dev-server@4.0.0beta.0具有bug。
屬性可設置為:Boolean、Object
屬性值為Boolean:為false時不顯示;為true時,當編譯出現錯誤時,顯示在頁面中
屬性值為Object:自定義配置警告和錯誤狀態。
-
injectClient:是否注入WebSocket
屬性可設置為:Boolean、function (compilerConfig) => boolean
默認值:true
-
injectHot:是否注入熱更新(HMR)。
此屬性是相當於injectClient屬性的一個子集,只控制熱更新(HMR)
屬性可設置為:Boolean、function (compilerConfig) => boolean
默認值:true
🐋🐋 此屬性在webpack-dev-server@4.0.0beta.0源碼中還可以設置only字符串,也就是webpack-dev-server@3.X 中的hotOnly屬性。但是屬性校驗中只允許設置Boolean。
-
liveReload:是否啟動刷新瀏覽器
此屬性開啟后會在在更新代碼數據后重新刷新瀏覽器
但是此屬性優先級低於hot,當開啟熱更新后,會優先使用熱更新。
屬性可設置為:Boolean
默認值:false
-
bonjour:是否開啟Zeroconf網絡
關於Zeroconf,有興趣的朋友可以查看相關文檔
屬性可設置為:boolean
默認值:false
-
historyApiFallback:是否將所有404頁面指向index.html
此屬性使用了connect-history-api-fallback來處理404頁面
屬性可設置為:Boolean、Object
屬性值為Boolean:是否啟用此功能
屬性值為Object:設置connect-history-api-fallback庫的參數
默認值:false
-
useLocalIp:是否使用本地局域網啟用服務器
屬性可設置為:Boolean
默認值:false
-
stdin:是否監聽Node.js中stdin.end事件關閉服務器
屬性可設置為:Boolean
默認值:false
-
setupExitSignals:是否監聽Node.js中的 ['SIGINT', 'SIGTERM'] 事件關閉服務器。
此屬性為webpack-dev-server@4.0.0beta.0新增加,在webpack-dev-server@4.0.0beta.0版本測試,此屬性內置了true屬性,無法更改
-
transportMode:設置WebSocket庫信息。
webpack-dev-server內置了兩個WebSocket庫:ws、sockjs。可以進行使用,並且可以自定義WebSocket Server和WebSocket Client。具體請參考官網
🐋
webpack-dev-server@4.0.0beta.0默認使用:ws
webpack-dev-server@3.X默認使用:sockjs
-
onBeforeSetupMiddleware:自定義鈎子中間件函數,此中間件會優先其它中間件執行。
🐋此屬性就是webpack-dev-server@3.X的before屬性
-
onAfterSetupMiddleware:自定義鈎子中間件函數,此中間件會在所有中間件之后執行。
🐋此屬性就是webpack-dev-server@3.X的after屬性
-
onListening:設置webpack-dev-server服務器啟動后執行的鈎子函數。
-
以上便是webpack-dev-server@4.0.0beta.0中部分配置屬性。
相對於webpack-dev-server@3.X,webpack-dev-server@4.0.0beta.0版本對配置屬性做了更好的整合。
host / port
這兩個屬性是最容易理解並且使用最多屬性之一。
webpack-dev-server內部使用express框架。
webpack-dev-server@4.0.0beta.0庫中 /lib/Server.js 文件就是webpack-dev-server服務器模塊。
/lib/Server.js 具有一個 listen(),listen() 就是啟動服務器函數。

而listen()的調用是在@webpack-cli庫的serve/lib/startDevServer.js。

可以看到在serve/lib/startDevServer.js中使用了options.port和options.host屬性值來啟動服務器。
這兩個屬性就是來自webpack配置中的devServer。
至於默認8080端口號的提供是在findPort()


🐋🐋 源碼是基於webpack-dev-server@4.0.0beta.0。?raw=true
open、 openPath
這兩個屬性在服務器啟動后判斷是否啟動瀏覽器。
Server.listen() 回調函數調用了showStatus()。
隨后調用了 /lib/util/runOpen.js模塊啟動瀏覽器

可以看到,open和openPath屬性都做了類型判斷。
open屬性支持設置字符串打開指定瀏覽器;
openPath可以配置為數組打開多個頁簽。最后使用了open庫來打開瀏覽器
hot、lveReload
在Server.listen() 回調函數中使用 hot屬性做了判斷 ,當設置了hot或liveReload屬性時,就會創建WebSocket· Server 。
也就是只有設置了hot或者liveReload時,才會使用WebSocket 與瀏覽器進行長鏈接

static
static屬性剛才說了,是webpack-dev-server@4.X對關於靜態文件屬性的封裝:訪問路徑、文件監聽等。
在這里只是詳細介紹下部分屬性。
directory、publicPath、staticOptions
這三個屬性是express服務器設置靜態文件使用的屬性。
在Server.setupStaticFeature(),使用了express服務器掛載了靜態文件中間件(express.static)。
將中間件掛載到服務器上的訪問地址是:static.publicPath。
而掛載的本地靜態文件地址是:static.directory。

可以看到,express服務器掛載了其訪問目錄為publicPath。而要掛載本地靜態文件目錄為directory。
靜態文件中間件使用的參數是:static.staticOptions
例如
將static.directory屬性設置為: path.join(config.root, 'assets');static.publicPath屬性設置為:/static
在訪問 /assets/images/yj.png 圖片時就應該使用 /static/images/yj.png



🐋🐋 static.publicPath和static.directory屬性一般不會自定義,如需自定義,需要注意將目錄地址設置好,避免在production找不到
🐋 源碼中static和static.publicPath屬性都是Array。所以配置屬性時可以配置為Array
🐋 在此只是以圖片做一個例子,並不涉及到文件打包。
serveIndex
此屬性是設置能否在瀏覽器中查看靜態文件。webpack-dev-server內部使用的是serve-index庫

如果將static.serverIndex屬性設置為false,那么在瀏覽器中查看靜態文件路徑,會直接是404


如果static.serverIndex屬性為true,那就可以在瀏覽器中查看靜態文件


dev
此屬性是webpack-dev-middleware庫使用的一系列屬性匯總。
index
此屬性是設置根目錄所指向的文件,代碼在webpack-dev-middleware庫中 /dist/utils/getFilenameFromUrl.js 文件

可以看到,在處理static.index屬性時做了類型判斷。
並且其默認值為index.html。
由於html-webpack-plugin庫中的filename屬性默認值也是index.html
也就可以在不做配置情況下默認就可以在根目錄下訪問代碼。
當然也可以更改此屬性。不過在更改代碼時也要將html-webpack-plugin庫的filename屬性進行更改。否則訪問時會404


🐋🐋🐋 約定大於配置,編寫代碼時盡量做到使用統一約定。
stats
此屬性是控制打包日志輸出等級的。在默認情況的執行webpack-dev-server。總是能在控制台輸出好多日志信息。這些日志信息就是由此屬性控制的。

代碼是在webpack-dev-middleware庫中 /dist/utils/setupHook.js 模塊。
代碼中 stats 字段是內部提供的一個狀態對象,根據 statsOptions(dev.stats) 屬性獲取指定的狀態信息。

如果將dev.stats設置為errors-only,控制台就不會有這么多日志,errors-only屬性值代表只有在代碼打包錯誤時才輸出日志。

而如果設置為none,那么連錯誤日志都不會再輸出。.
overlay
此屬性是控制代碼打包編譯時出現警告和錯誤時,是否在頁面上顯示錯誤信息。
此屬性在webpack-dev-server@4.0.0beta.0版本具有bug。
在下面Server.js文件中可以看到使用了clientOverlay屬性,但是在dev對象中並沒有此屬性。
所需在測試時需要改動一下源碼。將clientOverlay改為overlay。

所以在測試時需要改動一下源碼。將clientOverlay改為overlay。

當overlay屬性值為true時,如果代碼出現編譯錯誤,會直接在頁面上顯示錯誤信息。

這個功能個人感覺還挺好用。不過可能有些人更喜歡使用控制台查看錯誤信息,也就是dev.stats屬性。
historyApiFallback
此屬性代表在使用 HTML5 API 時是否將所有 無效路由(404) 都跳轉到指定頁面。
類似於項目中將所有 無效路由(404) 轉到 指定404頁面
webpack-dev-server內部使用的是connect-history-api-fallback中間件來做處理,默認跳轉的頁面是index.html。


總結
🐋🐋🐋
- webpack-dev-server是為了方便開發而提供的一種功能, 利用WebSocket與服務器建立長鏈接。
- webpack@4.X版本對代碼結構進行了大范圍更改,導致與webpack-dev-server@3.X使用
webpack-dev-server
命令會報錯。- webpack-dev-server@4.X版本對devServer屬性根據功能進行了更好的匯總。
本文參考
本文依賴
package.json
{
"name": "my-cli",
"version": "1.0.0",
"main": "index.js",
"author": "mowenjinzhao<yanzhangshuai@126.com>",
"license": "MIT",
"devDependencies": {
"@babel/core": "7.13.1",
"@babel/plugin-transform-runtime": "7.13.7",
"@babel/preset-env": "7.13.5",
"@babel/preset-react": "7.12.13",
"@babel/runtime-corejs3": "7.13.7",
"babel-loader": "8.2.2",
"clean-webpack-plugin": "3.0.0",
"html-webpack-plugin": "5.2.0",
"webpack": "5.24.0",
"webpack-cli": "4.5.0",
"webpack-dev-server": "4.0.0-beta.0",
"webpack-merge": "5.7.3"
},
"dependencies": {
"react": "17.0.1",
"react-dom": "17.0.1"
},
"scripts": {
"start:dev": "webpack-dev-server --config build/webpack.dev.js",
"start": "webpack serve --config build/webpack.dev.js",
"build": "webpack --config build/webpack.pro.js",
},
"browserslist": {
"development": [
"chrome > 75"
],
"production": [
"ie 9"
]
}
}