IGA Pages Functions 是 IGA Pages 平台提供的基于文件系统的 Node.js Serverless Functions 能力。开发者只需在项目根目录下创建 api/ 目录,并在其中放置 .js 文件,即可将每个文件自动映射为一条可公开访问的 HTTP 路由,整个过程无需编写路由配置文件,也无需手动注册路由表。
IGA Pages Functions 的设计理念是"约定优于配置":文件的存放路径决定了对外暴露的 URL 路径,函数的导出方式决定了请求的处理逻辑。这种方式显著降低了搭建后端 API 服务的门槛,使前端开发者也能快速构建轻量级的服务端接口。
核心特性:
只需两步即可在本地运行第一个 Function,验证整个开发流程。
创建 Function 文件。
在项目根目录下新建 api/hello.js 文件,写入以下内容。该函数处理 GET 请求,返回一段 JSON 格式的问候信息:
export async function GET(request) { return Response.json({ message: "Hello from IGA Pages!" }); }
启动本地开发服务。
首先安装 IGA Pages 命令行工具,然后启动本地开发服务器:
npm install -g @iga-pages/cli iga pages dev
服务启动后,在浏览器或任意 HTTP 客户端中访问 http://localhost:5173/api/hello,即可看到如下 JSON 响应:
{ "message": "Hello from IGA Pages Express Backend!", "timestamp": "......" }
至此,你已经成功创建并运行了第一个 IGA Pages Function。
说明
关于 CLI 的完整命令列表、参数说明及高级用法,请参见IGA Pages CLI 使用手册。
IGA Pages Functions 的路由系统完全基于文件系统驱动,api/ 目录下的文件夹层级和文件名直接决定了对外暴露的 URL 路径结构。开发者无需维护独立的路由配置文件,只要合理组织文件结构,即可自动生成清晰的 API 路由。
以下是一个典型的项目目录结构,以及每个文件对应的 HTTP 路由路径:
api/ ├── index.js → /api ├── hello.js → /api/hello ├── users/ │ ├── list.js → /api/users/list │ └── [id].js → /api/users/:id ├── [id].js → /api/:id ├── group/ │ └── [id]/ │ └── detail.js → /api/group/:id/detail └── [[default]].js → /api/:default*
可以看到,文件的嵌套层级与 URL 的路径层级完全一致。文件夹名称构成路径中的固定片段,而使用方括号包裹的文件名或文件夹名则构成动态参数片段。
IGA Pages Functions 支持三种路由类型,它们的命名规则和匹配行为各不相同:
路由类型 | 文件命名格式 | 匹配行为 | 典型用途 | 示例 |
|---|---|---|---|---|
静态路由 |
| 精确匹配固定路径,路径中不包含可变部分 | 获取固定资源列表、健康检查等 |
|
动态路由 |
| 匹配单层路径片段,该片段作为必填参数捕获 | 按 ID 获取单个资源 |
|
Catch-all 路由 |
| 匹配零个或任意多个剩余路径片段 | 代理转发、框架集成等兜底场景 |
|
补充说明:
/api/hello 与 /api/hello/ 在路由匹配时视为等价,两者均会命中 api/hello.js。[param] 要求请求路径中必须包含对应的路径片段。例如 api/users/[id].js 不会匹配 /api/users,因为缺少 id 参数。[[param]] 路由可以匹配空路径,也可以匹配任意深度的路径,因此非常适合作为兜底路由使用,常用于框架集成场景。当一个请求路径可能同时匹配多条路由规则时,IGA Pages 按照以下优先级从高到低依次尝试匹配。一旦命中,即停止后续匹配:
这一优先级设计确保了路由行为的可预测性:具体的路由总是优先于模糊的路由。
下表基于路由规则中的目录结构,列出了各种请求路径的匹配结果,帮助开发者直观理解路由匹配逻辑:
请求路径 | 匹配文件 | 路由类型 |
|
|---|---|---|---|
|
| 静态 | — |
|
| 静态 | — |
|
| 静态 | — |
|
| 动态 |
|
|
| 动态 |
|
|
| 动态 |
|
|
| Catch-all |
|
|
| Catch-all |
|
Function Handler 是 IGA Pages Functions 的核心概念。每个 .js 文件通过导出函数来定义请求处理逻辑。IGA Pages 运行时在接收到 HTTP 请求后,根据路由规则定位到目标文件,并调用其导出的处理函数。
最基础的方式是使用 export default 导出一个异步处理函数,该函数接收 request 和 response 两个参数,分别代表当前请求的上下文和响应控制器:
export default async function handler(request, response) { response.json({ message: "Hello, IGA!" }); }
request 对象在 Node.js 标准 IncomingMessage 的基础上进行了扩展,内置了常用的请求数据解析功能,开发者无需手动引入第三方中间件即可直接使用:
属性 | 类型 | 说明 | 使用示例 |
|---|---|---|---|
|
| URL 中的查询参数,自动解析为键值对对象 | 请求 |
|
| 动态路由中的路径参数,由路由匹配引擎自动注入 | 请求 |
|
| 请求携带的 Cookie,解析为键值对对象 | 若请求头包含 |
|
| 请求体内容,运行时根据 | 对于 |
使用示例:
export default async function handler(request, response) { // 获取动态路由参数 const { id } = request.params; // 获取查询字符串参数,提供默认值 const { page = "1", size = "10" } = request.query; response.json({ userId: id, page: Number(page), size: Number(size), }); }
response 对象在 Node.js 标准 ServerResponse 的基础上扩展了一组便捷方法,简化了常见的响应操作。其中 status() 方法支持链式调用,可以与其他响应方法组合使用:
方法 | 说明 | 使用示例 |
|---|---|---|
| 设置 HTTP 响应状态码,返回 |
|
| 将数据序列化为 JSON 并返回,自动设置 |
|
| 通用响应方法,根据传入数据类型自动推断 |
|
| 执行 HTTP 307 临时重定向,将客户端引导至新 URL |
|
| 执行指定状态码的重定向,适用于 301 永久重定向等场景 |
|
错误处理示例:
export default async function handler(request, response) { if (!request.query.token) { return response.status(401).json({ error: "Unauthorized" }); } if (request.params.id === undefined) { return response.status(400).json({ error: "Missing required parameter: id" }); } response.json({ data: "secret content" }); }
对于已有 Express 或 Koa 项目的开发者,IGA Pages Functions 支持将整个框架应用实例直接作为 Serverless Function 部署。框架内部定义的所有路由集中在一个 Function 文件中处理,由 IGA Pages 运行时负责网络层的管理,开发者无需自行启动 HTTP Server。
关于框架集成的完整配置细节和进阶用法,请参见IGA Pages 框架指南。
在进行框架集成时,必须严格遵守以下三项约束,否则部署可能失败或路由无法正确匹配:
约束项 | 具体要求 | 原因说明 |
|---|---|---|
使用 Catch-all 路由文件 | 文件必须命名为 | 框架需要接管所有入站请求,Catch-all 路由确保任意路径都能被转发到框架实例 |
禁止调用 listen | 不要在代码中调用 | IGA Pages 运行时自动处理端口监听和网络层,重复监听会导致端口冲突或部署失败 |
导出应用实例 | 必须通过 | 运行时需要获取应用实例以注入请求,未导出会导致函数无法正常响应 |
以下示例展示了如何在 IGA Pages Functions 中运行一个 Express 应用:
// api/[[default]].js import express from "express"; const app = express(); app.use(express.json()); app.get("/api/hello", (req, res) => { res.json({ message: "Hello from Express on IGA Pages!" }); }); app.post("/api/users", (req, res) => { const { name } = req.body; res.status(201).json({ created: true, name }); }); // 重要:不要调用 app.listen(),直接导出应用实例 export default app;
以下示例展示了如何在 IGA Pages Functions 中运行一个 Koa 应用:
// api/[[default]].js import Koa from "koa"; import Router from "@koa/router"; const app = new Koa(); const router = new Router(); router.get("/api/hello", (ctx) => { ctx.body = { message: "Hello from Koa on IGA Pages!" }; }); router.post("/api/users", (ctx) => { ctx.status = 201; ctx.body = { created: true }; }); app.use(router.routes()); app.use(router.allowedMethods()); // 重要:不要调用 app.listen(),直接导出应用实例 export default app;