30分鍾 帶你淺入seajs源碼


上個星期寫了淺入requirejs的,  大家都知道 require是AMD規范(Asynchronous Module Definition)

來  今天我們一起看看 CMD規范(Common Module Definition) 的seajs 是怎樣實現的

seajs比require寫的簡單, 源碼幾乎是require的一半,gzip后差距是拉近了,但是仍覺得大。
(最近對size很敏感 ,因為領導 大領導抱怨我們h5站點打開慢,今年我們逐步做提速的事情, 我心里暗下一個目標,不管業務簡單復雜 3G及以上用戶,我要做到全站秒開 做到了跟大家分享一下 哈哈)

 

結束前戲  直入主題  哈哈

sea里面一共就用到幾個api

sea.config   ------        配置函數
sea.use       ------       加載 並執行模塊(可以是多個)
define         ------       定義模塊
require        ------       同步引入模塊
require.async  ------    異步引入模塊
exports           ------   導出單個屬性
module.exports   ----- 導出整個模塊

 

詳細用法 :http://www.zhangxinxu.com/sp/seajs/docs/zh-cn/cheatsheet.html#exports

demo

目錄結構很簡單 定義了一個main.js  2個define的 模塊

//main.js
// 所有模塊都通過 define 來定義
define(function(require, exports, module) {

    // 通過 require 引入依賴
    var code = require('module/code');
    var game = require('module/game');

    console.log('code' , code);
    console.log('game' , game);

    code.codeAction();
    game.gameAction();

});
//code.js
define(function(require, exports, module) {

    exports.name = 'code';
    exports.skill = 'play';
    exports.codeAction = function() {
        console.log('coding');
    };

    // 或者通過 module.exports 提供整個接口
  /*  module.exports = {
        codeAction: function() {
            console.log('coding');
        }
    }*/


});
//game.js
define(function(require, exports, module) {

    // 或者通過 module.exports 提供整個接口
    module.exports = {
        gameAction: function() {
            console.log('gaming');
        }
    }


});

 

 

首先我覺得sea的源碼有點有意思的地方,他真的是  “那里用到, 那里定義”  看過我上一篇requrejs的文章的同學知道 我喜歡先把代碼疊起來 一覽眾山小,這招用不了在sea身上

大家看

 

像很多人都有這么一個強迫症,就是 所以定義都放在最開始的地方統一定義了, sea說 我偏不, 我哪里用到, 那里定義  哈哈  氣死處女座

 

config函數

for in 每一個屬性, 處理好后 掛在 閉包全局的data里

 

use函數

首先 seajs.use 會調用 Module.use , 然后 cid是每次調用自動++ 生成全局唯一標記,

Module.use 第一行, 初始化mod的屬性, 然后真正處理是mod.load(),注意 這里的掛了callback函數 還有 callback后刪除變量 釋放內存 

 

 

然后 module.load里 會判斷這個模塊是否加載過, 如果沒有加載過,會調用fetch方法,加載過 直接調用m.load() 

 

 

然后fetch方法里 會把加載的模塊的真實地址為key 生成requestCache[emitData.requestUri]  = sendRequest ,賦值內部函數 sendRequest,然后sendRequest調用內部onRequest
 

758line fetch函數生成模塊的請求關系后, 然后 留意768 真正執行這個fetch函數

 

然后執行request函數 addOnload 會綁定模塊獲取成功的onload和onerror函數,392,script真正插入到頁面中。

順便補充一句, sea很奇怪, 加載成功use后,會remove這個script, 我沒搞懂這個用意何在, 節省了頁面一個script?

 

define,require函數

因為2個函數 是有關系的, 可以是你中有我,我中有你, 所以就不拆開了。
先看define ,前面幾行是處理參數的, 過

主要看deps,這里其實就是解析define里的關鍵字,是否含有require,看控制台輸出

這個470行到672行 其實就是require的實現, 純粹是個體力 、嚴謹、 技巧活 ,各種字符串處理,各種正則匹配, 沒有遇到的場景,寫不出來, 純粹個人見解。 

 

然后再執行onRequest方法, 再次執行m.load方法解析modules里的依賴模塊,如果存在就像剛才use里獲取main一樣,獲取模塊,執行callback

 

 

exports

exports其實很簡單的, 其實就是一個空的obj,然后把你需要的屬性都掛在這個exports對象里面

每一個define里都有一個屬於自己的exports  不會污染別的模塊

 

exports.module

不用說你也懂了吧? 就是所有屬性都只能寫在module里,看我上圖exports下面有個exports.module的注釋, 其實就是換個寫法罷了

好剩下

require.async  

其實就是use的實現,加一個callback而已

看源碼  ,這么聰明的你 ,肯定一眼就懂了

 

 

好  寫了一個下午了, 有點累, 准備一下去健身房, 樓主很瘦  怕猝死  如果你知道有很好的增肥方法, 請告訴我  哈哈哈。

最后  如果此文對你有幫助, 記得點贊哦, 你的點贊,是我繼續創作的動力

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM