現在模塊化的 JavaScript 的開發愈來愈火熱,不管是模塊加載器仍是優秀的 JavaScript 模塊,都是層出不窮。既然這麼火,確定是有存在的理由,確定是解決了某些實際問題。不少沒接觸過模塊化 JavaScript 開發者不由要問,我真的須要模塊化嗎,模塊化相比於傳統的模式有什麼優點?
JavaScript 自己是沒有模塊化支持的,不少語言多有,就連CSS都有這樣的加載方式。
@import "fed.css";
雖然由於性能問題不推薦CSS這樣來進行加載,但這是一種模塊化的思想,這種思想對於 JavaScript 來講頗有用。幸虧JavaScript是一門靈活的語言,能夠經過下面這段代碼來進行動態加載 JavaScript 文件。
var script = document.createElement( 'script' ),
head = document.head;
script.src = 'http://example.com/test.js';
script.async = 'async';
head.insertBefore( script, head.firstChild );
傳統的加載方式必須在頁面中放置一個 script 標籤來進行加載。
<script type="text/javascript" src="http://example.com/test.js"></script>
更好的分離
那若是要加載多個就得放置多個 script 標籤,若是是加載模塊的話,拿 easy.js 來講,頁面中始終只要引用 easy.js 便可,這樣對於 HTML 和 JavaScript 分離頗有好處,在某些場景下這個分離度很重要。
就拿我司的狀況來講吧。後端的 view 層並非由咱們前端來開發的,項目上線的時候,前端只能更新 CSS 和 JS 文件,HTML 文件動不了。若是前端要在該頁面新增一個 JavaScript 文件的引用是很麻煩的,由於後端程序的更新都要嚴格按照流程來並有固定的更新時間,若是是用模塊加載的方式不用再理會後端的更新。固然,你也許會說,若是原頁面中已經有 JavaScript 文件,我直接在原文件中加代碼不就好了,那麼接下來講說直接在原文件中新增代碼會碰到什麼樣的問題。託福改分
更好的代碼組織方式
若是單個文件愈來愈大,維護起來出問題的概率也會愈來愈大,一我的開發還好,若是是多人開發,不一樣的代碼風格,超多的業務邏輯混雜在一塊兒,不要說維護了,光想一想都蛋痛。模塊式的開發,一個文件就是一個模塊,控制了文件的粒度,每一個模塊能夠專一於一個功能。正所謂一個蘿蔔一個坑,多人開發時,各自管好本身坑裏的蘿蔔就好了,這也正是 OOP 的思想託福答案
按需加載
仍是圍繞單個文件來講事,當文件大到必定的程度,性能問題也隨之而來了。合併文件是能減小請求,這是會帶來性能的提高,可是當文件大到必定的體積時,此時的下載時間可能並不會比多個小文件的下載時間更短。此時就須要權衡請求數和文件體積的關係了。
單文件還有一個問題,那就是緩存是否能充分的利用好。若是一個大致積的文件內包含了超多的業務邏輯和複雜的功能,而這個文件同時又被不少頁面引用到。好比在某頁面,實際只用到了該文件一個不多的功能,那麼其餘的代碼對於該頁面來講就是多餘的,浪費了加載流量。你或許會說,這個文件雖然大,可是它第一次加載的時候就被緩存過了,儘管在某頁面只用到了極少部分的功能,但只要緩存過,加載仍是挺快的。是的,若是狀況有這麼理想確定是好事。可是,每每理想和現實都會有差距,若是產品的迭代更新太快,業務需求一天一個樣,那麼該文件就會三天兩頭的更新,更新多是一個很小的功能,可是這樣的更新對於刷新緩存的代價但是很大的。若是確實有這種狀況,就說明這種設計確實是有問題。若是能合理的對文件進行模塊化的管理,那麼能夠儘可能減小沒必要要的加載,儘可能減小刷新大文件的緩存帶來的損失,這也須要權衡好,好比將不多更新的合併成一個文件,常更新的獨立成模塊。
避免命名衝突
JavaScript 自己是沒有命名空間的,爲了不命名衝突,常常會使用對象和閉包的辦法來避免。用對象僅僅是下降了衝突的機率而已,拿常用 jQuery 的開發來講,不管是往 $ 上擴展仍是在 $.fn 上擴展,人多了不免會起衝突。或者用自定義的對象,搞個好幾層,不光是寫起來難記,這樣的調用也會在性能上打折扣的。模塊化就很好的解決了這個問題,在該模塊內的任何形式的命名都不會再和其餘模塊有衝突,你想起啥名都行了。固然,你硬要在模塊內部給 window 上掛一堆東西,我也沒辦法。
既然每一個模塊都是封閉式的,那麼模塊之間如何通訊呢?接口的設計那是必須的。很簡單,對於像 seajs 這種 CMD 規範的,須要使用自定義的關鍵字來向外部暴露一個接口。
define(function( require, exports ){
var hello = 'hello world';
// 向外部暴露該模塊的接口
exports.hello = hello;
});
easy.js 遵循 AMD 規範,暴露接口更簡單,直接用 return 關鍵詞便可。
define( 'hello', function(){
var hello = 'hello world';
// 向外部暴露該模塊的接口
return hello;
});
更好的依賴處理
傳統的開發模式,若是 B 文件要依賴 A 文件,那麼必須在 B 文件前面用 script 的形式先加載好 A 文件。若是有一天,B 文件再也不須要依賴 A 文件,或者要增長依賴文件 C,那麼又回到了我說的第一個問題上。若是這個 B 文件被 N 個頁面在調用,並且頁面還跨業務站點,那改起來簡直就是噩夢啊。若是是用模塊化,只須要在模塊內部聲明好依賴就好了,增長刪除都直接修改模塊便可。調用的時候也不用管該模塊依賴了哪些其餘模塊,放心的用就是了。
好了,講了這麼多,若是你仍是以爲無動於衷,要麼是你接觸到的項目較小,還沒複雜到這個程度,要麼就是個人表達能力有問題。若是你以爲還有什麼須要補充的,歡迎在下面留言。
javascript