利用webpack實現js/css模塊化開發

什麼是模塊化開發?

對前端工程化的參考資料:https://github.com/fouber/blo...
前端的工程化構建開發不只僅停留在‘壓縮’、‘校驗’、‘合併’,模塊化構建可使項目的擴展性、代碼的複用性和可維護性大大提升。在解決基本的開發效率和運行效率以後,前端團隊要思考維護效率。模塊化是當前前端最流行的開發手段。
模塊化是一種處理複雜系統分解爲更好的管理模塊的方式。它能夠經過不一樣的組件設定不一樣的功能,把一個問題分解成多個小的獨立的、相互做用的組件。感受就像是在拼圖。
模塊化的好處:
提升代碼的重用率
提升開發效率、減小溝通成本
下降耦合
更好實現代碼的快速迭代
便於代碼的維護javascript

一、css模塊化

css模塊化開發基本都是在less、sass、stylus等預處理器的import/mixin特性支持下實現的。css

二、js模塊化

js模塊化方案有AMD/CommonJS/ES6 Module等
使用webpack模塊的各類方式的依賴關係:
一、ES2015 import語句
二、CommonJS require()語句
三、AMD define 和 require語句
四、css/sass/less文件的 @import 語句
五、樣式 (url(...)) 或 HTML文件(<img src=...>) 中的圖片連接(image url)
webpack的優點
一、支持CommonJS 和 AMD 模塊。
二、支持模塊加載器和插件機制,可對模塊靈活定製。babel-loader支持ES6
三、能夠經過配置,打包成多個文件。有效的利用瀏覽器的緩存。
四、將樣式文件和圖片等靜態資源視爲模塊進行打包。配合loader加載器,對資源進行處理。前端

下面介紹javascript模塊化編程:

1、原始寫法
模塊是實現特定功能的一組方法。java

function m1(){
    //''''
}

function m2(){
    //''''
}

上面的函數m1()和m2(),組成一個模塊。使用的時候,直接調用就ok了。
這種作法的缺點就是污染了全局變量,沒法保證不與其餘模塊發生變量名衝突,並且模塊成員之間看不出直接聯繫。
2、對象的寫法
將模塊寫成一個對象,全部的模塊成員都在這個對象裏。node

var module = new Object({
        _count : 0,
        m1: function(){
            console.log(this._count)
        },
        m2:function(){
            console.log(this)
        }
    })
    module.m1()
    module._count = 5
    module.m2()

上面的函數m1()和m2(),都封裝在module對象裏。使用的時候直接調用這個對象的屬性。jquery

module.m1();
輸出:0

可是這樣的寫法會暴露全部的模塊成員,內部狀態會被外部狀態改寫,好比:webpack

module._count = 5
module.m1()
輸出:5

3、當即執行函數
使用當即執行函數能夠達到不暴露私有成員的目的。git

var module_1 = (function(){
        var _count = 1;
        var m1 = function(){
            console.log(_count)
        };
        var m2 = function(){
            console.log(this)
        };
        return {
            m1:m1,
            m2:m2
        }
    })();
    module_1.m1()
    module_1.m2()

使用上面的寫法,外部代碼沒法讀取內部的_count變量。github

介紹如何規範的使用模塊

JavaScript模塊規範共有兩種:CommonJS 和 AMD。
爲何要有模塊?
有了模塊,咱們就能夠方便的使用別人的代碼,想要什麼功能,就加載什麼模塊。
1、CommonJS
用於服務端模塊化編程:
一個文件就是一個模塊,require方法用來加載模塊,該方法讀取一個文件並執行,最後返回文件內部的module.exports對象;
require是默認讀取 .js 文件,因此require(模塊名)能夠不寫後綴;
同步加載,因爲服務端加載的模塊通常在本地,因此能夠這樣;可是客戶端若是一個模塊過大就會致使頁面「假死」;

node.js的項目,將JavaScript語言用於服務器編程,在瀏覽器環境下,沒有模塊也是能夠的。但在服務器端,必定要有模塊,與操做系統和其餘應用程序互動,否側就無法編程。
node.js的模塊系統,就是參考CommonJS規範實現的。在CommonJS中,有一個全局性的方法require(),用於加載模塊。假定有一個數學math.js,就能夠像下面這樣加載。web

var math = require('math');

而後,就能夠調用模塊提供的方法;

var math = require('math');
math.add(2,3); //5

module.exports屬性表示當前模塊對外輸出的接口,其餘模塊文件加載該模塊,實際上就是讀取module.exports變量;爲了方便用exports,exports指向module.exports;即exports = module.exports = {};
exports.xxx至關於在導出的對象上添加屬性,該屬性對調用模塊可見;
exports = 至關於給exports從新賦值,這樣就切斷了和module.exports的關聯,調用模塊就不能訪問exports的對象及其屬性。
在瀏覽器環境:
CommonJS不使用於瀏覽器環境。若是在瀏覽器中運行,會有一個大問題;

var math = require('math');
math.add(2,3)

在第二行math.add(2,3),在第一行require('math')以後運行,所以必須等math.js加載完畢。若是加載時間很長,整個應用就會停在這裏。
這對服務器不是問題,由於全部的模塊都存在本地硬盤,能夠同步加載完成,等待時間就是硬盤的讀取時間。可是,在瀏覽器,由於模塊都在服務器端,等待時間取決於網速的快慢,可能要等很長時間,瀏覽器處於「假死」狀態。
所以,瀏覽器端的模塊,不能採用「同步加載」,只能採用「異步加載」。這就是AMD的產生的背景。

2、AMD
AMD是「Asynchronous Module Definition」的縮寫,意思是「異步模塊定義」。它採用異步方式加載模塊,模塊的加載不影響它後面的語句的運行。全部依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成以後,這個回到函數纔會運行。
AMD也採用require()語句加載模塊,可是不一樣於CommonJS,它要求兩個參數,

require([module],callback);

第一個參數[module],是一個數組,裏面的成員就是要加載的模塊,第二個參數callback,則是加載成功以後的回調函數。若是將前面的代碼改寫成AMD形式,就是下面的形式:

require(['math'],function(math){
    math.add(2,3);
})

math.add()與math模塊加載不是同步的,瀏覽器不會發生‘假死’。因此AMD比較適合瀏覽器環境。

3、require.js的用法:
require.js(前端模塊化管理的工具庫)實現js文件的異步加載,避免網頁失去響應;管理模塊之間的依賴性,便於代碼的編寫和維護。
主模塊的寫法:
main.js稱爲是「主模塊」,意思是整個網頁的入口代碼。全部的代碼都從這開始運行。主模塊依賴於其餘模塊,這時就使用AMD規範定義的require()函數。

//main.js
require(['moduleA','moduleB','moduleC'],function(moduleA, moduleB, moduleC){
//some  code here
});
require()函數接受兩個參數。第一個參數是一個數組,表示所依賴的模塊,
上例就是['moduleA','moduleB','moduleC'],即主模塊依賴這三個模塊;
第二個參數是一個回調函數,當前面指定的模塊都加載成功後,它將被調用。
加載的模塊會以參數形式傳入該函數,從而在回調函數內部就可使用這些模塊。
require()異步加載moduleA,moduleB和moduleC,瀏覽器不會失去響應;它指定的回調函數,只有前面的模塊都加載成功後,纔會運行,解決了依賴的問題。

假定主模塊依賴jquery、underscore和backbone三個模塊,main.js就能夠這樣寫:

require(['jquery','underscore','backbone'],function($,_,Backbone){

//some code here
})
requery.js是先加載jQuery、underscore和backbone,而後在運行回調函數。主模塊的代碼就寫在回調函數中。

4、模塊的加載
主模塊的依賴模塊是['jquery','underscore','backbone']。默認狀況下,require.js假定這三個模塊於main.js在同一個目錄,文件名分別是jquery.js、
underscore和backbone.js,而後自動加載。
使用require.config()方法,咱們能夠對模塊的加載行爲進行自定義。
require.config()就寫在主模塊(main.js)的頭部。參數就是一個對象,
這個對象的paths屬性指定各個模塊的加載路徑。

require.config({
    paths:{
        "jquery":"jquery.min",
        "underscore":"underscore.min",
        "backbone":"backbone.min"
    }
});
上面的代碼路徑默認與main.js在同一個目錄(js子目錄)。若是這些模塊在
其餘目錄,好比js/lib目錄,則有兩種寫法:
一種是逐一指定路徑。
require.config({
    paths:{
        "jquery":"lib/jquery.min",
        "underscore":"lib/underscore.min",
        "backbone":"lib/backbone.min"
    }
});
另外一種則是直接改變基目錄(baseUrl)
require.config({
    baseUrl:"js/lib",
    paths:{
        "jquery":"jquery.min",
        "underscore":"underscore.min",
        "backbone":"backbone.min"
    }
});
若是某個模塊在另外一臺主機上,也能夠直接指定它的網址,好比,
    require.config({
        path:{
            "jquery":
            "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
        }
    })
requiry.js要求,每個模塊是一個單獨的js文件。這樣的話,若是加載多個
模塊,就會發出屢次HTTP請求,會影響網頁的加載速度。所以,require.js提供一個優化工具,
當模塊部署完畢之後,能夠用這個工具將多個模塊合併在一個文件中,減小http請求。
相關文章
相關標籤/搜索