1. 程式人生 > >Seajs原始碼解析系列(一)

Seajs原始碼解析系列(一)

前言:以前在做webgis開發的時候,就對dojo的模組化載入方式很好奇,一直想弄清楚它的實現原理,奈何其框架過於龐大,加上自己也懶,就一直沒有深入進行研究。這段時間接觸了Sea.js,淘寶前端大牛玉伯寫的。它遵循的是CMD的載入規範,據說可以像Node一樣書寫模組程式碼。好奇看了一下原始碼,嗯~,才1000來行,加上最近時間也不是太忙,就想深入研究一下。

Seajs簡介
Seajs可以理解為是一種模組載入器,可以提供一種簡單,方便的模組化載入方式。以前,我們在前端開發過程中,通過會使用script標籤載入我們需要引入的js檔案。隨著網頁的結構越來越複雜,我們需要引入的js檔案也越來越多,有的檔案之間甚至還有依賴關係,如果我們還像以前一樣將所有的程式碼都放在一個檔案中的時候,很容易出現以下問題:

  • 全域性變數互相影響
  • JavaScript檔案過大,影響下載速度
  • 結構混亂,很難維護
  • 引入檔案時需要注意其依賴關係,稍不留神可能就會發生錯誤

在這種情況下,Seajs應運而生。Sea.js 是一個成熟的開源專案,核心目標是給前端開發提供簡單、極致的模組化開發體驗。這裡不多做介紹,有興趣的可以訪問 seajs.org 檢視官方文件。

使用 Sea.js,在書寫檔案時,需要遵守 CMD (Common Module Definition)模組定義規範。一個檔案就是一個模組。那麼,使用Seajs有什麼好處呢?再次回到我們上面的問題,假如我們在開發過程中,常常會將一些基礎的、底層的功能抽象出來,獨立成一個函式,並將其放在一個基礎的函式庫中,例如util.js。

function each(){}
function error(){}

那麼,我們以後再開發過程中如果需要使用這些功能,就可以在專案中引入util.js檔案,然後直接使用。這樣看起來很方便,但是在專案的進行中,我們常常會遇到這樣的問題,假如在頁面中我也想自定義一個方法來遍歷物件,但是在util.js中已經有一個了,那我的方法就只能取其他的名字。當方法名越來越多的時候,對於我這種英語剛過四級的學渣來說,取名簡直是一種煎熬/(ㄒoㄒ)/~~。。。

另外,還有一個問題,假如我的util.js中的某個方法還依賴於baseUtil.js檔案,那麼我們在引入js檔案的時候就必須要這樣:

    <script
type="text/javascript" src="baseUtil.js">
</script> <script type="text/javascript" src="util.js"></script>

假如我們在開發過程中,忘記了依賴引入,專案中的程式碼功能可能就會報錯。

以上的問題,我相信大部分前端開發者都曾遇到過。那麼,我們如何通過Seajs的模組化開發來解決上述問題呢?
Seajs在使用過程中,需要遵守CMD規範,一個檔案就是一個模組,那麼,我們可以這樣定義我們util模組。

define(function(require,exports,module){
    exports.each=function(){};
    exports.error=function(){};
})

那麼,我們在開發過程中要如何使用我們util模組呢?例如,我們需要在前端定義一個module模組,並在其中使用util中的功能。那麼,我們的module模組就可以這樣寫:

define(function(require,exports){
    var util=require("./util.js");
    exports.init=function(){};
})

在這裡,我們通過require(“./util.js”)可以拿到util模組通過exports暴露的介面。在這裡,我們可以將require理解為Seajs為我們提供的關鍵字,通過他,我們可以獲取其他模組提供的介面。
通過以上的介紹,我們可以大致的理解了Seajs帶來的兩個好處:

  • 通過exports暴露介面,解決了命名衝突的問題
  • 通過require引入依賴,使檔案的依賴關係內建,開發者只需要關心自己目前使用的模組,其他事情Seajs會幫你做好,提高了開發效率。

至此,Seajs的介紹已基本結束,前往Seajs官網可以瞭解更多有關seajs的知識。在下一節,將會和大家進一步分享這幾天閱讀Seajs原始碼的心得體會。