nodejs express 框架解密2-如何建立一個app

本文是基於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 模塊,渲染咱們的模板。

相關文章
相關標籤/搜索