30分鐘 帶你淺入requirejs源碼
因為最近項目想現實一個單頁功能,用的是react ,然后看了一下react route,挖槽 gzip后16k? 然后我簡單寫了一個純單頁(不支持多頁的單頁,所有入口都經過rewrite跑到index.html) 才200多行(后續放github)。
然后項目是用webpack打包的, 發現webpack的 require.ensure不支持變量加載的(至少暫時沒發現), 就是意味著我有多小頁面,就得在main(入口里配多小頁面的關系) 這樣挫,領導會噴我的。
然后我今天早上起來,想看看requirejs是如何現實的
好前戲完畢 直入主題,大家都知道requrejs 有一個data-main 配置 , 顧名思義就是 入口 類似c,java的main函數
main.js
require.config({ paths: { 'xm': 'xm', 'adb': 'db' }, waitSeconds: 50 }) requirejs(['xm', 'adb'], function(xm, db) { console.log(xm, 'main'); db.db(); });
然后定義了2個文件 ,分別是xm.js 和db.js
//xm.js define([], function() { return { name: 'xm', age: 22 } });
//db.js define(['xm'], function(xm){ return { db: function(){ var who = xm.name; console.log(who, ' play'); } } })
首先,我們把代碼疊起來, 一覽眾山小
可以看到,其實requirejs 很簡單, 只有3個api(按我的理解, 有錯請指正)
1、requirejs, 引入定義的模塊,并執行callback的代碼
2、require,只引入,不執行
3、define,定義一個模塊
然后具體看實現的地方
前面1000多行都是 內部調用的 function的實現,例如判斷函數啊, 是否數組啊,遍歷,反向遍歷 etc.. ,太細節 就不多說了

著重看看后面的req變量的實現, 本來想加些標注的, 但是發現 每行都是重點, 正如小時候老師讓我們畫重點,經常半頁書都畫上, 不如不畫了 囧。
1、這里requirejs 就是上面說到的1的實現
2、config其實就是一系列的配置,例如base路徑,path(配短名字), urlArgs(問號后加時間戳之類的),shim(沒有用define聲明的模塊,全局注入) etc..
3、nextTick 其實就是一個定時器, 按你代碼 加入的模塊,逐個依次 創建script標簽 引入到頁面
4、然后 引入require的時候,他會默認加了一個版本,默認初始化(注意這行 req({}) ), 默認錯誤提示等等
5、define函數的實現
好,有了上面已經知道require大概有些什么了, 然后來一起看看某幾個重要的細節點。
首先代碼里先看看data-main這個關鍵詞 ,其實就是遍歷所有的TagName為script的,找到data-main, 然后處理了一下路徑
然后最后一行,其實才是真正的main入口初始化

然后第一次require會根據配了的data-main 以下列處理后,通過req.load 自動引入main.js

第一次自動調用requirejs 內容基本都是默認值,沒啥好看的, 來 一起看看我們main.js 里主動調用的requrejs、
然后 繼續跟下去 發現最后調用了Module的有個each,然后是會調用自己的fetch,load進行一個一個按順序像main加載步驟一樣 加載
因為時間原因,有些太細的點就不深入一一步析 希望此文對初了解requirejs的同學有所幫助,謝謝觀看完畢。