本文是基於express 3.4.6 的express
1.在咱們的app.js 文件裏面有這麼幾行json
http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); });
這個實際上是調用http模塊 的 createServer 函數建立一個服務,而後監聽端口的。api
2. 咱們再去看看express 的入口文件 服務器
/** * Module dependencies. */ var connect = require('connect') , proto = require('./application') , Route = require('./router/route') , Router = require('./router') , req = require('./request') , res = require('./response') , utils = connect.utils; /** * Expose `createApplication()`. */ exports = module.exports = createApplication; /** * Expose mime. */ exports.mime = connect.mime; /** * Create an express application. * * @return {Function} * @api public */ function createApplication() { var app = connect(); //將application中的方法所有拷貝到connect對象上去。 utils.merge(app, proto); //設置app 的request對象的原型爲req,自己的屬性爲connect對象 app.request = { __proto__: req, app: app }; //設置app的response對象原型爲res ,自己的屬性爲connect對象 app.response = { __proto__: res, app: app }; //調用application中的方法init app.init(); return app; } /** * Expose connect.middleware as express.* * for example `express.logger` etc. */ /** * 加載connect模塊中得全部中間件 */ for (var key in connect.middleware) { Object.defineProperty( exports , key , Object.getOwnPropertyDescriptor(connect.middleware, key)); } /** * Error on createServer(). */ /** * 將建立服務器的方法輸出 * @returns {Function} */ exports.createServer = function(){ console.warn('Warning: express.createServer() is deprecated, express'); console.warn('applications no longer inherit from http.Server,'); console.warn('please use:'); console.warn(''); console.warn(' var express = require("express");'); console.warn(' var app = express();'); console.warn(''); //加載建立應用程序的方法,開始建立application return createApplication(); }; /** * Expose the prototypes. */ exports.application = proto; exports.request = req; exports.response = res; /** * Expose constructors. */ exports.Route = Route; exports.Router = Router; // Error handler title exports.errorHandler.title = 'Express';
能夠看到exports = module.exports = createApplication;將這個做爲模塊導出了,做爲一個構造函數。app
這個函數是: dom
function createApplication() { var app = connect(); //將application中的方法所有拷貝到connect對象上去。 utils.merge(app, proto); //設置app 的request對象的原型爲req,自己的屬性爲connect對象 app.request = { __proto__: req, app: app }; //設置app的response對象原型爲res ,自己的屬性爲connect對象 app.response = { __proto__: res, app: app }; //調用application中的方法init app.init(); return app; }
首先調用connect 組件app,因而將proto 上該有的方法都拷貝到app上去。proto是神馬麼?它就是 proto = require('./application') application.js 輸出的「app」 對象 全部得函數,函數
接着將req,res 做爲 組件app 的request,response 的原型,同時將app做爲他們的一個屬性,爲何要這麼作呢?後面就會看到。最後調用app.init()方法,這個實際上是調用applicationjsonp
中的init方法。ui
3.application.js this
app.init = function(){ this.cache = {}; this.settings = {}; this.engines = {}; //默認配置 this.defaultConfiguration(); };
咱們看到他是直接調用defaultConfiguration 方法的。咱們再去看看defaultConfiguration方法的實現
app.defaultConfiguration = function(){ // default settings this.enable('x-powered-by'); this.enable('etag'); this.set('env', process.env.NODE_ENV || 'development'); this.set('subdomain offset', 2); debug('booting in %s mode', this.get('env')); // implicit middleware //調用中間件 this.use(connect.query()); this.use(middleware.init(this)); // inherit protos //繼承原型 this.on('mount', function(parent){ this.request.__proto__ = parent.request; this.response.__proto__ = parent.response; this.engines.__proto__ = parent.engines; this.settings.__proto__ = parent.settings; }); //router //路由 this._router = new Router(this); this.routes = this._router.map; this.__defineGetter__('router', function(){ this._usedRouter = true; this._router.caseSensitive = this.enabled('case sensitive routing'); this._router.strict = this.enabled('strict routing'); return this._router.middleware; }); // setup locals this.locals = locals(this); // default locals this.locals.settings = this.settings; // default configuration this.set('view', View); this.set('views', process.cwd() + '/views'); this.set('jsonp callback name', 'callback'); this.configure('development', function(){ this.set('json spaces', 2); }); this.configure('production', function(){ this.enable('view cache'); }); };
從代碼中能夠看到,它首先調用中間件,中間件的做用主要是改寫改寫request,response 請求的。將這2個請求導出,方便後面的模板渲染。而後再調用路由模塊。路由模塊只要是根據path
調用路由分發函數分發路由,執行callback,最後調用view 模塊,渲染咱們的模板。