Express框架实现原理

一、Express 源码的目录结构

在这里插入图片描述
首先,会去package.json项目(包)描述文件中寻找main属性的值,
main:入口文件。这个main的值就是入口文件所在的路径。
在这里插入图片描述

这里并没有配置main属性的值,默认会去找index.js文件作为入口文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

二、快速体验

在这里插入图片描述
在这里插入图片描述

const http = require('http')
const url = require('url')
const routes = [/*{ path: '', method: '', handler: () => {} }*/]
function createApplication() {
    return {
        get (path, handler) {
            routes.push({
                path,
                method: 'get',
                handler
            })
        },
        listen (...args) {
            const server = http.createServer((req, res) => {
                const { pathname } = url.parse(req.url)
                const method = req.method.toLowerCase()
                const route = routes.find(route => route.path === pathname && route.method === method)
                if (route) {
                    return route.handler(req, res)
                }
                res.end('404 Not Found.')
            })
            server.listen(...args)
        }
    }
}
module.exports = createApplication

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、抽取App模块

在这里插入图片描述

在这里插入图片描述

const http = require('http')
const url = require('url')
function App() {
    this.routes = []
}
// const routes = [/*{ path: '', method: '', handler: () => {} }*/]
App.prototype.get = function (path, handler) {
    this.routes.push({
        path,
        method: 'get',
        handler
    })
}
App.prototype.listen = function (...args) {
    const server = http.createServer((req, res) => {
        const {pathname} = url.parse(req.url)
        const method = req.method.toLowerCase()
        const route = this.routes.find(route => route.path === pathname && route.method === method)
        if (route) {
            return route.handler(req, res)
        }
        res.end('404 Not Found.')
    })
    server.listen(...args)

}
module.exports = App

四、提取路由模块

在这里插入图片描述

const url = require('url')

let Router = function Router() {
    this.stack = []
}

Router.prototype.get = function(path, handler){
    this.stack.push({
        path,
        method: 'get',
        handler
    })
}
Router.prototype.handle = function(req, res){
    const {pathname} = url.parse(req.url)
    const method = req.method.toLowerCase()
    const route = this.stack.find(route => route.path === pathname && route.method === method)
    if (route) {
        return route.handler(req, res)
    }

    res.end('404 Not Found.')
}
module.exports = Router

在这里插入图片描述

const http = require('http')
const Router = require('./router/index.js')
let App = function App() {
    this._router = new Router()
}
// 把路由收集起来
App.prototype.get = function (path, handler) {
    this._router.get(path, handler)
}
App.prototype.listen = function (...args) {
    const server = http.createServer((req, res) => {
        this._router.handle(req, res)
    })
    server.listen(...args)
}
module.exports = App

五、处理不同的请求方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、更强大的路由路径匹配模式(基本实现)

在这里插入图片描述
在这里插入图片描述

const url = require('url')
const methods = require('methods')
const pathRegexp = require('path-to-regexp')
let Router = function Router() {
    this.stack = []
}
methods.forEach(method => {
    // Router.prototype.get = function(path, handler){
    Router.prototype[method] = function(path, handler){
        this.stack.push({
            path,
            method,
            handler
        })
    }
})
Router.prototype.handle = function(req, res){
    const {pathname} = url.parse(req.url)
    const method = req.method.toLowerCase()
    const route = this.stack.find(route => {
        const keys = []
        const regexp = pathRegexp(route.path, keys, {})
        const match = regexp.exec(pathname)
        return match && route.method === method
    })
    if (route) {
        return route.handler(req, res)
    }
    res.end('404 Not Found.')
}
module.exports = Router

七、处理动态路由路径参数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

const url = require('url')
const methods = require('methods')
const pathRegexp = require('path-to-regexp')
let Router = function Router() {
    this.stack = []
}
methods.forEach(method => {
    // Router.prototype.get = function(path, handler){
    Router.prototype[method] = function(path, handler){
        this.stack.push({
            path,
            method,
            handler
        })
    }
})
Router.prototype.handle = function(req, res){
    const {pathname} = url.parse(req.url)
    const method = req.method.toLowerCase()
    const route = this.stack.find(route => {
        const keys = []
        const regexp = pathRegexp(route.path, keys, {})
        const match = regexp.exec(pathname)
        console.log('keys=>', keys)
        console.log('match=>', match)
        if (match) {
            req.params = req.params || {}
            keys.forEach((key, index) => {
                req.params[key.name] = match[index + 1]
            })
        }
        return match && route.method === method
    })
    if (route) {
        return route.handler(req, res)
    }
    res.end('404 Not Found.')
}
module.exports = Router

八、提取Layer处理模块

在这里插入图片描述
在这里插入图片描述

const url = require('url')
const methods = require('methods')
const Layer = require('./layer.js')
let Router = function Router() {
    this.stack = []
}
methods.forEach(method => {
    // Router.prototype.get = function(path, handler){
    Router.prototype[method] = function(path, handler){
        const layer = new Layer(path ,handler)
        layer.method = method
        this.stack.push(layer)
    }
})
Router.prototype.handle = function(req, res){
    const {pathname} = url.parse(req.url)
    const method = req.method.toLowerCase()
    const route = this.stack.find(layer => {
        const match = layer.match(pathname)
        if(match) {
            req.params = req.params || {}
            Object.assign(req.params, layer.params)
        }
        return match && layer.method === method
    })
    if (route) {
        return route.handler(req, res)
    }
    res.end('404 Not Found.')
}
module.exports = Router

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值