Serverless Functions #
什么是 Serverless Functions? #
Serverless Functions 是无需管理服务器即可运行后端代码的服务。Netlify 基于 AWS Lambda 提供函数托管。
text
HTTP 请求 → Netlify Function → 执行代码 → 返回响应
优势 #
| 优势 | 说明 |
|---|---|
| 无服务器管理 | 专注代码,无需运维 |
| 自动扩展 | 根据请求量自动伸缩 |
| 按需计费 | 只为实际执行付费 |
| 全球部署 | 边缘节点执行 |
快速开始 #
创建函数目录 #
text
项目根目录/
├── netlify/
│ └── functions/
│ └── hello.js
├── netlify.toml
└── package.json
第一个函数 #
javascript
// netlify/functions/hello.js
exports.handler = async (event, context) => {
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: 'Hello World!'
})
}
}
访问函数 #
text
https://your-site.netlify.app/.netlify/functions/hello
函数配置 #
netlify.toml 配置 #
toml
[build]
command = "npm run build"
publish = "dist"
functions = "netlify/functions"
[functions]
directory = "netlify/functions"
node_bundler = "esbuild"
函数目录结构 #
text
netlify/functions/
├── hello.js # 单文件函数
├── api/
│ ├── users.js # /api/users
│ └── posts.js # /api/posts
└── complex/
├── index.js # 函数入口
├── utils.js # 辅助模块
└── package.json # 依赖
函数签名 #
基本结构 #
javascript
exports.handler = async (event, context) => {
// event: 请求信息
// context: 运行时上下文
return {
statusCode: 200,
headers: {},
body: ''
}
}
Event 对象 #
javascript
{
"httpMethod": "POST",
"path": "/api/users",
"queryStringParameters": {
"page": "1"
},
"headers": {
"content-type": "application/json",
"authorization": "Bearer xxx"
},
"body": "{\"name\":\"张三\"}",
"isBase64Encoded": false
}
Context 对象 #
javascript
{
"awsRequestId": "xxx",
"logGroupName": "/aws/lambda/xxx",
"functionName": "xxx",
"functionVersion": "$LATEST",
"identity": {}, // 用户身份信息
"user": {} // Netlify Identity 用户
}
处理请求 #
GET 请求 #
javascript
exports.handler = async (event) => {
const { page = 1, limit = 10 } = event.queryStringParameters || {}
const users = await getUsers(page, limit)
return {
statusCode: 200,
body: JSON.stringify({ users })
}
}
POST 请求 #
javascript
exports.handler = async (event) => {
if (event.httpMethod !== 'POST') {
return { statusCode: 405, body: 'Method Not Allowed' }
}
const data = JSON.parse(event.body)
const user = await createUser(data)
return {
statusCode: 201,
body: JSON.stringify(user)
}
}
处理文件上传 #
javascript
exports.handler = async (event) => {
if (!event.isBase64Encoded) {
return { statusCode: 400, body: 'Invalid content' }
}
const fileBuffer = Buffer.from(event.body, 'base64')
const contentType = event.headers['content-type']
// 处理文件...
return {
statusCode: 200,
body: JSON.stringify({ success: true })
}
}
响应格式 #
成功响应 #
javascript
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({
success: true,
data: {}
})
}
错误响应 #
javascript
return {
statusCode: 400,
body: JSON.stringify({
success: false,
error: 'Invalid request'
})
}
重定向 #
javascript
return {
statusCode: 302,
headers: {
Location: 'https://example.com'
},
body: ''
}
环境变量 #
访问环境变量 #
javascript
exports.handler = async (event) => {
const apiKey = process.env.API_KEY
const dbUrl = process.env.DATABASE_URL
// 使用环境变量...
}
配置环境变量 #
toml
[build.environment]
API_KEY = "your-api-key"
[context.production.environment]
DATABASE_URL = "postgres://..."
数据库操作 #
连接数据库 #
javascript
const { Pool } = require('pg')
let pool
const getPool = () => {
if (!pool) {
pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: { rejectUnauthorized: false }
})
}
return pool
}
exports.handler = async (event) => {
const pool = getPool()
const result = await pool.query('SELECT * FROM users')
return {
statusCode: 200,
body: JSON.stringify(result.rows)
}
}
使用 MongoDB #
javascript
const { MongoClient } = require('mongodb')
let client
const getClient = async () => {
if (!client) {
client = new MongoClient(process.env.MONGODB_URI)
await client.connect()
}
return client
}
exports.handler = async (event) => {
const client = await getClient()
const db = client.db('mydb')
const users = await db.collection('users').find({}).toArray()
return {
statusCode: 200,
body: JSON.stringify(users)
}
}
外部 API 调用 #
GET 请求 #
javascript
exports.handler = async (event) => {
const response = await fetch('https://api.example.com/users', {
headers: {
'Authorization': `Bearer ${process.env.API_KEY}`
}
})
const data = await response.json()
return {
statusCode: 200,
body: JSON.stringify(data)
}
}
POST 请求 #
javascript
exports.handler = async (event) => {
const body = JSON.parse(event.body)
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.API_KEY}`
},
body: JSON.stringify(body)
})
const data = await response.json()
return {
statusCode: 201,
body: JSON.stringify(data)
}
}
TypeScript 支持 #
配置 #
toml
[functions]
directory = "netlify/functions"
node_bundler = "esbuild"
TypeScript 函数 #
typescript
// netlify/functions/hello.ts
import { Handler } from '@netlify/functions'
interface Response {
message: string
timestamp: number
}
export const handler: Handler = async (event, context) => {
const response: Response = {
message: 'Hello World!',
timestamp: Date.now()
}
return {
statusCode: 200,
body: JSON.stringify(response)
}
}
本地开发 #
启动本地开发服务器 #
bash
netlify dev
访问本地函数 #
text
http://localhost:8888/.netlify/functions/hello
调试函数 #
javascript
exports.handler = async (event) => {
console.log('Event:', JSON.stringify(event, null, 2))
// 你的代码...
}
查看日志:
bash
netlify dev
函数日志 #
查看日志 #
text
Site overview → Functions → 选择函数 → Logs
CLI 查看日志 #
bash
netlify functions:log hello
定时函数 #
配置定时触发 #
toml
[functions."scheduled-task"]
schedule = "0 0 * * *"
定时函数示例 #
javascript
// netlify/functions/scheduled-task.js
exports.handler = async (event) => {
console.log('定时任务执行:', new Date().toISOString())
// 执行定时任务...
return {
statusCode: 200,
body: 'OK'
}
}
Cron 表达式 #
| 表达式 | 说明 |
|---|---|
0 0 * * * |
每天 0 点 |
0 */6 * * * |
每 6 小时 |
0 0 * * 0 |
每周日 0 点 |
0 0 1 * * |
每月 1 日 0 点 |
函数限制 #
执行限制 #
| 限制项 | 免费方案 | Pro 方案 |
|---|---|---|
| 执行时间 | 10 秒 | 26 秒 |
| 内存 | 1024 MB | 1024 MB |
| 包大小 | 50 MB | 50 MB |
调用限制 #
| 限制项 | 免费方案 | Pro 方案 |
|---|---|---|
| 每月调用 | 125,000 | 2,000,000 |
最佳实践 #
1. 复用连接 #
javascript
// 好的做法:复用数据库连接
let connection
const getConnection = async () => {
if (!connection) {
connection = await createConnection()
}
return connection
}
2. 错误处理 #
javascript
exports.handler = async (event) => {
try {
// 业务逻辑
return { statusCode: 200, body: 'OK' }
} catch (error) {
console.error('Error:', error)
return {
statusCode: 500,
body: JSON.stringify({ error: 'Internal Server Error' })
}
}
}
3. 输入验证 #
javascript
exports.handler = async (event) => {
if (event.httpMethod !== 'POST') {
return { statusCode: 405, body: 'Method Not Allowed' }
}
let body
try {
body = JSON.parse(event.body)
} catch {
return { statusCode: 400, body: 'Invalid JSON' }
}
if (!body.name) {
return { statusCode: 400, body: 'Name is required' }
}
// 处理请求...
}
4. CORS 处理 #
javascript
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS'
}
exports.handler = async (event) => {
if (event.httpMethod === 'OPTIONS') {
return { statusCode: 200, headers, body: '' }
}
return {
statusCode: 200,
headers,
body: JSON.stringify({ message: 'OK' })
}
}
下一步 #
掌握了 Serverless Functions 后,继续学习 重定向规则 了解 URL 重定向配置!
最后更新:2026-03-28