我們?cè)谟脀ebpack打包之后泛领,會(huì)生成一個(gè)打包的文件,這個(gè)文件里到底做了什么呢械拍?
就讓我來(lái)一步步為你分解
假如我現(xiàn)在有一個(gè)a.js文件
// a.js
module.exports = 'aaaaaaa';
我還有一個(gè)b.js文件
//b.js
var a = require('./a.js')
console.log(a)
那么現(xiàn)在我把b.js作為入口文件,打包出來(lái)的結(jié)果就是下面的代碼,注意:下面的代碼是經(jīng)過(guò)我簡(jiǎn)化之后胡陪,便于你理解webpack的代碼沥寥,只有27行,原始代碼比這個(gè)要多柠座。
var moduleArr = [
(function(module,exports){
module.exports = "aaaaa"
}),(function(module,exports,webpackRequire){
var a = webpackRequire(0);
console.log(a)
})
];
(function(modules){
var installedModules = {};
function webpackRequire(moduleId){
if(installedModules[moduleId]){
return installedModules[moduleId].exports;
}else { //為installedModules里增加一個(gè)moduleId邑雅,它指向一個(gè)對(duì)象
var module = installedModules[moduleId] = {
i: moduleId,
l:false,//是否已經(jīng)load的意思
exports:{}// 這個(gè)模塊到底exports出了什么東西,放到這
}
modules[moduleId](module,module.exports,webpackRequire)
module.l = true //表明已經(jīng)load進(jìn)了installedModules對(duì)象中
return module.exports;
}
}
webpackRequire(1)
})(moduleArr)
參數(shù)
var moduleArr = [
(function(module,exports){
module.exports = "aaaaa"
}),(function(module,exports,webpackRequire){ //注意這有一個(gè)webpackRequire的參數(shù)
var a = webpackRequire(0);
console.log(a)
})
];
最頂部妈经,我聲明了一個(gè)數(shù)組moduleArr淮野,這個(gè)數(shù)組里有兩個(gè)匿名函數(shù),每個(gè)匿名函數(shù)都需要module和exports吹泡,但其中一個(gè)函數(shù)還需要另外一個(gè)參數(shù)骤星,webpackRequire,這個(gè)參數(shù)是什么呢爆哑?我們看他的函數(shù)體很明顯知道這個(gè)參數(shù)是一個(gè)方法洞难,給它傳了一個(gè)參數(shù)0。而且揭朝,你不覺(jué)得函數(shù)體內(nèi)的代碼就是我上面那兩個(gè)簡(jiǎn)單的a.js和b.js文件中的代碼嗎队贱?
立即執(zhí)行
然后,我們看打包出來(lái)的文件中有一個(gè)立即執(zhí)行函數(shù)潭袱,這個(gè)函數(shù)需要一個(gè)modules的參數(shù)柱嫌,這個(gè)參數(shù)是什么呢?在這個(gè)函數(shù)的最底部屯换,我們把moduleArr傳進(jìn)去了编丘,說(shuō)明這個(gè)參數(shù)是一個(gè)數(shù)組。
然后我們看這個(gè)函數(shù)體彤悔,好多代碼嘉抓,怎么看?
跳過(guò)所有變量聲明和函數(shù)聲明字段蜗巧,只看代碼執(zhí)行字段掌眠,哪個(gè)?就是最底部那行
webpackRequire(1)
這行代碼是要執(zhí)行webpackRequire函數(shù)幕屹,并給它賦予了參數(shù)1蓝丙,然后我么再往回看這個(gè)函數(shù)要做什么。
webpackRequire函數(shù)做了什么
接著拆分
function webpackRequire(moduleId){
if(installedModules[moduleId]){
return installedModules[moduleId].exports;
}else { //為installedModules里增加一個(gè)moduleId望拖,它指向一個(gè)對(duì)象
var module = installedModules[moduleId] = {
i: moduleId,
l:false,//是否已經(jīng)load的意思
exports:{}// 這個(gè)模塊到底exports出了什么東西渺尘,放到這
}
modules[moduleId](module,module.exports,webpackRequire)
module.l = true //表明已經(jīng)load進(jìn)了installedModules對(duì)象中
return module.exports;
}
這個(gè)函數(shù)需要一個(gè)moduleId的參數(shù),然后函數(shù)體內(nèi)有一個(gè)條件判斷語(yǔ)句说敏,
然后我們看到了installedModules鸥跟,是什么?再往回看,發(fā)現(xiàn)它是一個(gè)空對(duì)象医咨,那它里面肯定沒(méi)有moduleId這個(gè)key枫匾,然后看else分支做了什么
啊···,現(xiàn)在它直接給installedModules添加屬性了
installedModules[moduleId] = {
i: moduleId, // 1
l:false,//我理解的是這個(gè)模塊是否已經(jīng)load的意思拟淮,如果錯(cuò)了通知我
exports:{}// 這個(gè)模塊到底exports出了什么東西干茉,放到這
}
添加完屬性我們接著往下看
咦,modules是什么很泊?就是傳給整個(gè)立即執(zhí)行函數(shù)的參數(shù)角虫,我都快忘了,這才開(kāi)始調(diào)用委造,早干嘛去了戳鹅。
modules[1]對(duì)應(yīng)的是moduleArr的第二個(gè)匿名函數(shù),這里執(zhí)行的時(shí)候,傳給了它三個(gè)參數(shù)昏兆,module就是installedModules[1],module.exports是一個(gè)空對(duì)象枫虏,webpackRequire是一個(gè)參數(shù),竟然把它自己都傳進(jìn)去了亮垫,這個(gè)叫遞歸模软。
然后我們執(zhí)行這個(gè)匿名函數(shù)吧伟骨!
匿名函數(shù)做了什么
我們接著看第二個(gè)匿名函數(shù)
function(module,exports,webpackRequire){ //注意這有一個(gè)webpackRequire的參數(shù)
var a = webpackRequire(0);
console.log(a)
}
這個(gè)函數(shù)中根本就沒(méi)有用到module和module.exports饮潦,只用到了webpackRequire,我們看到它又給webpackRequire賦參0,還記得我們第一次調(diào)用webpackRequire這個(gè)函數(shù)是什么時(shí)候嗎携狭?不記得就往回翻翻继蜡。
然后做了什么?再往回看 webpackRequire函數(shù)做了什么這一段逛腿,重復(fù)一遍稀并。
重復(fù)完了嗎,重復(fù)完了我們就應(yīng)該進(jìn)入到了另外一個(gè)匿名函數(shù)
匿名函數(shù)到底做了什么
function(module,exports){
module.exports = "aaaaa"
}
上面那個(gè)匿名函數(shù)帶我們兜了一圈单默,又把我們帶到了另外一個(gè)匿名函數(shù)碘举,注意,此時(shí)上面那個(gè)匿名函數(shù)還沒(méi)有執(zhí)行完。
然后我們看當(dāng)前這個(gè)匿名函數(shù),這個(gè)函數(shù)體內(nèi)有module豌骏,有exports谜悟,那么傳進(jìn)來(lái)的參數(shù),module,module.exports就可以派上用場(chǎng)了,具體執(zhí)行完就應(yīng)該是這樣
installedModules[0] = {
i:0,
l:false,
exports: "aaaaa"
}
好了巷送,匿名函數(shù)就干了這么點(diǎn)事,然后我們重新回到webpackRequire函數(shù),盡未完之事售滤。
module.l = true //表明已經(jīng)load進(jìn)了installedModules對(duì)象中
return module.exports; // "aaaaa"
這個(gè)return是干嘛用的,還記得我說(shuō) 有一個(gè)匿名函數(shù)并沒(méi)有執(zhí)行完嗎?
function(module,exports,webpackRequire){ //注意這有一個(gè)webpackRequire的參數(shù)
var a = webpackRequire(0);
console.log(a)
}
明白了吧完箩,return就是把 “aaaaa” 賦值給了a赐俗,然后再控制臺(tái)打印出a。
這就完了嗎弊知?
沒(méi)呢秃励!
module.l = true //表明已經(jīng)load進(jìn)了installedModules對(duì)象中
return module.exports; // 還是空對(duì)象{}
那這個(gè)return出來(lái)的空對(duì)象又是誰(shuí)的結(jié)果?
還記得我問(wèn)第一次調(diào)用webpackRequire函數(shù)是什么時(shí)候嗎吉捶?
嘿嘿···
完