.1-浅析express源码之入口文件
鸽了鸽了,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源码之入口文件的更多相关文章
- Yii2 源码分析 入口文件执行流程
Yii2 源码分析 入口文件执行流程 1. 入口文件:web/index.php,第12行.(new yii\web\Application($config)->run()) 入口文件主要做4 ...
- 详细解析Thinkphp5.1源码执行入口文件index.php运行过程
详细解析Thinkphp5.1源码执行入口文件index.php运行过程 运行了public目录下的index.php文件后,tp的运行整个运行过程的解析 入口文件index.php代码如下: < ...
- tp3.2源码解析——入口文件
如果有人读这篇文章并跟着做的话,希望你能使用支持函数跳转的编辑器,还要善用var_dump和exit,对着源码去调试着看.跟着入口文件读,执行到哪里你看到哪里,对于那些不能一眼看出来的配置,则要记录下 ...
- MyBatis 源码分析 - 映射文件解析过程
1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...
- .5-浅析express源码之Router模块(1)-默认中间件
模块application已经完结,开始讲Router路由部分. 切入口仍然在application模块中,方法就是那个随处可见的lazyrouter. 基本上除了初始化init方法,其余的app.u ...
- express源码分析之Router
express作为nodejs平台下非常流行的web框架,相信大家都对其已经很熟悉了,对于express的使用这里不再多说,如有需要可以移步到www.expressjs.com自行查看express的 ...
- Hyperledger Fabric 1.0 从零开始(四)——Fabric源码及镜像文件处理
2:Fabric源码及镜像文件处理 2.1下载Fabric源码 下载Fabric源码是因为要用到源码中提到的列子和工具,工具编译需要用到go语言环境,因此需要把源码目录放到$GOPATH下.通过1.3 ...
- 单独编译和使用webrtc音频回声消除模块(附完整源码+测试音频文件)
单独编译和使用webrtc音频降噪模块(附完整源码+测试音频文件) 单独编译和使用webrtc音频增益模块(附完整源码+测试音频文件) 说实话很不想写这篇文章,因为这和我一贯推崇的最好全部编译并使用w ...
- 单独编译和使用webrtc音频降噪模块(附完整源码+测试音频文件)
单独编译和使用webrtc音频增益模块(附完整源码+测试音频文件) 单独编译和使用webrtc音频回声消除模块(附完整源码+测试音频文件) webrtc的音频处理模块分为降噪ns,回音消除aec,回声 ...
随机推荐
- B - Avoiding a disaster
Description Percy likes to be punctual. So much so that he always keeps three watches with him, so t ...
- 在 Centos7 的KVM上启用嵌套虚拟化
1.嵌套虚拟化意味着在虚拟机内配置虚拟化环境.换句话说,我们可以说嵌套虚拟化是虚拟机管理程序hypervisor的一个特性,它允许我们通过虚拟化管理程序(宿主机)的硬件加速在虚拟服务器内安装和运行虚拟 ...
- Opencv3.4:显示一张图片
Github https://github.com/gongluck/Opencv3.4-study.git #include "opencv2/opencv.hpp" using ...
- Git清空历史,清空历史删除的文件,降低.git 文件大小
执行以下步骤之前 请做好源码备份 本操作用来清理github上面的历史删除文件,减少库的体积. 第一步骤 下载JDK环境和JAR包 https://rtyley.github.io/bfg-repo- ...
- 由VC2010与VC2017数据结构差异造成的程序错误
内容:VC2010和VC2017的标准库中,string(或wstring)的数据结构和操作有所不同,所以在将这两种数据作为参数在两个系统产生的函数中传递时会出现乱码(string和wstring在2 ...
- Linux下安装MySQL以及一些小坑
第一次写博客,各位凑合着看吧(假装有人看). 我这里使用的是centos7. 1.首先打开终端,查看有没有安装过MySQL: [root@localhost lyp]# rpm -qa | grep ...
- c# WebApi创建及客户端调用
前段时间学习WebApi的创建与调用,网上的信息千奇百怪(知识有限,看不懂啊),通过查阅资料及借鉴博友实例分析后总结一下,总结一套简单完整的WebApi创建及实例 首先创建一个WebApi服务(流程就 ...
- Python之lambda匿名函数使用if条件语句
C0LOR1 = "PapayaWhip" COLOR2 = "Tan" selectColor = lambda num: C0LOR1 if num % 2 ...
- 使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法
使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法 效果展示 一个很简单的组件脚本 运行状态在Inspector面板可以随便修改字段和调用方法 方法调用日志 设计由来 最近在 ...
- Centos Android开发环境配置-Android Tools -android list sdk --extended --all
Centos Android开发环境配置-Android Tools -android list sdk --extended --all 安装完Android Tools后执行 android ...