Serverless实战:从入门到项目落地的完整指南
先跑个函数再说
说实话,我第一次接触 Serverless 时,脑子里全是“这玩意儿到底能干啥”。文档看了半天,不如直接上手写个函数。所以今天咱们不扯概念,先搞个能跑的。
我用的是 Vercel(部署快、免费额度够用),你也可以用 AWS Lambda、阿里云函数计算,但 Vercel 对前端开发者最友好——写个 API 路由,git push 就自动部署了。
假设你有个 Next.js 项目(没的话新建一个也行),在 pages/api/hello.js 里写:
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from Serverless!' });
}
本地 npm run dev,访问 http://localhost:3000/api/hello,看到 JSON 就说明本地跑通了。接着 git push 到 Vercel 关联的仓库,等个十几秒,线上地址就出来了。亲测有效,比搭 Nginx + Node 服务省了至少半小时。
这个场景最好用:动态 API + 数据聚合
我最近做的一个项目需要从多个第三方接口拉数据,再合并返回给前端。以前得自己起个 Express 服务,还得考虑负载、日志、监控……现在?一个 Serverless 函数搞定。
比如从两个假接口拉用户信息和订单信息:
import fetch from 'node-fetch';
export default async function handler(req, res) {
try {
const [userRes, orderRes] = await Promise.all([
fetch('https://jztheme.com/api/user/123'),
fetch('https://jztheme.com/api/orders/123')
]);
const user = await userRes.json();
const orders = await orderRes.json();
res.status(200).json({
userId: user.id,
userName: user.name,
recentOrders: orders.slice(0, 5)
});
} catch (err) {
console.error('Aggregation failed:', err);
res.status(500).json({ error: 'Failed to fetch data' });
}
}
注意:这里用了 node-fetch,因为 Vercel 的 Serverless 环境默认没有 fetch(Node.js 18 以下)。如果你用的是 Node.js 18+ 运行时,可以直接用原生 fetch,但为了兼容性,我建议显式装 node-fetch 并 import。
这种聚合场景简直是 Serverless 的天菜——请求来了就跑,跑完就停,不用管服务器是不是半夜挂了。而且按调用量计费,没流量就不花钱,对我们这种小项目太友好了。
踩坑提醒:这三点一定注意
别看 Serverless 写起来简单,我踩过的坑能填满一个泳池。重点说三个:
- 冷启动延迟:函数长时间没被调用,下次触发会慢 1~3 秒(Vercel 免费版更明显)。解决方案?要么接受(对非关键接口),要么用 Pro 计划(保持常驻),或者前端加个 loading 提示。别指望完全消除,这是 Serverless 的物理限制。
- 超时时间硬限制:Vercel 免费版函数最长执行 10 秒,AWS Lambda 默认 3 秒(可调到 15 分钟)。我之前有个 PDF 生成函数,处理大文件时老超时。后来拆成两步:先返回“任务已提交”,再用另一个函数轮询结果。或者干脆换方案——有些重任务还是放传统服务器吧。
- 环境变量别硬编码:本地开发时图快,直接把 API Key 写代码里,一提交到 GitHub 就泄露了。正确做法是用平台提供的环境变量功能(Vercel 后台点几下就行),代码里读
process.env.API_KEY。上线前务必检查.env文件是否被 git 忽略!
还有个小细节:函数里别用 console.log 打印敏感数据(比如用户密码),日志可能被平台记录,有安全风险。调试时用 console.log 没问题,但上线前记得删掉。
高级技巧:用中间件封装通用逻辑
当函数多了,你会发现很多重复代码:鉴权、参数校验、错误格式化……这时候写个中间件层就很香。
我在项目里抽了个 withAuth.js:
// middleware/withAuth.js
export default function withAuth(handler) {
return async (req, res) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token || !isValidToken(token)) {
return res.status(401).json({ error: 'Unauthorized' });
}
return handler(req, res);
};
}
function isValidToken(token) {
// 你的验证逻辑,比如 JWT 解析
return token === 'valid-token'; // 简化示例
}
然后在具体函数里套一层:
import withAuth from '../../middleware/withAuth';
async function handler(req, res) {
// 你的业务逻辑
res.json({ data: 'protected content' });
}
export default withAuth(handler);
这样每个需要鉴权的函数只要 import 一下就行,不用重复写 if 判断。类似地,你还能做参数校验中间件、日志中间件。不过注意:中间件别嵌套太多层,否则调试时 stack trace 会很乱。
另外,Vercel 最近支持 Edge Functions(基于 Deno),启动更快,但生态还不成熟。我试过一次,发现 node-fetch 不能用,得改用 Web 标准的 fetch。如果你的函数逻辑简单,可以试试,但复杂项目建议先用传统 Serverless Functions。
不是万能药,但值得用
Serverless 不是银弹。它适合短时、无状态、事件驱动的任务。如果你要跑 WebSocket 长连接、或者需要持久化内存缓存,那还是老老实实用传统服务器吧。
但对大多数前端项目来说,80% 的后端需求(比如表单提交、数据代理、简单 webhook)都能用 Serverless 搞定。省下的运维时间,够你多写几个 feature 了。
以上是我踩坑后的总结,希望对你有帮助。这个技术的拓展用法还有很多(比如结合数据库触发器、定时任务),后续会继续分享这类博客。有更优的实现方式欢迎评论区交流——毕竟我上次那个 PDF 生成方案,到现在还在找更好的解法……

暂无评论