简介
这篇文章的主要的目的是通过研究express核心源码,让我们对express深入理解,不仅会用express,还要理解其背后的思想,提高开发效率。研究express源码,学习大神的代码结构。本文只介绍核心代码和核心流程,类型判断和express的使用等不包括在内。
express
express里的核心文件是index、express、application、router/index、router/layer、router/route。 index里只有一句话
module.exports = require('./lib/express');
复制代码
导入express,并导出。express文件里是导出许多api,像express、express.Router等。我们开发是用到的express(),实际上是执行createApplication()。application里是和app相关的api。 router/index里是和router相关的代码,router可以理解成路由器,把各个请求发给route。我们不会直接调用router/layer里的方法,layer是一个抽象概念,在express里中间件、路由都放在app._router.stack里,stack里的每个元素就是一个layer。 route里也有一个stack,里面的元素也是layer。
?
- 从下面的代码开始对express源码的研究:
- 用express做一个简单的服务器,访问http://localhost:3000,返回"Hello World"
const express = require('express');
const app = express();
app.get('/', (req, res,next)=>{
res.send('Hello World');
next()
});
app.listen(3000,()=>{
console.log('server is ok');
});
复制代码
- express(),实际调用createApplication(),返回一个app函数。
function createApplication() {
var app = function(req, res, next) {
app.handle(req, res, next);
};
//把proto的方法给app等初始化操作。
return app;
}
复制代码
- 这个app上有"application.js"的导出对象proto上的所有方法。proto在"application.js"里命名app,为了方便,下文都成为app。
- app上有一个lazyrouter()方法,改方法主要是判断app._router是否存在,如果不存在new Router赋值给app._router。
- app.get里的核心代码如下:
app.get = function(path){
this.lazyrouter();
var route = this._router.route(path);
route[method].apply(route, slice.call(arguments, 1));
return this;
};
复制代码
- route里是真正处理请求回调的函数,在route[method]里,循环参数,每次循环新建一个layer,handle是app.get的回调,把layer放在route的stack里。route[method]里的核心代码是:
var layer = Layer('/', {}, handle);
layer.method = method;
this.methods[method] = true;
this.stack.push(layer);
复制代码
- this._router即Router的实例。this._router.route(path)这个方法的核心代码如下:
proto.route = function route(path) {
var route = new Route(path);
var layer = new Layer(path, {}, route.dispatch.bind(route));
layer.route = route;
this.stack.push(layer);
return route;
};
复制代码
- route方法里新建了一个Route和Layer,Layer的第三个参数handle,是express中间件执行的核心内容(个人想法,欢迎讨论)。源码中可以看到,layer放到了this.stack,其实就是app._router.stack。 app._router.stack里存放着中间件。最后返回route。app.get执行结束,下面是app.listen:
作者:PlayerWho
链接:https://juejin.im/post/5aadbd856fb9a028ca52c02c
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。