一、安装
npm install koa-generator -g
Koa2 koa2-test
npm install & npm run dev
二 、package.js 的配置
1、安装npm i cross-env --save-dev
2、package.js 的配置 添加 cross-env NODE_ENV=dev

"dev": "cross-env NODE_ENV=dev ./node_modules/.bin/nodemon bin/www",
 "prd": "cross-env NODE_ENV=production pm2 start bin/www",

三、安装koa-redis koa-generic-session redis 设置session
app.js相关的配置

const Koa = require('koa')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json') // post data中 json格式的处理
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')
const session = require('koa-generic-session')
const redisStore = require('koa-redis')

const index = require('./routes/index')
const users = require('./routes/users')
const blog = require('./routes/blog')
const user = require('./routes/user')

// error handler
onerror(app) // app检测 (error)检测

// middlewares 应用中间件
app.use(bodyparser({  // 处理post data上传数据的 接收很多个格式
  enableTypes:['json', 'form', 'text']
}))
app.use(json()) // 接收到很多格式之后处理成json格式
app.use(logger()) // 日志
app.use(require('koa-static')(__dirname + '/public'))

app.use(views(__dirname + '/views', {
  extension: 'pug'
}))

// logger  看当时服务请求的耗时
app.use(async (ctx, next) => {
  const start = new Date() // 记录数据来时的时间
  await next() // 再去执行其他的操作 //中间这个所花费的耗时
  const ms = new Date() - start // 再用当前的时候减去记录的时间
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})
//async返回的是一个promise对象 next是下一个中间件的函数,下个中间件也是一个异步函数格式,执行这个也是返回一个promise对象,有了await后后面加的也是个promise,这样把异步变成同步的写法

// session配置
app.keys = ['WJoli#$_23312_']
app.use(session({
    // 配置cookie
    cookie: {
        path: '/',
        httpOnly: true,
        maxAge: 24 * 60 * 60 * 1000
    },
    // 配置redis
    store: redisStore({
       // all: '127.0.0.1:6379' //先写死本地redis端口
         all: `${REDIS_CONF.host}: ${REDIS_CONF.port}`
    })
}))

// routes
app.use(index.routes(), index.allowedMethods())
app.use(users.routes(), users.allowedMethods())
app.use(blog.routes(), blog.allowedMethods())
app.use(user.routes(), user.allowedMethods())

// error-handling
app.on('error', (err, ctx) => {
  console.error('server error', err, ctx)
});

module.exports = app

日志
安装koa-morgan
创建文件夹logs 再在此文件下创建access.log
在app.js中添加以下代码

// 引用
const path = require('path')
const fs = require ('fs')
const morgan = require('koa-morgan')

// 使用
const ENV = process.env.NODE_ENV
if(ENV !== 'production') {
    // 开发环境/测试环境
    app.use(morgan('dev'))
} else {
    // 线上环境
    const logFileName = path.join(__dirname, 'logs', 'access.log')
    const writeStream = fs.createWriteStream(logFileName, {
        flags: 'a'
    })
    app.use(morgan('combined', {
        stream: writeStream // morgan 也是给予stream方式来写的,stream是写入文件提供性能很好的方式
    }))
}

如何启用线上环境查看日志

"dev": "cross-env NODE_ENV=dev ./node_modules/.bin/nodemon bin/www",
  "prd": "cross-env NODE_ENV=production ./node_modules/.bin/nodemon bin/www",

npm run prd

koa2 中间件原理
分析

  • app.use 用来注册中间件,先收集起来
  • 实现next机制,即上一个通过next触发下一个
  • 不涉及method和path的判断 因为koa里不涉及到路由就不会有get post url path

洋葱圈模型

koa2怎么接入mysql数据库 koa2安装_json

const Koa = require('koa');
const app = new Koa();
// 1 先执行logger中 的 await next()
// 2 再执行 x-response-time  中的 const start = Date.now()
// 3 再执行 x-response-time  中的  await next();
// 4 再去response 中的  ctx.body = 'Hello World';
// 5 再执行 x-response-time  中  const ms = Date.now() - start;    ctx.set('X-Response-Time', `${ms}ms`);
// 6 再执行 logger 中  const rt = ctx.response.get('X-Response-Time');  最后再打印出来
// logger 记录日志
app.use(async (ctx, next) => {
    console.log('第一层洋葱 -开始')
    await next();
    const rt = ctx.response.get('X-Response-Time');  //获取ctx刚才设置的时间差
    console.log(`${ctx.method} ${ctx.url} - ${rt}`); //最后打印出来
    console.log('第一层洋葱 -开始')
});

// x-response-time   记录请求时间
app.use(async (ctx, next) => {
    console.log('第二层洋葱 -开始')
    const start = Date.now();  // 记录时间
    await next();
    const ms = Date.now() - start;  //获取一个时间差
    ctx.set('X-Response-Time', `${ms}ms`); //将时间差设置到ctx中
    console.log('第二层洋葱 -结束')
});

// response
app.use(async ctx => {
    console.log('第三层洋葱 -开始')
    ctx.body = 'Hello World';
    console.log('第三层洋葱 -结束')
});

app.listen(5000);

打印出来的结

koa2怎么接入mysql数据库 koa2安装_redis_02

koa2的中间件代码

const http = require ('http')
// 函数,组合中间件
function compose (middlewareList) {  //传入中间的列表
    return function (ctx) {  //返回一个函数,这个函数接受一个ctx的参数
        //中间件调用的逻辑
        function dispatch (i) {
            const fn = middlewareList[i]
            try {
                return Promise.resolve(  //中间件执行封装成一个promise不管中间件写的是不是一个async函数都封装 成一个promise  (书写格式的兼容处理)
                    fn(ctx, dispatch.bind(null, i + 1))  //中间件的执行   next的机制动过dispatch.bind(null, i+1)来实现next的机制
                )
            } catch (err) {
                return Promise.reject(err)
            }
        }
        return dispatch(0)
    }
}
class LikeKoa2 {
    constructor () {
        this.middlewareList = []   //中间件要存储的地方
    }
    use (fn) {
        this.middlewareList.push(fn)  // 中间件push到fn中
        return this
    }
    createContext(req, res) {  //将req,res进行组合组合成ctx就可以
        const ctx = {
            req,
            res
        }
        ctx.query = req.query
        return ctx
    }
    handleRequest (ctx, fn) {
        return fn(ctx)
    }
    callback() {
        const fn  = compose(this.middlewareList)  //有了compose之后获取第一个中间件然后去执行
        return (req, res) => {
            const ctx = this.createContext(req, res)
            return this.handleRequest(ctx, fn)//执行的额时候传入ctx的参数
        }
    }
    listen (... args) {
        const server = http.createServer(this.callback())  //创建一个服务,并且对服务进行监听
        server.listen(... args)
    }
}
module.exports = LikeKoa2