原因:
通常我們在專案的實現的時候可能會用到第三方的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檔案的內容。
首先我們先試著把jquery跟index.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.js與bundle.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
留言
張貼留言