鸽了鸽了,webpack源码大垃圾,看了那么久,感觉自己越来越渣……还是换个口味,node了解一下?

  尝试从express框架源码入手,学习一下node的http模块相关的知识。

入口文件

  先从框架的主文件入手,该JS文件包含三大部分:

1、外部/工具模块引入与属性挂载

2、主函数定义

3、中间件的分离提示

  

  首先是第一块,具体的相关代码如下:

var bodyParser = require('body-parser')
var EventEmitter = require('events').EventEmitter;
var mixin = require('merge-descriptors');
var proto = require('./application');
var Route = require('./router/route');
var Router = require('./router');
var req = require('./request');
var res = require('./response'); // 内部模块 exports.application = proto;
exports.request = req;
exports.response = res; // 构造方法 exports.Route = Route;
exports.Router = Router; // 中间件 exports.json = bodyParser.json
exports.query = require('./middleware/query');
exports.static = require('serve-static');
exports.urlencoded = bodyParser.urlencoded

  昨天正正经经的刷了一遍官方文档,在API的那一块,很暴力的把express分为了5个模块:

1、express本身

2、Application

3、Request

4、Response

5、Router

  从源码来看也正是这样的,值得注意的是,express内部自带了body-parser模块,并且将该模块用来解析application/json与application/x-www-form-urlencoded形式的方法添加到了express上面。

  EventEmitter是node内置事件模块,不必多讲。剩下的就是mixin方法,可以看下源码:

var hasOwnProperty = Object.prototype.hasOwnProperty

module.exports = function merge(dest, src, redefine) {
// 错误处理
if (!dest) throw new TypeError('argument dest is required')
if (!src) throw new TypeError('argument src is required')
// 默认为true
if (redefine === undefined) redefine = true Object.getOwnPropertyNames(src).forEach(function forEachOwnPropertyName(name) {
// redefine参数的作用是在目标对象与源对象有冲突键时 是否进行覆盖定义
if (!redefine && hasOwnProperty.call(dest, name)) return // 复制所有键 包含不可枚举的
var descriptor = Object.getOwnPropertyDescriptor(src, name)
Object.defineProperty(dest, name, descriptor)
})
return dest
}

  所以说,在引入express模块后,除了直接执行获取app实例,还可以调用上面的一些方法。

  第二块就来看主函数的定义了,大部分的情况下,express的使用不外乎下面两行代码:

var express = require('express');
var app = express();

  也就是express模块本身在引入后是一个函数,而函数的源码如下:

function createApplication() {
// 返回的app实例也是一个函数
var app = function(req, res, next) {
app.handle(req, res, next);
};
// 目标对象属性的复制
mixin(app, EventEmitter.prototype, false);
mixin(app, proto, false); // 挂载req、res的属性
app.request = Object.create(req, {
app: { configurable: true, enumerable: true, writable: true, value: app }
});
app.response = Object.create(res, {
app: { configurable: true, enumerable: true, writable: true, value: app }
}); // 初始化
// 该方法来源于上面的proto
app.init();
return app;
}

  函数十分简单,首先定义了一个函数,然后将EventEmitter、proto(application)上面的属性添加到函数上,把request、response的原型设置为引入的内部模块req、res,调用init初始化方法后,返回app。

4.18后记,补充一下这里的知识点:

  这里返回函数是必要的,首先参照正常情况下创建node服务器的代码:

let http = require('http');
http.createServer((req, res) => {
// ...
}).listen(9123);

  可以看出,第二步的方法调用接受一个函数,通常我们会在这处理请求并进行响应。

  而app.listen方法(这里提前讲一下)的代码如下:

app.listen = function listen() {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};

  可以看到,基本上就是原生的方法,对应传进去的函数变成了this,this指向什么呢?就是生成的函数,当有请求时,触发的函数就是app.handle方法。

  涉及的handle、init方法均来源于混入的proto中,这个后面再看。

  第三块就是4.x的一个变化:Express 4 不再依赖 Connect,而且从内核中移除了除 express.static 外的所有内置中间件。

  从代码来看就很直白:

// 分号确实是源码里的
// 因为上一行代码没有分号
;[
'bodyParser',
'compress',
'cookieSession',
'session',
'logger',
'cookieParser',
'favicon',
'responseTime',
'errorHandler',
'timeout',
'methodOverride',
'vhost',
'csrf',
'directory',
'limit',
'multipart',
'staticCache',
].forEach(function (name) {
// 每次尝试在express上访问这些属性将会报错
Object.defineProperty(exports, name, {
get: function () {
throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.');
},
configurable: true
});
});

  对原有的中间件属性访问将会报错……但是问题是内部又引入了body-parser模块,看来还是不能完全脱离,偷偷用了一个。

  完结。

.1-浅析express源码之入口文件的更多相关文章

  1. Yii2 源码分析 入口文件执行流程

    Yii2 源码分析  入口文件执行流程 1. 入口文件:web/index.php,第12行.(new yii\web\Application($config)->run()) 入口文件主要做4 ...

  2. 详细解析Thinkphp5.1源码执行入口文件index.php运行过程

    详细解析Thinkphp5.1源码执行入口文件index.php运行过程 运行了public目录下的index.php文件后,tp的运行整个运行过程的解析 入口文件index.php代码如下: < ...

  3. tp3.2源码解析——入口文件

    如果有人读这篇文章并跟着做的话,希望你能使用支持函数跳转的编辑器,还要善用var_dump和exit,对着源码去调试着看.跟着入口文件读,执行到哪里你看到哪里,对于那些不能一眼看出来的配置,则要记录下 ...

  4. MyBatis 源码分析 - 映射文件解析过程

    1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...

  5. .5-浅析express源码之Router模块(1)-默认中间件

    模块application已经完结,开始讲Router路由部分. 切入口仍然在application模块中,方法就是那个随处可见的lazyrouter. 基本上除了初始化init方法,其余的app.u ...

  6. express源码分析之Router

    express作为nodejs平台下非常流行的web框架,相信大家都对其已经很熟悉了,对于express的使用这里不再多说,如有需要可以移步到www.expressjs.com自行查看express的 ...

  7. Hyperledger Fabric 1.0 从零开始(四)——Fabric源码及镜像文件处理

    2:Fabric源码及镜像文件处理 2.1下载Fabric源码 下载Fabric源码是因为要用到源码中提到的列子和工具,工具编译需要用到go语言环境,因此需要把源码目录放到$GOPATH下.通过1.3 ...

  8. 单独编译和使用webrtc音频回声消除模块(附完整源码+测试音频文件)

    单独编译和使用webrtc音频降噪模块(附完整源码+测试音频文件) 单独编译和使用webrtc音频增益模块(附完整源码+测试音频文件) 说实话很不想写这篇文章,因为这和我一贯推崇的最好全部编译并使用w ...

  9. 单独编译和使用webrtc音频降噪模块(附完整源码+测试音频文件)

    单独编译和使用webrtc音频增益模块(附完整源码+测试音频文件) 单独编译和使用webrtc音频回声消除模块(附完整源码+测试音频文件) webrtc的音频处理模块分为降噪ns,回音消除aec,回声 ...

随机推荐

  1. 转:spring的启动过程-spring和springMVC父子容器的原理

    要想很好理解这三个上下文的关系,需要先熟悉spring是怎样在web容器中启动起来的.spring的启动过程其实就是其IoC容器的启动过程,对于web程序,IoC容器启动过程即是建立上下文的过程. s ...

  2. double float的精度问题

    三部曲 1: #include <iostream> #include <stdio.h> #include <string.h> using namespace ...

  3. centos7 搭建WEB服务器

    centos7 搭建WEB服务器 2017年09月17日 09:44:50 逝然1994 阅读数:18321 标签: centosapacheweb服务器 更多 个人分类: centos服务器简单配置 ...

  4. UITableView横向滚动

    UITableView 设置 CGRect tableViewRect = CGRectMake(0.0, 0.0, 50.0, 320.0); self.tableView = [[UITableV ...

  5. WPF 网易云音乐PC端

    简介 (1)左侧菜单采用 Expander+RadioButton: MVVM 绑定 后台的一个Menu 属性(使用转换器) (2)右侧采用Frame绑定Page的方式 ## [更新日志] ### 1 ...

  6. 设计模式:Builder

    简介 建造者模式(Builder),将一个复杂对象的表示和它的构建分离,这样同样的构造过程可以创建出不同的对象状态. 类图 下面的Product是要创建的对象的目标类型,产品. Builder 创建一 ...

  7. Android Dagger 2 无法自动生成 Dagger Component

    给项目升级 gradle(3.0)和 build(27)后发现 Dagger 2 无法自动生成 Dagger Component 类了. 原因竟是我把 : kapt 'com.google.dagge ...

  8. LOJ#3092. 「BJOI2019」排兵布阵(递推)

    题面 传送门 题解 设\(dp_{i,j}\)表示前\(i\)座塔派了总共\(j\)个人的最大收益,转移显然 //minamoto #include<bits/stdc++.h> #def ...

  9. 微信赌场——H5棋牌游戏渗透之旅

    i春秋作家:F0rmat 0x01 前言 本来不想发的,涉及太多利益了,这些棋牌游戏的源码最高能卖到几万.开发起来不比一个商场程序难.最近又太忙了,没时间去做代码审计的文章了,但一不小心又抢了个运气王 ...

  10. Linux学习笔记-基本操作1

    1>. 命令解析器2>. Linux快捷键3>. Linux 系统目录结构4>. 用户目录5>. 文件和目录操作6>. 文件和目录的属性7>. 文件权限, 用 ...