webpack的學習(4) --------- vendor library 靜態下載與 chunk.

原因:

通常我們在專案的實現的時候可能會用到第三方的library而並非全部都自己撰寫所有的功能,因此這邊會開始把所謂的第三方library(vendor)打包進去。

方向:

這邊我們會先針對直接下載Library的方式來實做(npm install 第三方之後在介紹),並且會在後續使用webpack的chunk功能如何把vendor library切割出來,這次的專案會延續上一個教學的內容繼續實做。

Step1:

我們先下載jQuery 這個前端幾乎最常被使用的library,先到jQuery官方網站下載。
點選右上方的『Download jQuery 』進入下載頁面,接著我們點選『 Download the compressed, production jQuery 3.2.1 』這個縮小過的library。





接著我們回到webpack資料夾下在新開一個叫做vendors的資料夾並且把"jquery-3.2.1.min.js"放到這個資料夾下。其整個架構會如下:

/webpack/
|-----/app/
|        |----- index.js
|
|-----/vendors/
|        |------jquery-3.2.1.min.js
|
|------index.html
|------package.json
|------webpack.config.js


Step2:


接著我們開始編輯webpack.config.js檔案的內容。
首先我們先試著把jqueryindex.js整個打包到bundle.js裡面,所以在entry的設定就改成如下:
const path = require('path')    // nodejs core module

module.exports = {
  entry: {
    app: ["./app/index.js", "./vendors/jquery-3.2.1.min.js"]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  }
}

我們在app那邊用array的方式告知webpack 有這兩個檔案做entry ,output部份我們先不更動接著我們來修改index.js 做確認 jQuery是否真的有被打包並且可以使用。

Step3:

我們開始編輯index.js 主要是加入jQuery的全域變數 '$' 並且把之前在index.html的button透過jQuery的click()功能來讓使用者點擊按鈕時,彈出一個Hello World的警示視窗。
// ES6 feature. 從 jquery import $
import $ from '../vendors/jquery-3.2.1.min';

function componet() {
  var element = document.createElement('div');
  element.innerHTML = '<h2>Hello World</h2>
'
	element.innerHTML += '<button id="myBtn">Test</button>';
	return element;
}

document.body.appendChild(componet());

// 透過jquery 取 button id
let $btn = $('#myBtn');

// 讓button 帶click事件,點擊時彈出'Hello World'
$btn.click(function(evt) {
    alert('Hello World!')
});


接著我們就可以來打包看看了。

Step4:

回到webpack資料夾下命令視窗我們執行上一章教的 "npm run start" 應該會看到打包好的檔案放在dist 內,其實打開bundle.js內收尋 'jquery' 就會看到webpack真的有把jquery包進去。
接著我們用瀏覽器開啟index.html 點擊 Test 按鈕看看有沒有跳出 "Hello World" 警示欄。



這表示jQuery也有正常運作But 其實這種作法有個缺點!!

因為jQuery其實是第三方函式庫我們幾乎不會去修改它,我們開發時會變更的通常是自己撰寫的index.js這個檔案,但是我們把這兩個打包在一起的時候一旦index.js有修改bundle.js內容也會跟著變,然後bundle.js內關於jQuery的部份根本不會變動!但是因為包在一起就會造成使用者的瀏覽器都要重新下載一次bundle.js,所以如果可以把有關第三方函式庫(vendors)的部份切割(chunk)出來自成一份檔案,則使用者只需要下載變更過的index.js打包後的檔案,vendors就可以不用重新下載keep在瀏覽器的cache 裡面。所以接來我們來試著用用看webpack的CommonsChunkPlugin這個 Plugins。

CommonsChunkPlugin:
官方詳細的設定方式可以參考這個連結~commonsChunkPlugin~,這邊我們修改webpack.config.js內容如下:
const path = require('path')    
var webpack = require('webpack')   // *** 1

module.exports = {
	entry: {
    app: ["./app/index.js"],
    vendor: ["./vendors/jquery-3.2.1.min.js"]   // *** 2
  },
	output: {
		path: path.resolve(__dirname, 'dist'),
		filename: 'bundle.js'
	},
  plugins: [                                    // *** 3
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      filename: 'common.js'
    })
  ]

}
var webpack = require('webpack')這個部份是因為現在nodejs的實做讓Javascript可以在server端運作而非以往的在瀏覽器端運行的語言,因為在瀏覽器端運行必須等待client把需要用到的javascript檔案下載完成才可運行的先天限制但是在server端運行就沒有這個問題,一切需要的檔案都在硬碟裡,所以server端開發目前遵行的主流為CommonJS規範與AMD兩種,而在上方看到的require()用法就是屬於CommonJS的規範!那如果是在瀏覽器端實做require()功能的最多人使用的函式庫就是requireJS了,不過其requireJS的用法又跟Server端的不太一樣,有興趣的再請各自研究吧!因為說真的我也只碰過requireJS一點點 XD。
在這邊我們要用到webpack的CommonsChunkPlugin所以把webpack module載入為webpack這個變數物件,然後在下方plugins這個屬性內new 出 CommonsChunkPlugin並對其做設定。

name:

屬性"name"為告知CommonsChunkPlugin要找的chunk名稱~也就是我們在entry那邊給定的vendors,name的內容除了放字串之外也可以改用array放許多要切割出來的chunk名稱。

filename:

屬性"filename"則是切割出來打包後的檔案名稱,這邊我們就給名叫做"common.js"。

其實CommonsChunkPlugin能做的事情還有很多~例如:連index.js打包後的bundle.js也能切割,但是目前我還很菜所以先一步一步慢慢來了。
最後我們也要修改index.html內容了。

Step5:

由於我們把vendor的部份獨立到common.js,所以在index.html也要修改加入common.js的引入。
<html>
  <head>
    <title>webpack 2 demo</title>
  </head>
  <body>
    <script src='dist/common.js'></script>
    <script src='dist/bundle.js'></script>
  </body>
</html>

這邊要注意的是common.js一定要放在bundle.js的上方!因為我們在index.js裡面有使用jQuery的功能,所以jQuery必須比index.js還要早引入否則會出現bundle.js裡面有些程式碼無法執行(小弟的測試是你會在console下看到 Uncaught ReferenceError: webpackJsonp is not defined)。所以這邊要注意!

再來我們先把原本的dist資料夾刪除重新執行 " npm run start "看看有沒有出現錯誤。



接著用瀏覽器開啟index.html 看看Test 按鈕點擊之後是不是有正常運作並且在瀏覽器本身提供的"開發人員工具"(熱鍵: ctrl + shift + i)或是"檢視原始碼"內有看到引入 common.jsbundle.js





另外你也可以把index.html內的common.js引入放到bundle.js後面看看會發生什麼事情 XD
此外我們這邊只有用一個jQuery 的lib,可以試著多找幾個lib 擺到entry的vendors內試試看呦!本章就先到此結束了。
                                        ------------ 待續

Ref:
1. webpack plugin CommonsChunkPlugin.
2. CommonsChunkPlugin
3. Rhadow's Tech Note
4. What Is AMD, CommonJS, and UMD?
5. 和平、奮鬥、救web

留言