Bypass WordPress Database: How to Fetch Static JSON with Zero-Config CORS 的封面图片

aritrhk

你决定使用 Next.js 或 Astro 等现代前端框架构建无头 WordPress 站点。这听起来像是极佳的开发体验——直到你遇到了两个臭名昭著的障碍:

  1. CORS 地狱:你在本地开发服务器 http://localhost:4321http://localhost:3000 上启动,发起 fetch 请求,然后……轰。浏览器控制台里满是红色的 CORS 策略错误。
  2. 迟缓的 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 设置

  1. 从官方 WordPress 插件目录搜索并安装 Static JSON Export & CORS Whitelist
  2. 在仪表板中打开 JSON Export CORS 设置页面。
  3. CORS Allowed Origins 列表中,添加你的开发 URL(例如 http://localhost:4321http://localhost:3000)。
  4. 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 站点?你使用了什么解决方案来解决 CORS 并加速 API 响应?让我们在评论中讨论!