let express = require('express');
let app = express();
這是我們常用的最基礎(chǔ)的創(chuàng)建express實(shí)例的方式,然后在它的基礎(chǔ)上在構(gòu)建各自的項(xiàng)目,今天主要就是圍繞著這個(gè)app來(lái)介紹express的源碼
首先先看express目錄
express/index.js ? =====》
express/lib/express.js ? ? =====》
createApplication()
生成app
到這邊應(yīng)該都顯明扼要囚霸。接下來(lái)寞埠,在這個(gè)函數(shù)中崖技,就是對(duì)app的生成操作稿静,可以看到除了在這個(gè)文件中初始化了各種app的方法娇掏,還通過(guò)mixin操作將其他文件的app的方法給加入進(jìn)來(lái)
接下去就是使用循環(huán)結(jié)構(gòu)州刽,配合原型鏈?zhǔn)褂每罩矗沟胊pp和req/res能互相利用到:
// expose the prototype that will get set on requests
app.request = Object.create(req, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
而后依舊是基礎(chǔ)的暴露出一些基本的方法,例如router穗椅,application等
接下來(lái)是express的核心
也是前面提到的 ?
將其他文件的方法加入進(jìn)來(lái)? ? 初始化了Application(詳見(jiàn)點(diǎn)我)中的方法
此處需要注意的是路由的加載辨绊,并不是在app生成的時(shí)候加載的,而是在后期人為添加路由功能的時(shí)候動(dòng)態(tài)添加
原因:路由的添加需要使用到app配置信息匹表,為了避免路由生成的時(shí)候门坷,app的基礎(chǔ)配置信息還未生成,所以使用了lazyrouter()袍镀,進(jìn)行到入下圖的代碼時(shí)再將路由生成(情況之一)
路由:
通過(guò)lib/router下路由模塊生成
router/下有3個(gè)文件
index:主文件
route:路由
layer:express路由底層數(shù)據(jù)結(jié)構(gòu)
所有的express中間件都存放在stack數(shù)組中默蚌,由layer生成每條數(shù)據(jù)
感興趣的可以在自己項(xiàng)目里輸出一下app._router.stack觀察
了解了這些,那么可以剛才那張圖里看到苇羡,在express路由初始化生成的時(shí)候绸吸,加入了2個(gè)默認(rèn)使用的中間件
再來(lái)仔細(xì)看看路由文件
首先分析路由生成,再分析訪問(wèn)時(shí)路由的解析
思路與app生成大同小異设江,也可以看出在路由生成的時(shí)候锦茁,就生成了用來(lái)存放中間件的stack數(shù)組
需要注意的是router.handle方法就是訪問(wèn)時(shí)的路由解析操作
初始化生成路由————添加路由解析器(app.use/app.route/express.Router()等)———存放相應(yīng)中間件到stack
再來(lái)看handle方法
首先分析下express是如何接受http請(qǐng)求的
可以看到整個(gè)app是被注冊(cè)進(jìn)createServer中的,然后進(jìn)行監(jiān)聽(tīng)
我們知道叉存,在express/express.js中
實(shí)例化的app首先就執(zhí)行了handle方法码俩,用來(lái)處理http請(qǐng)求
然后去stack中找尋匹配到路由規(guī)則的中間件
不停傳遞next()方法按順序執(zhí)行中間件。
中間件越多歼捏,理論上來(lái)說(shuō)請(qǐng)求處理耗時(shí)越長(zhǎng)握玛,
按照源碼執(zhí)行的中間件查找順序可知,需要更高效率的api應(yīng)當(dāng)放在中間件(路由)的最前面(路由實(shí)質(zhì)上也就是中間件)
引出的問(wèn)題:
路由是由數(shù)組儲(chǔ)存甫菠,并且更糟糕地采取了遞歸方式遍歷挠铲,開(kāi)銷(xiāo)過(guò)大,未對(duì)相同路由采取過(guò)濾措施寂诱,導(dǎo)致會(huì)出現(xiàn)不必要的資源浪費(fèi)