源码阅读的提前准备
什么时候进行源码阅读 除了一定的编程基础之外,应对该项目具有一定的理解,知道该以什么样的方案解决什么问题。 在github仓库的地址上github后面加上 1s 可以在网页上利用vscode查看源码,支持快捷方式文件跳转,全局搜索等。
例如:https://github1s.com/nodejs/node/blob/HEAD/benchmark/es/defaultparams-bench.js
推荐学习网站:
怎么进行源码阅读
入口
对于js项目,可以直接从package.json的main、bin字段入手入口, 亦可参考files字段。
tip: 对于Monorepo则需要从编译工具入手。
node_modules里面
对应无须编译的项目,可直接在node_modules文件夹里面查看,推荐使用vscode 插件,Search node_modules 来搜索打开项目。
下载github源码查看
对于需要编译的项目,如React、vue组件库或者基于ts等项目,推荐下载github到本地,按照 CONTRIBUTING.md 的指引来开始。
koa是什么,解决了什么问题
koa仅仅只是web框架,真正成熟的企业级的框架可以参考eggjs、thinkjs。koa与eggjs的关系,可大致 类比 react与umijs的关系。 本文仅介绍koa的2.x。
大致过一遍
koa入口文件,为lib/application,Koa type github链接
const app = new Koa()
koa关键点:
- middleware koa洋葱模型
- context,上下文
- onerror, 错误处理
洋葱模型
洋葱模型示意图
洋葱模型中间件示意图
DOM事件流
可以将server的request 可类比于 DOM的click事件。可以将 next(); 之前的任意代码视为“捕获”阶段,之后为冒泡。
中间件执行顺序
- 创建一个跟踪响应时间的日期
- 等待下一个中间件的控制
- 创建另一个日期跟踪持续时间
- 等待下一个中间件的控制
- 将响应主体设置为“Hello World”
- 计算持续时间
- 输出日志行
- 计算响应时间
- 设置
X-Response-Time头字段- 交给 Koa 处理响应
koa-compose的源码
函数调研堆栈
developer.mozilla.org/zh-CN/docs/…
compose含义
redux compose源码
// 中间件签名 见applyMiddleware.ts
// 核心之applyMiddleware.ts
funcs.reduce((a, b) => (...args: any) => a(b(...args)))
const middlewareAPI: MiddlewareAPI = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
// 核心之compose.ts
dispatch = compose<typeof dispatch>(...chain)(store.dispatch)
koa compose源码链接
https://github.com/koajs/compose/blob/master/index.js
// 中间件签名
async (ctx, next) => {}
// 可简单理解为:用户代码也为最深处的中间件
// 核心
Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
上下文
只有一点,将示例作为属性挂在ctx上,没啥特殊的。delegates 包就是属性劫持。 Object.create(proto),创建一个空对象,其__proto__为proto。
createContext(req, res) {
const context = Object.create(this.context);
const request = context.request = Object.create(this.request);
const response = context.response = Object.create(this.response);
context.app = request.app = response.app = this;
context.req = request.req = response.req = req;
context.res = request.res = response.res = res;
request.ctx = response.ctx = context;
request.response = response;
response.request = request;
context.originalUrl = request.originalUrl = req.url;
context.state = {};
return context;
}
错误处理
ctx.onerror
中间件中的错误捕获, 处理请求 中间件的错误可以被app级别的onerror捕获, this.app.emit('error', err, this); github.com/koajs/koa/b…
默认onerror
github.com/koajs/koa/b… github.com/koajs/koa/b…
自定义onerror
class Application extends Emitter app.on('error', (err) => {})
More
co...