你决定使用 Next.js 或 Astro 等现代前端框架构建无头 WordPress 站点。这听起来像是极佳的开发体验——直到你遇到了两个臭名昭著的障碍:
-
CORS 地狱:你在本地开发服务器
http://localhost:4321或http://localhost:3000上启动,发起 fetch 请求,然后……轰。浏览器控制台里满是红色的 CORS 策略错误。 - 迟缓的 REST API:标准的 WordPress REST API 或 WPGraphQL 会在每一次请求中启动整个 WordPress 核心并查询 MySQL。响应时间徘徊在 300ms 到 1s 之间,拖慢你的构建并导致动态服务端获取滞后。
如果你能把 WordPress 变成静态 JSON 生成器,立即提供无需数据库查询的 API 载荷,并直接从管理面板管理 CORS 标头而无需服务器配置,会怎么样?
以下是使用开源 Static JSON Export & CORS Whitelist 插件在 1 分钟内实现此目标的方法。
考虑过的替代标题
- How to solve WordPress CORS issues in 1 minute with Astro / Next.js
- Bypass WordPress Database: How to Fetch Static JSON with Zero-Config CORS(已选)
- The Clean Way to Headless WordPress: Static JSON + Zero-SDK Plugin
工作原理:静态 JSON vs. 动态数据库查询
在传统的无头设置中,你的前端在每次点击时查询数据库:
[Traditional REST API]
Frontend Fetch ──> Boot WordPress ──> Run MySQL Queries ──> Format JSON ──> Return Payloads (200-500ms)
Enter fullscreen mode Exit fullscreen mode
使用静态 JSON 导出架构时,数据库会被绕过:
[Static JSON Export]
Content Updated ──> Write Static JSON files in Background
Frontend Fetch ──> WordPress REST Endpoint ──> Directly Load JSON file ──> Return Payloads (30-50ms)
Enter fullscreen mode Exit fullscreen mode
因为 JSON 是在发布时预渲染的,所以在提供源时数据库查询次数为零,在流量高峰期大幅降低服务器负载。
1 分钟 WordPress 设置
- 从官方 WordPress 插件目录搜索并安装 Static JSON Export & CORS Whitelist。
- 在仪表板中打开 JSON Export CORS 设置页面。
- 在 CORS Allowed Origins 列表中,添加你的开发 URL(例如
http://localhost:4321或http://localhost:3000)。 - 在 JSON Feeds Settings 中,为
post类型添加一个名为posts的新源,然后点击 Save Settings。
该插件会立即将你的文章导出为静态 JSON 文件。你将获得两个简洁的端点:
-
源索引:
https://your-wp.com/wp-json/sjec/v1/feed?name=posts -
单篇文章详情:
https://your-wp.com/wp-json/sjec/v1/post?feed=posts&slug=hello-world
连接你的前端
下面是在 Astro 和 Next.js 中使用这个简洁、支持 CORS 的静态 JSON 源是多么简单。
示例 A:Astro(静态站点生成)
Astro 的静态优先方法与静态 JSON 源完美匹配。
---
// src/pages/index.astro
interface Post {
id: number;
title: string;
slug: string;
excerpt: string;
date: string;
}
// Fetch the static JSON feed (no DB queries executed on WP)
const response = await fetch('https://your-wordpress-site.com/wp-json/sjec/v1/feed?name=posts');
if (!response.ok) {
throw new Error('Failed to fetch posts');
}
const posts: Post[] = await response.json();
---
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Fast Headless Astro Blog</title>
</head>
<body class="max-w-3xl mx-auto py-12 px-4 bg-slate-50 text-slate-800">
<header class="mb-12">
<h1 class="text-4xl font-extrabold">Lightning-Fast Headless Blog</h1>
<p class="text-slate-500 mt-2">Bypassing WordPress database queries using pre-generated static JSON feeds.</p>
</header>
<main class="space-y-6">
{posts.map((post) => (
<article class="p-6 bg-white rounded-lg shadow-sm border border-slate-100 hover:shadow-md transition">
<h2 class="text-2xl font-bold text-indigo-600 hover:underline">
<a href={`/blog/${post.slug}`}>{post.title}</a>
</h2>
<p class="text-slate-600 mt-3" set:html={post.excerpt} />
<time class="text-xs text-slate-400 block mt-4">
Published: {new Date(post.date).toLocaleDateString()}
</time>
</article>
))}
</main>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
示例 B:Next.js(App Router - 增量静态再生成)
Next.js 会自动缓存静态 JSON 文件并高效地提供服务。
// app/blog/page.tsx
export const revalidate = 600; // Cache for 10 minutes
interface WordPressPost {
id: number;
title: string;
slug: string;
excerpt: string;
date: string;
}
export default async function BlogIndexPage() {
const res = await fetch('https://your-wordpress-site.com/wp-json/sjec/v1/feed?name=posts', {
next: { revalidate: 600 }
});
if (!res.ok) {
throw new Error('Failed to fetch static feed');
}
const posts: WordPressPost[] = await res.json();
return (
<div className="max-w-4xl mx-auto py-12 px-6">
<h1 className="text-3xl font-bold mb-8">Next.js + Static JSON Feeds</h1>
<div className="space-y-6">
{posts.map((post) => (
<div key={post.id} className="p-6 bg-white border border-slate-200 rounded-lg shadow-sm">
<h2 className="text-2xl font-bold">
<a href={`/blog/${post.slug}`} className="text-blue-600 hover:text-blue-800 hover:underline">
{post.title}
</a>
</h2>
<div
className="text-slate-600 mt-2"
dangerouslySetInnerHTML={{ __html: post.excerpt }}
/>
<span className="text-xs text-slate-400 mt-4 block">
Published: {new Date(post.date).toLocaleDateString()}
</span>
</div>
))}
</div>
</div>
);
}
Enter fullscreen mode Exit fullscreen mode
性能基准
我们比较了在本地环境下获取标准 WP REST API 与该插件的响应能力:
| 路由 / 方法 | 平均响应时间 | 数据库负载 | 备注 |
|---|---|---|---|
| Standard WP REST API | ~320 ms | 高(启动 WP + 查询 MySQL) | 速度慢,负载下崩溃 |
| This Plugin (Free Version) | ~35 ms | 零 (0) | 通过 WP REST 提供已保存的 JSON |
| This Plugin (PRO Version) | <1 ms | 零 (0) | 通过独立的 api.php 完全绕过 WP 核心 |
即使是免费版本也能将响应延迟减少约 90%,并完全消除数据库查询,确保你的托管服务器保持稳定。
🧼 100% 干净:无跟踪 SDK,无臃肿
WordPress 目录中的许多免费插件包含第三方营销 SDK,如 Freemius 来收集用户跟踪数据。这通常会用侵入性的升级横幅使你的管理仪表板变得臃肿。
为了尊重开发环境,该插件的免费版本构建得完全无 SDK:
- 无跟踪器或动态外部脚本。
- 无侵入性升级通知或营销弹窗。
- 轻量级代码库,100% 符合 WordPress.org 提交指南。
如果你需要高性能功能来扩展规模(如独立的 api.php 端点、多个自定义源或 Webhook 自动触发器),你可以单独购买并下载 PRO 版本。
后续步骤
要在 60 秒内尝试此设置,请查看:
- 🌐 WordPress 插件:WordPress.org 上的 Static JSON Export & CORS Whitelist
- 🚀 即用型样板:GitHub 上的 Astro Headless WordPress Starter Template
你是否构建过无头 WordPress 站点?你使用了什么解决方案来解决 CORS 并加速 API 响应?让我们在评论中讨论!
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.