[前言]:由於最近在vue2.0的時候用到了webpack的externals,才發現我以前都只是用webpack作一些搭建完項目後的「收尾工做」——即打包,而沒有把它歸入到項目開發的「主體過程」中來,真是「物不盡其用」。因而就有了我今天的這篇學習文章:
利用webpack-dev-server搭建一個webpack的服務器
參考資料:
webpack-dev-server的github地址:
https://github.com/webpack/webpack-dev-server
webpack1官方文檔http://webpack.github.io/docs/webpack-dev-server.html(推薦看2的文檔)
webpack2官方文檔https://webpack.js.org/configuration/dev-server/#devserver(推薦讀這個)
提綱:
1.複習webpack的知識
2.詳解webpack-dev-server的配置屬性
3.webpack-dev-server的自動刷新和模塊熱替換機制
4.webpack下配置服務器的三種方式
複習一下webpack的知識
我將目錄結構簡化以後長這樣:
個人webpack.config.js:
var webpack = require('webpack')
var path =require('path')
module.exports = {
entry:{
app:path.join(__dirname,'src','index.js')
},
output:{
filename:'bundle.js',
path:path.join(__dirname,'dist')
}
}
個人src/index.js:html
require('./a.js')
require('./b.js')
console.log('我是index.js')
個人src/a.js:
個人src/b.js:
個人dist/index.html:
/*其餘部分省略*/
<body>
<script src="./bundle.js"></script>
</body>
當咱們在終端運行「webpack」命令後,目錄變爲:
一張圖複習一下webpack的機制:
OK,下面,讓咱們開始搭建一個服務器吧:
怎麼用最簡單的方式搭建一個服務器?
1.你須要一個安裝一個模塊
在終端中進入項目目錄下,敲下npm install webpack-dev-server --save-dev回車
2.在終端運行一段命令:
node_modules/.bin/webpack-dev-server(網上有的說直接輸webpack-dev-server那是錯的)
成功!輸出的是這一段信息:
而後進入默認的localhost:8080頁面:
服務器的根目錄就是咱們工程的目錄
到這裏,咱們要作的第一步就成功啦!
進入dist後,咱們發現報了這樣一段錯誤:
what?沒有找到bundle.js?
因此咱們要在webpack.config.js裏寫一下配置:
module.exports = {
/*這裏省略entry和output,參照上面寫的內容*/
devServer: {
contentBase: path.join(__dirname, "dist")
}
}
保存,後打開頁面看控制檯,報錯已經消失了!正確打印了被打包的文件內容:
詳解webpack-dev-server的配置屬性 vue
1.devServer.contentBase
contentBase是咱們今天要講的第一個webpack-dev-server的配置屬性,那麼,contentBase作了什麼事情呢?——它指定了服務器資源的根目錄,若是不寫入contentBase的值,那麼contentBase默認是項目的目錄。
在上面例子中產生錯誤和後來解決錯誤的緣由:
產生錯誤:由於bundle.js被
"放在了"咱們的項目根目錄裏,在dist/html裏<script src="./bundle.js"></script>此時顯然不能根據路徑找到bundle.js
解決錯誤:經過配置contentBase: path.join(__dirname, "dist")將bundle.js
"放在了"dist目錄下,此時bundle.js和dist/index.html位於同一目錄下,經過 src="./bundle.js"天然就找到bundle.js了
webpack打包和webpack-dev-server開啓服務的區別——
webpack輸出真實的文件,而webpack-dev-server輸出的文件只存在於內存中,不輸出真實的文件!(注意下面兩張圖的區別)
webpack:當咱們在終端運行"webpack"後:
webpack-dev-server:當咱們在終端運行"node_modules/.bin/webpack-dev-server後:
這也就是我在上面的闡述中將bundle.js"放在了"加上雙引號的緣由
2.devServer.port
port配置屬性指定了開啓服務的端口號:
設置端口號爲7000:
運行:node_modules/.bin/webpack-dev-server
這個時候就不是默認的8080的端口了,而是咱們設置的7000
3.devServer.host
host設置的是服務器的主機號:
修改配置爲:
devServer: {
contentBase: path.join(__dirname, "dist"),
port:7000,
host:'0.0.0.0'
}
此時localhost:7000和0.0.0.0:7000都能訪問成功
4.devServer.historyApiFallback
在文檔裏面說的很清楚,
這個配置屬性是用來應對返回404頁面時定向到特定頁面用的(the index.html page will likely have to be served in place of any 404 responses)
在dist目錄下新增一個HTML頁面:
/*剩下的都是很常規的HTML內容,故省略*/
<p>這裏是404界面</p>
咱們把webpack.config.js修改以下:
module.exports = {
/*這裏省略entry和output,參照上面寫的內容*/
devServer: {
contentBase: path.join(__dirname, "dist"),
historyApiFallback:{
rewrites:[
{from:/./,to:'/404.html'}
]
}
}
}
打開頁面,輸入一個不存在的路由地址:
5.devServer.overlay
這個配置屬性用來在編譯出錯的時候,在瀏覽器頁面上顯示錯誤,默認是false,可設置爲true
首先咱們人爲製造一個編譯錯誤:在咱們還沒有配置babel loader的項目裏使用ES6寫法:
在src/index.js裏寫入「const a」
在shell裏提示編譯錯誤:
但在瀏覽器裏沒有提示:
因此咱們把webpack.config.js修改成:
module.exports = {
/*這裏省略entry和output,參照上面寫的內容*/
devServer: {
contentBase: path.join(__dirname, "dist"),
overlay: true
}
}
再從新運行node_modules/.bin/webpack-dev-server,瀏覽器上把錯誤顯示出來了
6.devServer.stats(字符串)
這個配置屬性用來控制編譯的時候shell上的輸出內容,咱們沒有設置devServer.stats時候編譯輸出是這樣子的:
(其中看起來有許多看似不重要的文件也被打印出來了)
stats: "errors-only"表示只打印錯誤:
咱們把配置改爲:
devServer: {
contentBase: path.join(__dirname, "dist"),
stats: "errors-only"
}
由於只有錯誤才被打印,因此,大多數信息都略過了
除此以外還有"minimal","normal","verbose",這裏很少加贅述
7.devServer.quiet
當這個配置屬性和devServer.stats屬於同一類型的配置屬性
當它被設置爲true的時候,控制檯只輸出第一次編譯的信息,
當你保存後再次編譯的時候不會輸出任何內容,包括錯誤和警告
來作個對比吧:
quiet:false(默認):
第一次編譯:
第二次編譯(當你保存的時候)
quiet:truenode
第一次編譯同上
第二次編譯什麼都不輸出
【吐槽】這樣看的話感受這個配置好像只有負面做用呢.....
8.devServer.compress
這是一個布爾型的值,當它被設置爲true的時候對全部的服務器資源採用gzip壓縮
採用gzip壓縮的優勢和缺點:
優勢:對JS,CSS資源的壓縮率很高,能夠極大得提升文件傳輸的速率,從而提高web性能
缺點:服務端要對文件進行壓縮,而客戶端要進行解壓,增長了兩邊的負載
9.devServer.hot和devServer.inline
在這以前,首先要說一下的是webpack-dev-server的自動刷新和模塊熱替換機制
webpack-dev-server的自動刷新和模塊熱替換機制
這兩個機制是牢牢聯繫在一塊兒的
從外部角度看——自動刷新
當咱們對業務代碼作了一些修改而後保存後(command+s),頁面會自動刷新,咱們所作的修改會直接同步到頁面上,而不須要咱們刷新頁面,或從新開啓服務
(The webpack-dev-server supports multiple modes to automatically refresh the page)
從內部角度看——模塊熱替換
在熱替換(HMR)機制裏,不是重載整個頁面,HMR程序會只加載被更新的那一部分模塊,而後將其注入到運行中的APP中
(In Hot Module Replacement, the bundle is notified that a change happened. Rather than a full page reload, a Hot Module Replacement runtime could then load the updated modules and inject them into a running app.)
webpack-dev-server有兩種模式能夠實現自動刷新和模塊熱替換機制
1. Iframe mode
(默認,無需配置)
頁面被嵌入在一個iframe裏面,而且在模塊變化的時候重載頁面
2.inline mode(需配置)添加到bundle.js中
當刷新頁面的時候,一個小型的客戶端被添加到webpack.config.js的入口文件中
例如在咱們的例子中,在使用inline mode的熱替換後,至關於入口文件從
entry:{
app:path.join(__dirname,'src','index.js')
}
變成了:
entry:{
app:[path.join(__dirname,'src','index.js'),
'webpack-dev-server/client?http://localhost:8080/'
]
}
從一個入口變成了兩個入口,並實現刷新
那怎麼才能inline mode模式的刷新呢?
你須要作這些:
1在配置中寫入devServer.hot:true和devServer.inline:true
2增長一個插件配置webpack.HotModuleReplacementPlugin()
例如:
var webpack = require('webpack')
module.exports = {
/*省略entry ,output等內容*/
plugins:[
new webpack.HotModuleReplacementPlugin()
],
devServer: {
inline:true,
hot:true
}
}
打開頁面:
若是有上面兩行輸出則代表你已經配置成功
如今還有一個問題,那就是每次直接輸入node_modules/.bin/webpack-dev-server來啓動服務器對咱們來講簡直就是莫大的痛苦,那麼怎麼對這一過程進行簡化呢?
答案:把這個運行腳本寫到package.json裏就好了!
這裏我把個人package.json寫成:
{
"name": "webpackTest2",
"dependencies": {},
"devDependencies": {},
"scripts": {
"start": "node_modules/.bin/webpack-dev-server"
}
}
在終端運行npm start:
運行成功!
配置服務的三種方式:
1在webpack.config.js輸出對象中的devServer屬性中寫配置(也就是咱們上述全部例子的作法)
2寫在package.json中,寫在node 命令對應的腳本中,例如咱們能夠寫成:
"scripts": {
"start": "node_modules/.bin/webpack-dev-server --port 8000 --inline true "
}
(但這顯然並非一個值得推薦的方式)
3使用純node的API實現,下面是一個官方給的例子
var config = require("./webpack.config.js");
config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/");
var compiler = webpack(config);
var server = new WebpackDevServer(compiler, {
/*咱們寫入配置的地方*/
});
server.listen(8080);