鸽了鸽了,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. cocos游戏网址

    http://www.cocos.com/doc/article/index?type=cocos2d-x&url=/doc/cocos-docs-master/manual/framewor ...

  2. 利用C#迭代器的一个杨辉三角示例

    身边有个朋友在跟着廖雪峰的教程学习python,途中遇到了"在Python中使用迭代器打印杨辉三角"的问题,我在帮忙解决的同时顺手写了个简单的C#版本以供补充. internal ...

  3. Mirror--不同SQL Server版本使用的默认镜像端点加密算法不同

    在搭建镜像时遇到一个小问题,搭建镜像时报错,排查好半天,对证书/用户/登陆/连接授权等方面都做了逐一排查,未发现异常,最后生成镜像端点创建脚本时,才发现问题原因: 镜像主节点(10.50.4276)的 ...

  4. ASP.NET微信公众号用于给指定OpenId用户发送红包

    ASP.NET微信公众号用于给指定OpenId用户发送红包 微信公众号要实现对指定用户发送红包,必须指定一个存放兵发放金额的商户号,在微信商户平台里面申请商户号并获取相关参数例如发送红包所要用到的安全 ...

  5. WPF 分享一种背景动画效果

    今天看微软的一个Samples,发现一个蛮好玩的背景样式,如下图所示: 风格比较卡哇伊. <Window x:Class="WPFSamplesTest.MainWindow" ...

  6. 迁移桌面程序到MS Store(2)——Desktop App Converter

    迁移传统桌面程序到MS Store的另一种方式是使用Desktop App Converter工具.虽然本篇标题包含了Desktop App Converter(以下简称DAC),实际上我是来劝你别用 ...

  7. 关于css3中的flex

    参考几篇文章: Flex 布局语法教程 IE10中的Flexible Box("Flexbox")布局 “老”的Flexbox和“新”的Flexbox 一个可以练习的地方: NEW ...

  8. HttpURLConnection与HttpClient随笔

    目前在工作中遇到的需要各种对接接口的工作,需要用到HTTP的知识,工作完成后想要做一些笔记,本来知识打算把自己写的代码粘贴上来就好了,但是偶然发现一篇博文对这些知识的总结非常到位,自认无法写的这么好, ...

  9. 跟着刚哥深入学maven(通俗易懂)

    前言:目前所有的项目都在使用maven,可是一直没有时间去整理学习,这两天正好有时间,好好的整理一下. 一.为什么使用Maven这样的构建工具[why] ① 一个项目就是一个工程 如果项目非常庞大,就 ...

  10. 解决linux下source /etc/profile关闭终端失效问题

    本来想配置环境变量的,看网上和博客上很多说改/etc/profile,然后source /etc/profile之后就可以永久保存使环境变量生效,但是终端一关闭,就环境变量就失效了,其他终端也用不了. ...