我用nodejs实现了热加载接口文件,感觉又离“serverless”进了一步

68 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

背景

serverless很火,但是很多文章概念多实践少,也不适合个人开发者来玩耍。固然和硬件设备绑定,有完善生态的severless才有大的商业价值。但是个人想要试一下serverless总没有问题吧,结果看了一堆文章实现复杂,难以快速搭建落地。所以我准备自己搞一个serverless版本。

目标

  • 云函数可以快速部署。
  • 一个服务可以多个云函数。
  • 接口式访问。

设计思路

一个云函数形成一个nodejs文件,服务端动态加载这些nodejs,访问文件对应的接口,就返回该云函数的运行结果。

工具库 与 实现

框架选择 koa

新建一个名字叫serverless的文件夹,然后进入文件夹后执行以下

npm init -y
npm i koa

库介绍

koa 与 koa-body

koa 是一个简单nodejs服务端框架,封装了nodejs的一些基础api,可以让你上手更快

koa-body 是一个基于koa,用于处理用户传入信息(Class: http.IncomingMessage)的库。IncomingMessage 又继承了 stream。而在koa中req是基于incomingMessage的再次封装。而一般业务逻辑中,我们不需要对流进行特别的处理,建议强烈建议使用 koa-body,来避免自己直接处理 IncomingMessage。

const Koa = require('koa');
const app = new Koa();
const koaBody = require('koa-body');
app.use(koaBody())

function test(ctx) {
    console.log(ctx.request.body);
    // => POST body
    ctx.body = JSON.stringify(ctx.request.body);
}

app.use(test);

app.listen(3000);


glob 支持以某种规则读取目录下指定的文件

var glob = require("glob")

// options is optional
glob("**/*.js", options, function (er, files) {
  // files is an array of filenames.
  // If the `nonull` option is set, and nothing
  // was found, then files is ["**/*.js"]
  // er is an error object or null.
})

koa-router koa 的路由器中间件

实现热加载

目录结构

serverless
  ├─app.js
  ├─middleware
  │    ├─get
  │    │    └─test.js
  │    └─post
  ├─package-lock.json
  └─package.json
  
var Koa = require('koa');
var Router = require('koa-router');

var app = new Koa();
var router = new Router();

router.get('/', (ctx, next) => {
  // ctx.router available
});

app
  .use(router.routes())
  .use(router.allowedMethods());
  
const path = require('path');
const Koa = require('koa');
const route = require("koa-route");
const koaBody = require("koa-body");
const glob = require('glob');
const app = new Koa();

app.use(
    koaBody({
        jsonLimit: '50mb',
    })
);

// ----------------



setPostApi()

// 定时加载 接口文件
setInterval(() => {
    console.log('first')
    setPostApi()

}, 10000);
function json(ctx) {
    return function (jn) {
        ctx.body = JSON.stringify(jn)
    }
}

function addJsonApi(fn) {

    return async function (ctx) {
        const { request, res } = ctx
        request.cookies = {
            'principal_dev': ctx.cookies.get('principal_dev')
        }
        res.json = json(ctx)
        await fn(request, res)
    }
}
function setPostApi() {


    let fileList = glob.sync(path.join(__dirname, './middleware/post/*.js'));
    fileList.map((file) => {
        const { reg, fn } = require(file)
        app.use(route.post(reg, addJsonApi(fn)));
    });
    fileList = glob.sync(path.join(__dirname, './middleware/get/*.js'));
    fileList.map((file) => {
        const { reg, fn } = require(file)
        app.use(route.get(reg, addJsonApi(fn)));
    });
}


app.listen(3000);

test.js 文件 内容


function aaaaa(req,res) {
    res.json('ccccccc')
}

module.exports = {
    reg: /test*/,
    fn:aaaaa
}