上個星期寫了淺入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而已
看源碼 ,這么聰明的你 ,肯定一眼就懂了
好 寫了一個下午了, 有點累, 准備一下去健身房, 樓主很瘦 怕猝死 如果你知道有很好的增肥方法, 請告訴我 哈哈哈。
最后 如果此文對你有幫助, 記得點贊哦, 你的點贊,是我繼續創作的動力。