一、需求

手动实现一个 Koa2 的中间件,用以完成基本的路由加载功能。

只考虑 GET 请求方式加载静态 HTML 页面。

中间件或异步操作均使用 async/await 实现。

代码结构:

|- middlewares
    - log.js
    - router.js
|- views
    - index.html
    - login.html
    - 404.html
|- app.js

二、实现

1、HTML文件内容异步读取

代码路径 middleware/router.js

const fs = require('fs');
const path = require('path');

// 读取页面文件内容 注意 toString()
function render(url) {
  return new Promise((resolve,reject)=>{
    fs.readFile(path.resolve(`./views/${url}`),(err,res)=>{
      if(err) reject(err);
      resolve(res.toString());
    });
  });
}

2、路由中间件方法

代码路径 middleware/router.js

async function route(url){
    let view = '404.html';
    switch(url){
        case '/': view = 'index.html';break;
        case '/index' : view = 'index.html';break;
        case '/login' : view = 'login.html';break;
        case '/404': view = '404.html';
        default :break;
    }
    // 读取 html 内容,并且返回
    const html = await render(view);
    return html;
}

3、导出中间件

代码路径 middleware/router.js

module.exports = () => {
    return async (ctx,next) => {
        const url = ctx.request.url;
        // 调用路由中间件方法
        const html = await route(url);
        ctx.page = {html};
        next();
    }
}

三、使用中间件

代码路径 router.js

const Koa = require('koa');
const app = new Koa();

const logMiddleware = require('./middlewares/log');
const routerMiddleware = require('./middlewares/router');
 
app.use(logMiddleware()); 
app.use(routerMiddleware());

app.use(async (ctx)=>{
   ctx.body = ctx.page.html;
}); 
 
app.listen(3000); 

四、效果

1、首页

1.jpg

2、登录页

2.jpg

3、404

3.jpg