1. 寫(xiě)在前面
在之前的博客中,每次使用webpack打包編譯完成之后,我們都需要手動(dòng)打開(kāi)編譯后的index.html文件,這樣對(duì)于前端開(kāi)發(fā)的調(diào)試很不方便。為了解決這一問(wèn)題,webpack給出了 開(kāi)發(fā)服務(wù)器 這一方案。在進(jìn)行開(kāi)發(fā)的過(guò)程中,我們可以使用webpack啟動(dòng)一個(gè)開(kāi)發(fā)服務(wù)器,來(lái)實(shí)時(shí)查看自己的項(xiàng)目,很方便進(jìn)行調(diào)試。
相信很多前端開(kāi)發(fā)者都用過(guò)webpack的開(kāi)發(fā)服務(wù)器,但是有些開(kāi)發(fā)者不是很了解它。那么在這篇文章中,我就給大家介紹webpack的開(kāi)發(fā)服務(wù)器,主要內(nèi)容包括:
- 安裝webpack的開(kāi)發(fā)服務(wù)器
- 初步配置webpack的開(kāi)發(fā)服務(wù)器
- 深入配置webpack的開(kāi)發(fā)服務(wù)器
2. 安裝webpack的開(kāi)發(fā)服務(wù)器
首先執(zhí)行一下命令來(lái)安裝webpack的開(kāi)發(fā)服務(wù)器:
yarn add webpack-dev-server -D
安裝完成之后,我們就可以通過(guò) npx webpack-dev-server 命令啟動(dòng)開(kāi)發(fā)服務(wù)器,或者在 package.json 文件中新建一條腳本,后續(xù)就可以很方便地使用 npm run 或 yarn 來(lái)啟動(dòng)開(kāi)發(fā)服務(wù)器。腳本配置如下:
{
"name": "webpack-learning",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "webpack --config webpack.config.js",
"dev": "webpack-dev-server"
},
"devDependencies": {
"webpack": "^4.32.2",
"webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.5.1"
}
}
啟動(dòng)本地服務(wù)器之后,我們便可以在瀏覽器中通過(guò) http://localhost:8080 來(lái)訪問(wèn)項(xiàng)目了。截圖如下:

3. 初步配置webpack的開(kāi)發(fā)服務(wù)器
現(xiàn)在開(kāi)發(fā)服務(wù)器已經(jīng)啟動(dòng)了,但是顯而易見(jiàn)的是,當(dāng)前的開(kāi)發(fā)服務(wù)器使用的是默認(rèn)配置,很大程度上不能滿足我們開(kāi)發(fā)的需求,比如:
- 開(kāi)發(fā)服務(wù)器不要使用8080端口號(hào),使用其他的端口號(hào)
- 開(kāi)發(fā)服務(wù)器打開(kāi)之后,不是在根目錄下,而是在 build 目錄下
- 開(kāi)發(fā)服務(wù)器啟動(dòng)之后,我希望自動(dòng)打開(kāi)瀏覽器
- ......
下面我們就講解一下,如果初步配置開(kāi)發(fā)服務(wù)器,完成上述需求。之所以說(shuō)是初步配置,是因?yàn)殚_(kāi)發(fā)服務(wù)器配置內(nèi)容較多,后面準(zhǔn)備單獨(dú)寫(xiě)一篇博客,講述開(kāi)發(fā)服務(wù)器的詳細(xì)配置。
其實(shí)初步配置開(kāi)發(fā)服務(wù)器很簡(jiǎn)單,在 webpack.config.json 文件中新增 devServer 屬性,該屬性是一個(gè)對(duì)象,我們將一些配置信息寫(xiě)到該對(duì)象下即可,配置代碼如下:
let path = require("path");
module.exports = {
devServer: {
port: 3000, // 指定開(kāi)發(fā)服務(wù)器的端口號(hào)
progress: true, // 顯示開(kāi)啟本地服務(wù)器的進(jìn)度
contentBase: "./build", // 指定本地服務(wù)器默認(rèn)打開(kāi)的目錄
compress: true // 是否對(duì)代碼進(jìn)行壓縮
},
mode: "development",
entry: "./src/index.js",
output: {
filename: "index.js",
path: path.resolve(__dirname, "build")
}
}
現(xiàn)在再次開(kāi)啟開(kāi)發(fā)服務(wù)器,就可以通過(guò) http://localhost:3000 訪問(wèn)到項(xiàng)目的 build 目錄了,默認(rèn)尋找該目錄下的 index.html 文件進(jìn)行渲染,如果沒(méi)有則展示該目錄下的所有文件。
4. 深入配置webpack的開(kāi)發(fā)服務(wù)器
以上就是對(duì)webpack開(kāi)發(fā)服務(wù)器的安裝和初步配置,但是上述的初步配置存在一些問(wèn)題:我們希望開(kāi)發(fā)服務(wù)器啟動(dòng)之后,就會(huì)顯示我們項(xiàng)目的頁(yè)面,但是上述配置中,如果要看到項(xiàng)目的頁(yè)面,一個(gè)前提是build目錄下必須存在index.html文件。但是這個(gè)文件是打包編譯后才生成的,所以在開(kāi)發(fā)服務(wù)器環(huán)境下可能不會(huì)存在,而且也不會(huì)實(shí)時(shí)刷新,所以很明顯初步配置不能滿足我們的開(kāi)發(fā)需求。
正常情況下,我們希望看到的場(chǎng)景是:使用 npm run 或 yarn 來(lái)啟動(dòng)開(kāi)發(fā)服務(wù)器之后,就可以實(shí)時(shí)看到項(xiàng)目的頁(yè)面,如果項(xiàng)目有代碼的更新,頁(yè)面也要實(shí)時(shí)更新。要做到這一點(diǎn),我們需要完成以下步驟:
1) 安裝 html-webpack-plugin 插件
執(zhí)行 yarn add html-webpack-plugin -D 進(jìn)行安裝該插件
2) 配置 html-webpack-plugin 插件
安裝完成之后,我們就需要到 webpack.config.js 文件中配置該插件,其實(shí)webpack之所以有這么強(qiáng)大的功能,就是依靠各種各樣的插件。所以在webpack配置文件中,肯定會(huì)有各種插件的相關(guān)配置。這里介紹 html-webpack-plugin 插件的配置,其他插件的配置如出一轍。
首先在 webpack.config.js 文件中引入安裝的 html-webpack-plugin 插件,然后新建一個(gè) plugins 屬性,該屬性是一個(gè)數(shù)組,webpack使用到的插件,都要在這個(gè)數(shù)組中進(jìn)行配置。我們先來(lái)看一下具體的配置代碼:
let path = require("path");
let HtmlWebpackPlugin = require("html-webpack-plugin") // 引入安裝的插件
module.exports = {
devServer: {
port: 3000, // 指定開(kāi)發(fā)服務(wù)器的端口號(hào)
progress: true, // 顯示開(kāi)啟本地服務(wù)器的進(jìn)度
contentBase: "./build", // 指定本地服務(wù)器默認(rèn)打開(kāi)的目錄
compress: true // 是否對(duì)代碼進(jìn)行壓縮
},
mode: "development",
entry: "./src/index.js",
output: {
filename: "index.js",
path: path.resolve(__dirname, "build")
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // 模板文件
filename: 'index.html', // 開(kāi)發(fā)服務(wù)器中生成的臨時(shí)文件
minify: {
removeAttributeQuotes: true, // 是否去除文件中的雙引號(hào)
collapseWhitespace: true // 是否去除文件中的空行
},
hash: true // 引入文件的時(shí)候添加哈希值,防止緩存的問(wèn)題
}),
]
}
下面講述一下以上文件中的一些配置選項(xiàng):
- template: 模板文件。webpack開(kāi)發(fā)服務(wù)器啟動(dòng)的時(shí)候,會(huì)將項(xiàng)目的代碼打包編譯成一個(gè)或多個(gè) .js 文件,但是這些文件不能直接在瀏覽器中打開(kāi),需要在一個(gè) **.html **文件中引入,才能正常被瀏覽器渲染。模板文件就是這個(gè) .html 。webpack打包編譯后的 .js 腳本文件會(huì)自動(dòng)地被引入到該模板文件中。
- filename: 開(kāi)發(fā)服務(wù)器中打包編譯后生成的 臨時(shí)文件 的文件名,默認(rèn)是 index.html 。生成的這個(gè)文件是一個(gè)臨時(shí)文件,存放在內(nèi)存中,在項(xiàng)目中是看不到的。但是這個(gè)文件非常重要,當(dāng)我們?cè)跒g覽器中訪問(wèn) http://localhost:3000 ,看到的頁(yè)面,就是這個(gè)文件渲染出來(lái)的。同時(shí)這個(gè)文件也是模板文件和webpack打包后的 .js 文件結(jié)合生成的。
- minify: 表示是否對(duì)打包編譯生成的代碼進(jìn)行處理,比如去除空行、去除雙引號(hào)等。
-
hash:哈希值。如果在模板文件中,直接引入打包編譯后的 .js 文件,那么有的時(shí)候會(huì)受到緩存的影響,但是加上哈希值,就不會(huì)存在這個(gè)問(wèn)題。如果不加hash值,在臨時(shí)文件中引入 .js 文件可能是這個(gè)情況:
<script src="index.js"></script>;如果加上了hash值,在臨時(shí)文件中引入 .js 文件可能是這個(gè)情況:<script src="index.js?fb39b867e8a90e7cc9ec"></script>。有效解決了緩存帶來(lái)的影響。
這里需要說(shuō)明的是, html-webpack-plugin 插件的配置不僅適用于開(kāi)發(fā)服務(wù)器,再進(jìn)行打包編譯的時(shí)候,該插件的相關(guān)配置也會(huì)發(fā)揮作用,比如指定的模板、是否刪除雙引號(hào)、是否刪除空行等。
3) 創(chuàng)建模板文件
在上述敘述中,我們知道在啟動(dòng)開(kāi)發(fā)服務(wù)器的時(shí)候,要有一個(gè)模板文件,所以我們要在項(xiàng)目中創(chuàng)建一個(gè)模板文件。根據(jù)上面的配置要求,該文件是位于 src 文件夾下的 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>Document</title>
</head>
<body>
<h1>這是一個(gè)模板文件</h1>
</body>
</html>
5. 后記
以上就我在學(xué)習(xí)webpack過(guò)程中對(duì)開(kāi)發(fā)服務(wù)器的一些總結(jié)??偟膩?lái)說(shuō),開(kāi)發(fā)服務(wù)器就是對(duì)當(dāng)前項(xiàng)目進(jìn)行打包編譯,將生成的文件存放在內(nèi)存中,然后起一個(gè)本地服務(wù)。我們?cè)跒g覽器中訪問(wèn)這個(gè)本地服務(wù)(如 http://localhost:3000 )來(lái)訪問(wèn)內(nèi)存的 index.html 文件,進(jìn)而看到我們的項(xiàng)目。
而且,這個(gè)過(guò)程是實(shí)時(shí)熱更新的,一旦項(xiàng)目代碼有變化,開(kāi)發(fā)服務(wù)器會(huì)自動(dòng)進(jìn)行打包編譯,這樣我們看到的項(xiàng)目就是最新的。