Vercel Functions 地理定位实战:在 Edge 和 Serverless 中获取用户位置
@vercel/functions 包提供了 geolocation() 和 ipAddress() 两个核心函数,让你在 Vercel 部署的应用中零配置获取用户地理位置和 IP 地址。本文聚焦安装、配置、参数详解和常见坑点,帮你快速在生产环境中落地。
安装与快速上手
安装
BASHnpm install @vercel/functions
基础用法(Next.js App Router 示例)
TYPESCRIPTimport { geolocation, ipAddress } from '@vercel/functions'; export async function GET(request: Request) { const geo = geolocation(request); const ip = ipAddress(request); return Response.json({ city: geo.city, country: geo.country, region: geo.region, latitude: geo.latitude, longitude: geo.longitude, ip, }); }
关键点:
geolocation()和ipAddress()都需要传入标准的Request对象。- 在 Next.js Pages Router 中,使用
req对象(IncomingMessage类型)同样有效。 - 返回的
geo对象中,city、region等字段可能为undefined,务必做空值检查。
核心参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
geolocation(request) | Request | 是 | 返回 { city, country, latitude, longitude, region } 对象 |
ipAddress(request) | Request | 是 | 返回请求的 IP 地址字符串 |
返回值字段详解:
| 字段 | 示例值 | 说明 |
|---|---|---|
city | "Beijing" | 城市名,可能为 undefined |
country | "CN" | ISO 3166-1 alpha-2 国家代码 |
latitude | "39.9042" | 纬度(字符串) |
longitude | "116.4074" | 经度(字符串) |
region | "iad1" | Vercel Edge 节点代码,非用户所在地区 |
注意:region 字段返回的是处理请求的 Vercel 边缘节点位置(如 hkg1 表示香港节点),并非用户的地理区域。如需用户所在地区(如 US-CA),需通过请求头 X-Vercel-IP-Country-Region 手动解析。
在 Edge Middleware 中集成(低延迟方案)
Edge Middleware 运行在 Vercel Edge Network,延迟极低,适合做基于地理位置的请求拦截或重定向。
TYPESCRIPT// middleware.ts(项目根目录或 src/ 下) import { geolocation } from '@vercel/functions'; import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const { country } = geolocation(request); // 限制非中国地区访问 if (country !== 'CN') { return NextResponse.redirect(new URL('/blocked', request.url)); } // 根据国家做 A/B 测试 if (country === 'US') { return NextResponse.rewrite(new URL('/us-version', request.url)); } return NextResponse.next(); } export const config = { matcher: '/api/:path*', };
性能对比:
| 方案 | 延迟 | 适用场景 |
|---|---|---|
| Edge Middleware | < 10ms | 重定向、A/B 测试、访问控制 |
| Serverless Functions | 50-200ms | 需要数据库查询或复杂计算 |
与自建 IP 地理定位方案对比
| 维度 | Vercel Functions | 自建(MaxMind GeoIP2) |
|---|---|---|
| 部署复杂度 | 零配置,开箱即用 | 需维护 IP 库更新、数据库查询 |
| 延迟 | Edge 层直接读请求头,极低 | 可能涉及外部 API 或数据库查询 |
| 成本 | 包含在 Vercel 平台费用中 | IP 库许可费或 API 调用费 |
| 精度 | 国家、地区、城市级别 | 可提供邮编、时区等更细粒度 |
| 可移植性 | 绑定 Vercel 平台 | 可迁移至任意云或本地 |
常见报错与排查
1. geolocation is not defined
原因:未正确导入或安装包。
解决:
BASHnpm install @vercel/functions
确保导入语句正确:
TYPESCRIPTimport { geolocation } from '@vercel/functions';
TypeScript 用户需在 tsconfig.json 中设置 "esModuleInterop": true。
2. Request object is not valid
原因:传入的参数不是标准的 Request 对象。
解决:在 Next.js App Router 中,从路由处理函数参数获取 request;在 Pages Router 中使用 req。不要传入 undefined 或自定义对象。
3. Geolocation headers are missing
原因:本地开发环境没有地理定位请求头。
解决:
- 使用
vercel dev命令启动本地开发(Vercel CLI)。 - 手动模拟请求头进行测试:
BASH
curl -H "X-Vercel-IP-Country: US" http://localhost:3000/api/geo - 生产环境若仍缺失,检查是否使用了代理(如 Cloudflare)。Enterprise 用户可启用 Trusted Proxy 功能。
4. Cannot read properties of undefined (reading 'city')
原因:geolocation() 返回的对象中某些字段为 undefined。
解决:访问前做空值检查:
TYPESCRIPTconst { city } = geolocation(request) || {}; // 或使用可选链 city?.toLowerCase();
常见问题 FAQ
Q: 如何在 Next.js 的 Edge Middleware 中使用 geolocation?
A: 在 middleware.ts 中直接调用 geolocation(request) 即可。注意:
middleware.ts必须放在项目根目录或src/目录下。- Edge Middleware 运行在 Vercel Edge Network,延迟极低,适合做重定向和访问控制。
- 示例见上文“在 Edge Middleware 中集成”章节。
Q: geolocation() 返回的 region 字段是什么格式?
A: region 字段返回的是 Vercel Edge 节点代码(如 iad1、hkg1),代表处理请求的边缘节点位置,并非用户的地理区域。如需用户所在地区(如 US-CA),需通过请求头 X-Vercel-IP-Country-Region 手动获取,geolocation() 函数目前不直接返回此字段。
Q: 能否在 Vercel Functions(Serverless)中使用 geolocation?
A: 可以。geolocation() 同时支持 Edge Middleware 和 Serverless Functions。在 Serverless 函数中,请求对象同样包含地理定位请求头。但注意:
- Serverless 函数可能运行在特定区域,延迟比 Edge Middleware 高。
- 建议对延迟敏感的场景(如重定向、A/B 测试)使用 Edge Middleware,对需要复杂计算或数据库操作的场景使用 Serverless Functions。
生产环境注意事项
- 代理问题:如果使用了 Cloudflare、自定义反向代理等,Vercel 无法获取正确的客户端 IP 和地理位置。Enterprise 用户可配置 Trusted Proxy 功能。
- 精度限制:Vercel 仅提供国家、地区、城市级别的地理位置,无法获取精确坐标或邮编。数据基于 IP 库,VPN 或代理可能导致误判。
- 配额限制:免费版 Vercel 账户对 Edge Middleware 的请求量有限制,高流量场景需注意配额。
- 无内置缓存:每次请求都需解析请求头,可能增加 Edge 函数执行时间。如需缓存,可在应用层自行实现。
- 安全性:地理位置信息通过请求头传递,确保不泄露给客户端或第三方。不要在客户端 JavaScript 中暴露这些数据。
相关深度解决方案
在配置当前服务时,如果您需要实现更复杂的架构或多源数据整合,建议配合参考我们整理的 Upstash Redis Serverless REST API 实战:从 HTTP 调用到 MCP 集成。
在配置当前服务时,如果您需要实现更复杂的架构或多源数据整合,建议配合参考我们整理的 Next.js SSG 与同类方案怎么选:实测对比与选型指南。