Hello,大家好。
在之前兩篇文章中:
webpack練手項目之easySlide(一):初探webpack
webpack練手項目之easySlide(二):代碼分割
與大家分享了webpack的基本使用方法,以及使用webpack對代碼進行分割,根據需求進行異步加載。
今天我們繼續為大家介紹webpack的其他應用方法,主要包括common chunks以及web-dev-server。
1.Demo與Code
在實際的項目開發過程中,我們的項目中會有很多公共的部分,比如一些第三方的元件,CSS樣式等。通過添加一些配置,webpack在打包過程中自動的提取出這些公共元素,并将其打包到一個獨立的檔案中。在頁面上我們隻需要引入這個公共的腳本以及頁面單獨的腳本即可。
如果大家注意的話,在上一章中我們使用的Demo就已經使用了common chunks:
Demo:http://xiaoyunchen.github.io/easySlide/
Code:https://github.com/xiaoyunchen/easySlide
為了示範效果,我們新增了一個頁面入口,叫做jsEvent.html,現實的功能也就是之前在 http://www.cnblogs.com/souvenir/p/4988367.html 已經實作的功能,示範JS事件流的傳播。隻是這次稍微将代碼改成子產品化的形式。
OK。同一個項目下有兩個頁面(實際項目中會更多入口或者頁面),這兩個頁面都需要引用一些公共的元件,比如頭部導航菜單,footer腳部資訊等,這些元件一般都是全站通用的,然後每個頁面進行單獨調用即可。
我們在項目下增加了一個jsEvent的子產品,引入了jsEvent的頁面和調用JS:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmLwcDMwcjNzITOtAzM1UTMwMDNxIDMyETNxAjMtYDOxYDM28CXyETNxAjMvwlN4EjNwYzLcd2bsJ2Lc12bj5ycn9Gbi52YuUTMwIzcldWYtl2Lc9CX6MHc0RHaiojIsJye.jpg)
關于jsEvent子產品的實作我們稍後再看,先來看看jsEvent入口JS檔案的内容:
1 (function(){
2 //引入公共CSS與頁面CSS
3 require('../../css/vendor/reset.css');
4 require('../../css/page/jsEvent.css');
5 require('../../css/module/footer.css');
6
7 //引入header
8 require("../module/header.js");
9
10 //引入jsEvent子產品
11 var Delegate=require("../module/jsEvent.js");
12 var delegate=new Delegate();
13 delegate.addBodyListener();
14 delegate.addListElement($('#list1'),$('#btn1'));
15 delegate.addListElement($('#list2'),$('#btn2'));
16
17 })();
同樣的,前三行代碼我們先引入了公共CSS和本頁面所需的CSS。
第8行:引入了header子產品。因為header子產品除了樣式以外隻有一個頁面滾動式固定的功能,是以這裡也需要調用其任何方法,隻需引入該子產品即可。
第11-15行:引入jsEvent子產品,并配置相關事件監聽。關于jsEvent這個子產品的實作大家可以檢視之前的文章或者源碼,這裡不再作贅述。
同樣的大家可以再來回顧一下Index.js的源碼:
是的,前面引入公共CSS以及引入header部分是完全一緻的,這也就是我們所說的common chunks公共部分。
接下來我們再來看webpack.config.js中的配置内容:
在配置檔案中先定義了這兩個入口檔案:Index與delegate,然後這裡新引入了一個新的插件:CommonsChunkPlugin (官方文檔)
new webpack.optimize.CommonsChunkPlugin("commons.js", ["index", "delegate"])
通過這句代碼我們将Index與delegate中的公共部分提取出來并放置在commons.js這個單獨的檔案中,是以我們在頁面中除了需要引入index/jsevent以外,還需要引入這個commons。
再來看看CommonsChunkPlugin 的其他配置選項:
minChunks :公共子產品被使用的最小次數。比如配置為3,也就是同一個子產品隻有被3個以外的頁面同時引用時才會被提取出來作為common chunks。
minSize:作用類似于minChunks,隻不過這裡控制的檔案大小。
children:這個參數比較有意思,他可以将common chunks不單獨存放,而是将其加入到所引用的頁面JS中進行合并。關于這個參數我也定義了一個webpack.config2.js以及index2.html用于測試,大家使用 webpack --config webpack.config2.js 就能單獨打一次包,然後發現這次并沒有生成commons.js,因為已經被加入到index.js中,是以在index2.html我們隻需要引入bundle.js即可。(咦,怎麼感覺又回去了呢)
2.header元件
這是一個單獨的元件,功能比較簡單,作為頁面的一個導航,同時在頁面滾動的時候固定在最頂部。
我們來看看具體的實作代碼:
1 (function(){
2 require('../../css/module/header.css');
3
4 var headerModule={
5 config:{ //配置資訊,頭部class/多少高度觸發fixed,fixed class名
6 headerDom:$('.headerWrapper'),
7 fixedTop:80,
8 fixedCls:'header-fixed'
9 },
10 headerFixed:function(){ //切換class
11 if ($(window).scrollTop()>headerModule.config.fixedTop){
12 headerModule.config.headerDom.addClass(headerModule.config.fixedCls);
13 }else{
14 headerModule.config.headerDom.removeClass(headerModule.config.fixedCls);
15 }
16 },
17 init:function(){ //為window綁定scroll事件
18 $(window).bind('scroll',function(){
19 headerModule.headerFixed();
20 });
21 }
22 };
23 headerModule.init();
24 module.exports=null;
25 })();
第2行,不多說,引入header子產品所需要的css樣式。
第4行,定義了header元件的實作變量;
第5行,定義了一些配置資訊,具體資訊大家看注釋。
第10行,headerFixed:判斷目前滾動的高度是否大于咱們的配置,如果是的話就添加一個class。
第17行,init行數:初始化函數,為window綁定了這個scroll滾動事件。
第23-24行,主動調用了init行數,是以這裡我們的exports為null,沒有任何需要導出的内容。
這裡需要一下兩個問題:
1.關于header的html模闆,這裡沒有加載器來做異步加載,而是直接寫在每個頁面中的,其實有些增加了維護工作量。實際項目的做法應該是将這個header.html的模闆檔案獨立出來,然後通過後端的文法(比如PHP或者Java)來進行引入。這個工作如果由前端來完成的話,需要單獨一個HTTP請求同時需要重新渲染DOM,比較消耗浏覽器的性能,是以不推薦。
2.關于header子產品的配置資訊。根據一般元件的做法,這個參數應該是需要是暴露接口,讓調用者可以修改的,但是我們考略到header的特殊性,作為全站的導航菜單,一般都是樣式與功能統一的,是以這裡并沒有開放修改接口。
好的,我們來看下最後的頁面效果:
當我們滾動向下滾動頁面後,header上增加了一個class,将header固定在了頁面頂部。
3.web-dev-server
這裡再單獨介紹一個webpack的小功能:web-dev-server.
這個功能的作用在于每次修改儲存後,webpack将會自動重新對資源進行打包,并且自動重新整理頁面。(使用的是socket.io進行通信)
首先通過npm安裝web-dev-server
npm install web-dev-server --save--dev
安裝完成後再通過 web-dev-server 即可啟動server,啟動成功後指令行會出現如下的提示:
webpack:bundle is now VALID.
然後我們隻需要通路 http://localhost:8080/ 就可以通路到我們的項目頁面。
可以嘗試修改一下任何一個資源檔案,然後會發現控制台上webpack重新進行了編譯,而且浏覽器也自動進行了重新整理,無需我們手動幹預。(雙屏開發的同學可以開始鼓掌了...)
小結:
截止到這裡為止,我們對webpack的學習就暫時告一個段落。
webpack是一款非常優秀的前端子產品化打包工具,他還有很多實用的功能,因為目前我的項目中還沒有涉及到,是以還沒來得及做深入研究。比如對react/angularjs這樣的前端架構,LESS/JADE等這些模闆或者css工具的編譯與支援,同時還相容了AMD/CommonJS/ES6文法,功能十分強大,值得我們好好研究。