icloudfunc
v1.0.0
Published
一个基于 Koa 的轻量级云函数框架,支持自动路由生成
Maintainers
Readme
iCloudFunc
🚀 一个基于 Koa 的轻量级云函数框架,通过环境变量配置自动扫描 functions 目录并生成路由。
English | 简体中文
✨ 核心特性
- 📁 自动路由生成 - 零配置,自动扫描
functions目录生成路由 - 🎯 统一函数入口 - 每个文件只支持一个云函数,必须使用
exports.main导出 - 🔄 HTTP 方法分发 - 在
main函数内根据ctx.method分发处理 - 🎯 动态路由支持 -
[id].js自动转换为:id动态参数 - ⚙️ 环境变量驱动 - 通过
.env文件配置所有选项 - 🛠️ 内置中间件 - Body Parser、CORS、日志、错误处理开箱即用
- 📦 开箱即用 - 一行代码启动完整的 API 服务
🎯 核心概念
通过设置环境变量,自动读取项目 functions 目录下的所有文件,自动化匹配生成路由。
只需:
- 设置环境变量指定 functions 目录
- 在目录中编写函数文件
- 框架自动扫描并生成对应的 HTTP 路由
📦 安装
npm install icloudfunc🚀 快速开始
方式一:CLI 快速创建(推荐)
# 使用 CLI 创建新项目
npx icloudfunc create my-app
# 进入项目目录
cd my-app
# 安装依赖
npm install
# 启动服务
npm start方式二:手动创建
1. 创建项目结构
my-project/
├── app.js
├── .env
└── functions/
├── hello.js
└── users.js2. 配置环境变量
创建 .env 文件:
# Functions 目录路径(必需)
FUNCTIONS_DIR=./functions
# 路由前缀(可选,默认 /api)
ROUTE_PREFIX=/api
# 服务器端口(可选,默认 3000)
PORT=3000
# Node 环境
NODE_ENV=development3. 创建入口文件
app.js
require('dotenv').config(); // 加载环境变量
const iCloudFunc = require('icloudfunc');
// 框架会自动从环境变量读取配置
const app = new iCloudFunc();
app.listen();4. 创建云函数
functions/hello.js
/**
* Hello World 云函数
* 每个文件只支持一个云函数,必须使用 exports.main
*/
exports.main = async (ctx) => {
ctx.body = {
success: true,
message: 'Hello, iCloudFunc!'
};
};functions/users.js
/**
* 用户管理云函数
* 在 main 函数内根据 HTTP 方法分发处理
*/
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
// 必须使用 exports.main 作为入口
exports.main = async (ctx) => {
const method = ctx.method;
// GET - 获取用户列表
if (method === 'GET') {
ctx.body = {
success: true,
data: users
};
return;
}
// POST - 创建用户
if (method === 'POST') {
const { name } = ctx.request.body;
const newUser = {
id: users.length + 1,
name
};
users.push(newUser);
ctx.status = 201;
ctx.body = {
success: true,
data: newUser
};
return;
}
// 其他方法
ctx.status = 405;
ctx.body = {
success: false,
error: 'Method not allowed'
};
};5. 启动服务
node app.js访问 API:
http://localhost:3000/api/hellohttp://localhost:3000/api/users
📖 详细功能
环境变量配置
框架支持以下环境变量:
| 变量名 | 说明 | 默认值 |
|--------|------|--------|
| FUNCTIONS_DIR | Functions 目录路径 | ./functions |
| ROUTE_PREFIX | API 路由前缀 | /api |
| PORT | 服务器端口 | 3000 |
| NODE_ENV | 运行环境 | development |
示例 .env 文件:
FUNCTIONS_DIR=./functions
ROUTE_PREFIX=/api
PORT=3000
NODE_ENV=development配置选项优先级
配置的优先级为:环境变量 > 构造函数参数 > 默认值
// 使用环境变量(优先级最高)
process.env.PORT = 8080;
// 使用构造函数参数
const app = new iCloudFunc({
port: 3000, // 会被环境变量覆盖
prefix: '/api'
});自动路由匹配规则
框架根据文件路径自动生成路由:
| 文件路径 | 生成路由 | 说明 |
|---------|---------|------|
| hello.js | /api/hello | 基本路由 |
| users.js | /api/users | 基本路由 |
| users/[id].js | /api/users/:id | 动态参数路由 |
| products/index.js | /api/products | index 映射到目录根 |
| api/v1/users.js | /api/api/v1/users | 嵌套路由 |
特殊规则:
index.js文件映射到其所在目录的根路径[参数名].js格式转换为:参数名动态路由- 以
_开头的文件会被忽略 *.test.js和*.spec.js测试文件会被忽略
函数导出方式
重要:每个文件只支持一个云函数,必须使用 exports.main 导出
基本用法
// functions/hello.js
exports.main = async (ctx) => {
ctx.body = { message: 'Hello' };
};路由:ALL /api/hello
处理多个 HTTP 方法
在 main 函数内根据 ctx.method 分发处理:
// functions/users.js
exports.main = async (ctx) => {
const method = ctx.method;
if (method === 'GET') {
// 处理 GET 请求
ctx.body = { users: [] };
return;
}
if (method === 'POST') {
// 处理 POST 请求
const data = ctx.request.body;
ctx.status = 201;
ctx.body = { created: true };
return;
}
if (method === 'PUT') {
// 处理 PUT 请求
ctx.body = { updated: true };
return;
}
if (method === 'DELETE') {
// 处理 DELETE 请求
ctx.body = { deleted: true };
return;
}
// 不支持的方法
ctx.status = 405;
ctx.body = { error: 'Method not allowed' };
};路由:ALL /api/users(支持所有 HTTP 方法)
动态路由
使用 [参数名].js 格式创建动态路由:
// functions/users/[id].js
exports.main = async (ctx) => {
const { id } = ctx.params; // 获取路由参数
const method = ctx.method;
if (method === 'GET') {
ctx.body = {
userId: id,
name: 'User ' + id
};
return;
}
if (method === 'DELETE') {
ctx.body = {
message: `User ${id} deleted`
};
return;
}
ctx.status = 405;
ctx.body = { error: 'Method not allowed' };
};访问:
GET /api/users/123→{ userId: '123', name: 'User 123' }DELETE /api/users/123
获取请求数据
module.exports = async (ctx) => {
// 1. 路由参数(/users/:id)
const { id } = ctx.params;
// 2. Query 参数(/users?name=john&age=20)
const { name, age } = ctx.query;
// 3. 请求体数据(POST/PUT)
const { email, password } = ctx.request.body;
// 4. 请求头
const token = ctx.headers.authorization;
// 5. 请求方法
const method = ctx.method; // GET, POST, PUT, DELETE...
};高级配置
除了环境变量,也可以在代码中配置:
const iCloudFunc = require('icloudfunc');
const app = new iCloudFunc({
// Functions 目录
functionsDir: './functions',
// 路由前缀
prefix: '/api',
// 端口
port: 3000,
// 启用日志
enableLogger: true,
// CORS 配置
cors: {
origin: '*',
methods: 'GET,POST,PUT,DELETE,OPTIONS',
headers: 'Content-Type,Authorization'
},
// 自定义中间件
middlewares: [
async (ctx, next) => {
console.log('Custom middleware');
await next();
}
]
});
app.listen();错误处理
框架内置了错误处理中间件:
module.exports = async (ctx) => {
// 手动抛出错误
if (!ctx.query.id) {
ctx.status = 400;
ctx.body = {
success: false,
error: 'ID is required'
};
return;
}
// 或使用 ctx.throw
ctx.throw(400, 'ID is required');
// 未捕获的错误会自动返回 500
throw new Error('Something went wrong');
};自定义中间件
const app = new iCloudFunc({
middlewares: [
// 认证中间件
async (ctx, next) => {
const token = ctx.headers.authorization;
if (!token) {
ctx.status = 401;
ctx.body = { error: 'Unauthorized' };
return;
}
await next();
},
// 日志中间件
async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
}
]
});🎨 项目结构示例
my-app/
├── app.js # 入口文件
├── .env # 环境变量配置
├── package.json
└── functions/ # 云函数目录(通过环境变量配置)
├── hello.js → GET/POST /api/hello
├── users.js → GET/POST /api/users
├── users/
│ └── [id].js → GET/PUT/DELETE /api/users/:id
├── products/
│ ├── index.js → GET/POST /api/products
│ └── [id].js → GET/PUT/DELETE /api/products/:id
└── admin/
└── dashboard.js → ALL /api/admin/dashboard📚 完整示例
查看 example/ 目录获取完整的示例代码:
# 运行示例
npm run example
# 或
node example/app.js🔧 开发技巧
使用 nodemon 热重载
npm install -D nodemonpackage.json
{
"scripts": {
"dev": "nodemon app.js"
}
}推荐的响应格式
// 成功响应
ctx.body = {
success: true,
data: { /* 数据 */ },
message: 'Success'
};
// 错误响应
ctx.status = 400;
ctx.body = {
success: false,
error: 'Error message',
code: 'ERROR_CODE'
};📝 发布到 npm
# 1. 登录 npm
npm login
# 2. 发布包
npm publish
# 3. 更新版本
npm version patch # 1.0.0 -> 1.0.1
npm version minor # 1.0.0 -> 1.1.0
npm version major # 1.0.0 -> 2.0.0
# 4. 发布新版本
npm publish详细发布指南请查看 PUBLISH.md
🆘 常见问题
Q: 如何自定义 functions 目录位置?
A: 在 .env 文件中设置:
FUNCTIONS_DIR=./my-custom-functions或在代码中配置:
new iCloudFunc({
functionsDir: './my-custom-functions'
}).listen();Q: 如何修改路由前缀?
A: 在 .env 文件中设置:
ROUTE_PREFIX=/v1Q: 如何启用 CORS?
A:
new iCloudFunc({
cors: {
origin: '*', // 或指定域名
methods: 'GET,POST,PUT,DELETE,OPTIONS'
}
}).listen();Q: 如何访问原始 Koa 实例?
A:
const app = new iCloudFunc();
const koaApp = app.getApp();
// 添加自定义中间件
koaApp.use(async (ctx, next) => {
// 你的逻辑
await next();
});
app.listen();🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可证
MIT
🙏 致谢
基于 Koa 构建
