在开发面向海外的独立站或 Web 应用时,Next.js 是很多前端团队的首选框架。为了兼顾 SEO 和首屏加载速度,我们通常会开启 SSR(服务端渲染)或 ISR(增量静态再生)。
最近在将 Next.js 项目部署到腾讯云服务器(Node.js 环境)后,遇到了一个非常典型的线上问题:本地开发环境(Mac/Windows)测试一切秒开,但线上的页面在服务端调用海外 Headless CMS(无头内容管理系统)或第三方 API 时,频繁出现首屏白屏、Nginx 报 504 Gateway Timeout,或者在 Vercel 可以看到日志里大面积报 FetchError: request to https://api.overseas-cms.com failed, reason: connect ETIMEDOUT。
本文记录这次 SSR 请求超时的排查与解决过程。
1. 区分是前端还是服务端问题
首先打开浏览器的 Network 面板,发现请求 Next.js 页面 URL 时,服务器迟迟没有返回 HTML 文档,状态码为 504。这说明问题卡在了 Node.js 服务端的 getServerSideProps 或 generateMetadata 中,而不是浏览器端的跨域或网络问题。
2. 服务端网络探测
登录腾讯云服务器,使用 curl 直接请求目标海外 API 的端点:
curl -o /dev/null -s -w "DNS解析: %{time_namelookup}s\nTCP建连: %{time_connect}s\nTLS握手: %{time_appconnect}s\n首字节(TTFB): %{time_starttransfer}s\n" \
"https://api.overseas-cms.com/v1/data"结果显示,TCP建连 耗时极长,TTFB 甚至超过 10 秒。偶尔能连通,但速度极慢。
3. 检查出口 IP 的“身份”
使用 curl -s https://ipinfo.io/json\ 查看腾讯云服务器的公网 IP 归属,发现其 ASN 属于云服务商(数据中心 IP)。
根本原因:Next.js SSR 是在服务端发起 HTTP 请求。许多海外 CMS 服务(如 Contentful, Sanity)和 SaaS API 的前端通常接入了 Cloudflare 或 Akamai 等 WAF(Web 应用防火墙)。这些防护系统对来自云服务器机房的 IP 段有极其严格的降级策略,以防止恶意爬虫和 CC 攻击。表现为:能握手,但严重限速或间歇性 RST(连接重置),导致 Node.js 的 fetch 超时。
既然瓶颈在服务器出口 IP 的信任度上,就需要给 Node.js 进程配置一个干净的、非机房的网络出口。这里以接入 1024Proxy 的住宅网络出口为例。
在 Next.js 的服务端环境中,原生的 fetch API 无法直接通过 options 传入代理。我们需要使用 undici 库(Node.js 内置 fetch 的底层实现)的 ProxyAgent,或者在旧版 Node 中使用 https-proxy-agent。
以下是在 Next.js 项目中引入网络出口的代码示例:
npm install undici在 lib/fetchWithProxy.ts(或 js 文件)中封装请求:
// ============================================
// Next.js 服务端配置独立网络出口示例
// 出口服务:1024Proxy
// 官网:https://1024proxy.com/?kwd=hyj-txy
// ============================================
import { ProxyAgent, fetch as undiciFetch } from 'undici';
// 从环境变量中读取住宅 IP 信息
const PROXY_URL = process.env.RESIDENTIAL_PROXY_URL || 'http://用户名:密码@gateway.1024proxy.com:端口';
const proxyAgent = new ProxyAgent(PROXY_URL);
export async function fetchWithProxy(url: string, options: any = {}) {
try {
// 使用底层的 undici fetch 并注入网络出口
const response = await undiciFetch(url, {
...options,
dispatcher: proxyAgent, // 将请求流量导入住宅 IP
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error("Fetch with proxy failed:", error);
throw error;
}
}在 app/page.tsx(App Router)或 pages/index.tsx(Pages Router)中:
import { fetchWithProxy } from '@/lib/fetchWithProxy';
export default async function Page() {
// 该请求在 Node.js 服务端执行,走干净的住宅 IP 出口
const data = await fetchWithProxy('https://api.overseas-cms.com/v1/data');
return (
<main>
<h1>{data.title}</h1>
{/* 渲染内容 */}
</main>
);
}配置重启 Next.js 服务后,再次访问页面:
fetch 耗时 8-10s,频繁超时导致 504。ETIMEDOUT 报错。在前后端同构的现代框架(如 Next.js, Nuxt.js)中,服务端发起的请求很容易被忽视。云服务器的默认机房 IP 在访问海外服务时,往往会遭遇 WAF 的严格限速。通过底层网络模块(如 undici、https-proxy-agent)为 SSR 渲染进程接入稳定、高匿的住宅 IP,是提升海外站点首屏加载速度、降低请求失败率的有效工程手段。
本文仅做技术开发交流,请确保所有网络请求与数据交互符合目标平台的使用条款。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。