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


本文是基於express 3.4.6 的

1.在我們的app.js 文件里面有這么幾行

 

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

這個其實是調用http模塊 的 createServer 函數創建一個服務,然后監聽端口的。

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;將這個作為模塊導出了,作為一個構造函數。

這個函數是: 

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()方法,這個其實是調用application

中的init方法。

3.application.js 

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 模塊,渲染我們的模板。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM