模仿RequireJs的用法寫一個低配版的模塊加載器

模仿RequireJs的用法寫一個低配版的模塊加載器


Contents

  1. 前言
  2. 回顧RequireJs的基本用法
  3. 實現(xiàn)原理
  4. 使用方法
  5. 總結

前言


前段時間一直想用單頁開發(fā)技術寫一個自己的個人網(wǎng)站(使用es2015),寫了一部分之后,發(fā)現(xiàn)單頁應用因為只有一個頁面,所以第一次加載index.html時就要下載所有js文件暖眼,并且為了好管理各個部分的狀態(tài),需要劃分頁面的各個功能區(qū)為各個模塊颜凯,es2015本身是不支持一些模塊規(guī)范的(比如AMD湿颅、CMD叨襟、CommonJs等)敬扛,所以只能這樣模擬實現(xiàn):

  // global
  var spa = (function(){...})();

  // module blog
  spa.blog = (function(){
    ...
    return {
      do1: do1,
      do2: do2,
    };
  })();

  // module model
  spa.model = (function(){...})();

  // module shell
  spa.model = (function(){...})();

并且各個模塊之間又存在一些依賴關系讥巡,在index.html里面寫script標簽來載入模塊時需要寫很多個,同時也要根據(jù)依賴關系來確定書寫順序舔哪,頁面邏輯混亂,如下:

  <script type="text/javascript" src="/javascripts/spa.utils.js"></script>
  <script type="text/javascript" src="/javascripts/spa.model.js"></script>
  <script type="text/javascript" src="/javascripts/spa.mock.js"></script>
  <script type="text/javascript" src="/javascripts/spa.chat.js"></script>
  <script type="text/javascript" src="/javascripts/spa.blog.js"></script>
  <script type="text/javascript" src="/javascripts/spa.action.js"></script>
  <script type="text/javascript" src="/javascripts/spa.shell.js"></script>

之前用過RequireJs(一個流行的JavaScript模塊加載器)槽棍,它是用同構js的架構來寫的捉蚤,所以node.js環(huán)境下也能使用。我想自己可以嘗試一下寫一個低配版的js模塊加載器 requireJs-nojsja 來應付一下我這個單頁網(wǎng)站炼七,當然只是大致模仿了主要功能缆巧。

回顧RequireJs的基本用法


  1. 配置模塊信息
  requirejs.config({
      baseUrl: '/javascripts',  // 配置根目錄
      paths: {
        moduleA: 'a.js',
        moduleB: 'b.js',
        moduleC: 'c.js',
      },
      shim: {  // 配置不遵循amd規(guī)范的模塊
        moduleC: {
          exports: 'log',
          deps: ['moduleA']
        }
      },
  });
  1. 定義一個模塊
  define(name, ['moduleA', 'moduleB'], function(a, b){
    ...
    return {
      do: function() {
        a.doSomething();
        b.doAnother();
      }
    };
  });
  1. 引用一個模塊
  // 引用模塊
  require(['moduleA', 'moduleB'], function(a, b) {
    a.doSomething();
    b.doAnother();
  });

實現(xiàn)原理


  1. config方法確定各個模塊的依賴關系
  /* 記錄模塊訪問地址和模塊的依賴等信息 */
  Require.config({
    baseUrl: '/javascripts/',
    paths: {
      'moduleA': './moduleA.js',  // 相對于當前目錄
      'moduleB': '/javascripts/moduleB.js',  // 不使用baseUrl
      'moduleC': 'moduleC.js',

      'moduleD': {
        url: 'moduleD.js',
        deps: ['moduleE', 'moduleF'],
      },
      ...
    },
    shim: {
      'moduleH': {
        url: 'moduleH.js',
        exports: 'log',
      },
    }
  });
  1. 數(shù)據(jù)請求過程分析

(1) config配置模塊信息時并不會觸發(fā)網(wǎng)絡請求
(2) 在index.js主入口文件里使用require方法引用多個模塊時,根據(jù)config配置文件構造一下所有模塊的依賴分析樹豌拙。按深度優(yōu)先或是廣度優(yōu)先來遍歷這個依賴樹陕悬,將所有依賴按照依賴順序放進一個數(shù)組,最后進行數(shù)組去重處理按傅,因為會出現(xiàn)依賴重復的情況

  var dependsTree = new Tree('dependsTree');
  var dependsArray = [];
  var dependsFlag = {};  // 解決循環(huán)依賴

  // 創(chuàng)建樹
  setDepends(depends, dependsTree);
  // 得到依賴數(shù)組
  sortDepends(dependsArray, dependsTree);
  // 數(shù)據(jù)去重
  arrayFilter(dependsArray);

  return dependsArray;

(3) 創(chuàng)建XHR對象異步下載數(shù)組里面的所有js文件捉超,按照依賴順序挨個解析js代碼胧卤,解析完成后觸發(fā)回調函數(shù),回調函數(shù)里傳入各個模塊的引用

  // ajax下載代碼文件
  Utils.request(url, 'get', null, function(responseText){
    // 暫時保存
    _temp[module_name] = responseText;
  });

  // 文件下載完成后eval解析代碼
  array.map(function(jsText){
    ...
    eval(jsText);
    ...
  });

  // 調用回調函數(shù)
  callback.apply(null, [dep1, dep2, dep3]);

使用方法


詳細說明: github README.md

總結


  1. 下載js代碼時我用了ajax來實現(xiàn)拼岳,所以對于跨域文件和CDN會有點問題枝誊,這個可以改成創(chuàng)建script標簽,指定標簽src惜纸,最后將document.head.appendChild(script)叶撒,這樣來解決,其它的諸如使用XMLHttpRequest 2.0耐版,iframe等也可以的祠够,可以實驗一下。
  2. 解析代碼時我用了eval的方法粪牲,這個eval在JavaScript里面是眾說紛紜古瓤,可以看看這個,如果是用了上面創(chuàng)建script標簽的方法的話虑瀑,就不用自己eval了湿滓。
  3. 發(fā)現(xiàn)一個bug,存在循環(huán)依賴時舌狗,代碼會報錯叽奥,還沒去解決。RequireJs是這樣處理的:模塊a依賴b痛侍,同時b依賴a朝氓,這種情況下b的模塊函數(shù)被調用時,被傳入的a是undefined主届,所以需要自己在b里面手動require一下a赵哲。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市君丁,隨后出現(xiàn)的幾起案子枫夺,更是在濱河造成了極大的恐慌,老刑警劉巖绘闷,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件橡庞,死亡現(xiàn)場離奇詭異,居然都是意外死亡印蔗,警方通過查閱死者的電腦和手機扒最,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來华嘹,“玉大人吧趣,你說我怎么就攤上這事。” “怎么了强挫?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵岔霸,是天一觀的道長。 經(jīng)常有香客問我纠拔,道長秉剑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任稠诲,我火速辦了婚禮侦鹏,結果婚禮上,老公的妹妹穿的比我還像新娘臀叙。我一直安慰自己略水,他們只是感情好,可當我...
    茶點故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布劝萤。 她就那樣靜靜地躺著渊涝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪床嫌。 梳的紋絲不亂的頭發(fā)上跨释,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天,我揣著相機與錄音厌处,去河邊找鬼鳖谈。 笑死,一個胖子當著我的面吹牛阔涉,可吹牛的內容都是我干的缆娃。 我是一名探鬼主播蹲诀,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼塔逃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了冬念?” 一聲冷哼從身側響起椭住,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤崇渗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后京郑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體显押,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年傻挂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挖息。...
    茶點故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡金拒,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情绪抛,我是刑警寧澤资铡,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站幢码,受9級特大地震影響笤休,放射性物質發(fā)生泄漏。R本人自食惡果不足惜症副,卻給世界環(huán)境...
    茶點故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一店雅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贞铣,春花似錦闹啦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至酱畅,卻和暖如春琳袄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纺酸。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工窖逗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吁峻。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓滑负,卻偏偏與公主長得像,于是被迫代替她去往敵國和親用含。 傳聞我的和親對象是個殘疾皇子矮慕,可洞房花燭夜當晚...
    茶點故事閱讀 45,930評論 2 361

推薦閱讀更多精彩內容

  • 導語: 之前一直有聽說RequireJS,但是一直都沒機會去了解啄骇,只知道它是一個給js做模塊化的API痴鳄。最近在做R...
    wuqke閱讀 40,934評論 11 78
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)缸夹,斷路器痪寻,智...
    卡卡羅2017閱讀 134,719評論 18 139
  • requirejs、require方法沖突 如果加載了多個requirejs腳本虽惭,每個requirejs會判斷是否...
    Howie223閱讀 1,662評論 1 2
  • 孩子生病后橡类,先生自責地說:“要知道是這樣,我病了就該在公司睡覺芽唇,害得孩子跟著受罪顾画,都怨我取劫。”親情就是這樣研侣,自己咽下...
    瞳瞳日中的微笑閱讀 231評論 0 2
  • 過得好快庶诡,兩天就這樣過去了惦银。仿佛還在看著你。星期天的時候有點疲倦末誓,見到你后精神好多了扯俱,能有你在身邊感到很舒適。好像...
    SZhua閱讀 235評論 0 0