fastify-autoload + ncc + s3 实现模块的插件化开发加载

发布时间 2023-10-17 13:30:22作者: 荣锋亮

以前简单说明过基于fastify-autoload 的插件化加载fastify插件,方便实现开发,但是对于实际生产环境我们可以需要频繁的模块修改,发布以及构建,所以需要我们需要频繁的调整,不是很方便,我们可以基于ncc 进行入口的打包,同时对于每个插件也基于ncc 打包为独立的文件,这样我们开发的插件只需要基于ci/cd 构建之后放到s3中,然后reload 服务就可以了

参考集成

 


简单说明: 基于fastify-autoload 加载插件,但是存储的存储基于ci/cd 直接可以存储到s3 中,对于运行示例基于juicefs 或者mountpoint-s3 进行
s3 数据的挂载,这样数据就是动态的

项目结构

  • 参考结构
 
├── Dockerfile
├── README.md
├── app-restart.js
├── app.js
├── config.js
├── docker-compose.yaml
├── package.json
├── plugins
├── apps
└── app.js
├── home
└── app.js
├── init
└── app.js
├── login
└── app.js
└── users
└── app.js
├── tsup.config.js
└── yarn.lock

代码简单说明

  • pacakge.json
{
  "name": "fastify-autoload-app",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "@fastify/autoload": "^5.7.1",
    "@fastify/restartable": "^2.1.1",
    "dotenv": "^16.3.1",
    "fastify": "^4.24.0",
    "fastify-plugin": "^4.5.1",
    "hashids": "^2.3.0"
  },
  "scripts": {
    "plugin-build": "ncc build app.js -o dist ",
    "plugin-app": "ncc build plugins/apps/app.js  -o distapp/plugins/apps",
    "plugin-init": "ncc build plugins/init/app.js  -o distapp/plugins/init",
    "plugin-home": "ncc build plugins/home/app.js  -o distapp/plugins/home",
    "plugin-users": "ncc build plugins/users/app.js  -o distapp/plugins/users",
    "plugin-login": "ncc build plugins/login/app.js  -o distapp/plugins/login",
    "tsup": "tsup app.js -d distv2",
    "myplugin-build": "concurrently  'yarn:plugin-*'"
  },
  "devDependencies": {
    "@vercel/ncc": "^0.38.0",
    "concurrently": "^8.2.1",
    "tsup": "^7.2.0"
  }
}
  • app.js
    应用的入口
 
require('dotenv').config()
const Fastify = require('fastify')
const path = require("path")
const autoLoad = require('@fastify/autoload');
const config = require('./config')
 
const app = Fastify({
    logger: true,
    ignoreDuplicateSlashes: true,
}
);
// 加载插件
app.register(autoLoad, {
    dir: path.join(__dirname, config.pluginPath)
})
app.listen({
    port: 3000,
    host: '0.0.0.0',
    backlog: 511
}, (err, address) => {
    if (err) {
        console.log(err)
        process.exit(1)
    } else {
        console.log(`Server listening on ${address}`)
    }
})
  • 插件开发
    就是一个标注的基于fastify-plugin的包装,主要说明一个简单的login,其他的类似
 
const fp = require('fastify-plugin')
function login(fastify, opts, done) {
    fastify.get("/login", async (req, res) => {
        res.send({
            version:"v3333",
            login:"login"
        })
    })
    done()
}
module.exports = fp(login, {
    name: "login"
})
  • docker 运行
    Dockerfile 主要包含了入口
 
FROM  node:18.18.2-buster-slim
WORKDIR /app
ENTRYPOINT [ "node","index.js" ]

docker-compose 文件

version: "3"
services:
  app:
    build: ./
    volumes:
      - ./dist:/app/
      - ./distapp:/app/plugins
    env_file:
      - ./.env
    ports:
      - "3000:3000"

构建之后的效果

对于多个插件的构建基于了concurrently,当然基于tsup 也是一种可选的方式,基本上类似

说明

此处基于s3 的插件加载实际上可以使用类似文件系统扩展的包,目前已经有一些底层使用s3 但是可以暴露为标注node fs 操作的包
但是比较稳定的似乎不是很好,对于我们新开发的插件直接基于标准开发,然后使用ncc 包装为一个单一文件,之后reload 服务就
可以生效了,还是很方便的,至少对于很多环境我们需要使用npm 包,但是网络不是很方便的是否很简单了不少,目前此方式是有
一些缺陷,相同的npm 包会有多个,同时可能会造成文件比较大,当然基于ncc 的集成模式实际上也是实现了一种简单的多版本包
如果能实现类似webpack module federation 的能力,就更加方便了

参考资料

https://github.com/vercel/ncc
https://github.com/fastify/fastify-autoload
https://github.com/fastify/fastify-plugin
https://github.com/awslabs/mountpoint-s3
https://github.com/juicedata/juicefs
https://github.com/rongfengliang/fastify-autoload_ncc_pacakge