webpack的學習(6) ------- webpack-dev-server的使用。

Why:

在之前的範例中,每次修改了專案的內容(html or javascript)就是重新打包一次然後會到瀏覽器再重新載入一次是不是讓人覺得很浪費時間在移動滑鼠上面啊? XD
我想很多人都一定會有這種開發上討厭的情況,當然webpack也有發現到這點因此有個webpack-dev-server的功能套件可以使用,讓你可以在編寫code後按下ctrl + s 存檔後馬上更新你的網頁、馬上看到修改後的效果,這個套件就叫做 " webpack-dev-server"。接下來我們就來簡單的介紹與使用這個套件吧!

Step1 安裝 webpack-dev-server:

第一件事當然是安裝webpack-dev-server啦!我們在webpack資料夾下使用 npm 安裝webpack-dev-server但是這次我們在參數上改成 --save-dev 而非之前jQuery的 --save
兩者的不同是 --save-dev是告訴npm 『這只是開發用的套件』並不是在真正成品上會用到的套件!也就是說這個只是開發用,最後的成品沒有 webpack-dev-server這個套件不會影響其功能的。

~/webpack/ $  npm   install  --save-dev  webpack-dev-server

安裝完後我們可以開啟"package.json"來看看是不是多了一個叫做"devDependencies"的屬性,並且內容寫著"webpack-dev-server": "^2.4.5"  呢!

這個devDependencies與我們之前裝jQuery的 dependencies的意義上是不一樣的!也就是說在真正的完成品上 dependencies列出的套件是一定要有的,否則我們的專案是不會運作或是會有功能上的缺失。然後devDependencies則是說:在開發上會用的軟體、套件,但是不會影響到最後真正的成品。 就像我們用webpack-dev-server只是方便我們開發,但在最後成品上沒有webpack-dev-server本來就不會影響到程式的運作與功能,webpack本身也是!因為它只是我們用來打包的工具,最後我們只是把webpack打包好的 html, js 跟一些static 檔案放在server上面透過web server (如:apache , nginx)運行就可以執行了!根本用不到webpack。

再來是webpack-dev-server後方的版本資訊前面有的 "^"的符號!這個代表之後如果我們把這個整個專案搬到其他電腦上時,由於那台電腦一般預設沒有安裝 webpack, jquery, webpack-dev-server 所以當我們下npm install 的時候,npm 會參考package.jsondependenciesdevDependecies的清單去安裝我們需要的套件版本,而後面的"^2.4.5"則是告知當npm 上面的webpack-dev-server時,要安裝那一版本的webpack-dev-server?  "^" 的意思就是 可以安裝 大於( > 2.4.5)但是不要安裝3.0以上的(< 3.0)。

npm 對於版本的安裝還有很多符號的使用與限制方式,如果有興趣可以參考這邊的資訊。
npm semver

Webpack-dev-server:

這邊我們先簡單介紹webpack 本身提供一個即時打包、編譯的功能,也就是在webpack的命令後面多加一個 " --watch" 的參數,webpack本身也能作到馬上存檔、馬上打包的動作!但是缺點就是因為即時打包、編譯然後檔案在寫回硬碟所以在效率上就比較慢!然而webpack-dev-server的作法則是把打包與編譯的後的檔案都放在記憶體而不是真的去『打包、編譯』,速度上當然快上許多也是會有這麼多人使用的原因啦!

在設定webpack-dev-server上有兩種方式:1. 使用webpack.config.js來設定。2. 用下指令的方式來設定。這兩種都會簡單介紹一下。


1. 使用webpack.config.js來設定:

首先我們開啟webpack.config.js檔案來做設定。在module.export內加入有關dev-server的設定如下:
module.exports = {
  devServer: {                // dev-server 的設定
    contentBase: path.join(__dirname, '/'),      // 1
    compress: true,                              // 2
    port: 9000,                                  // 3
    inline: true                                 // 4
  },
  entry: {
    app: ["./app/index.js"],
    vendor: ["jquery"]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: 'dist',             // 多了 publicPath
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      filename: 'common.js'
    })
  ]
}

這邊devServer就是設定dev-Server的內容:

  1. contentBase: 就是跟dev-Server講啟動之後當作根目錄的位置在哪邊!這會影響到你html中載入靜態檔案的設定相對路徑。舉例來說:我們在index.html放在專案目錄的第一層(mywebpack/index.html)所以載入boundle.js時是src="dist/boundle.js" ,假設我們如果把contentBase設成 path.join(__dirname, 'dist') 那除了啟動之後讀不到index.html外(除非把index.html搬到dist下),原本boundle.js的載入還需要改成 src="boundle.js"~~因為現在跟目錄變成dist了。
  2. compress: true 這邊就是跟dev-Server說提供壓縮的功能(gzip)。在真實web server中有一種方式就是把網頁的所有檔案壓縮成.gzip檔案,因為壓縮後體積變小所以client在下載網頁內容的時候就可以降低頻寬的使用量(傳輸變快了),然後在透過browser將gzip解壓縮後呈現(需要更多browser的資源)。
  3. port: 9000 就邊就是在我們啟動dev-server之後在local會用port 9000這個來開啟網頁。
  4. inline: true 由於dev-server再做即時修改後的畫面呈現是透過兩種方式:
    a. inline mode, b.iframe mode
    inline的方式是當成網頁來做即時修改的畫面呈現。
    iframe則是用一個網頁在網頁內使用frame 這個html 的tag將我們撰寫的網頁塞入這個iframe來做即時修改程式碼的畫面呈現。
    由於我都用inline所以frame的用法我就真的沒用過因此這邊就不介紹了,有興趣的朋友再去官網參考有關frame的使用方式。
    兩者的結果都是相同的~呈現即時的網頁畫面
這邊在output這邊多了publicPath: "/"設定。主要在載入外部資源時的路徑設定,在這邊dev-server會去參考這個設定決定我們網頁在讀取一些外部資源(如:CDN、圖片、js檔...等)的位置。在我們的index.html內我們把common.js與boundle.js src路徑都指定在dist內,也就是index.html會去dist這個資料夾內拿取common.jsboundle.js,我們透過dev-server模擬處在一個真實的網頁server做即時編輯即時顯示的開發的時候也會依照我們index.html內去找到那些需要用到的資源。但是由於dev-server並不是真的打包所以會去參考publicPath的內容而非output.path(畢竟就沒打包)去哪邊找那些資源。

舉個例子:
我們output.path 設定在dist 所以webpack真的打包的時候,會把東西打包放到dist內。所以真正index.html內的common.js與boundle.js會放在dist,src="dist/common.js" src="dist/boundle.js"。

此時如果我們把publicPath設成 "assets"的時候,使用dev-server在開發時,dev-server會認為common.js與boundle.js放在assets內,所以開發的時候就必須把index.html內的common.js與boundle.js改成 src="assets/common.js"與src="assets/boundle.js"。問題是如果當我們真的開發完畢做真正打包的時候(output.path的設定是dist)又要把index.html內的common.js與boundle.js的設定改回dist,這不是很自找麻煩嗎?因此在這邊我們把publicPath也設在dist這樣子不論打包或是開發的時候,都不用去修改index.html。

package.json設定:
由於我們現在要用dev-server來執行,為了方便起見我們一樣在package.json的script內加入啟用dev-server的命令方便我們用npm run來執行。

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",           // 不要忘了逗號
    "dev": "webpack-dev-server"   // 新增這行方便使用dev-server
  },
所以我們就可以在命令列直接下$npm  run dev 來執行dev-server

上面就是執行 npm run dev的正常啟動樣子。接下來我們開啟瀏覽器,網址填 localhost:9000 就可以看到畫面:


點擊Test按鈕一樣會出現 "Hello World",現在我們修改index.js把alert("Hello World") 改成alert("Dev Server")然後存檔,接著再回到瀏覽器點擊Test按鈕就會發現警示視窗內容馬上變成"Dev Server"了



看看這神奇又方便開發的dev-server有多麼好用!!


2. 使用命令列的方式:

這邊要先說明一下並不是所有的設定都可以透過命令列的方式來設定!
很多設定可以參考webpack-dev-server的 help 內容觀看。

$./node_modules/.bin/webpack-dev-server --help


這邊我們先把webpack.config.js內關於devServer的那段註解掉,然後在命令列下:

$ ./node_modules/.bin/webpack-dev-server --compress --port=9000 \
--content-base="/home/cloverhsc/mywebpack"  --inline

這邊要注意 --content-base 要下絕對路徑,不同於 webpack.config.js 是使用相對路徑。


一樣可以透過修改index.js來看看網頁有沒有馬上跟著變!
                                       ----- 待續


Ref:
1. webpack學習(三)—— webpack-dev-server
2. 使用 Webpack 建立 React 專案開發環境
3. Webpack - DevServer
4. Npm semver

留言