All Systems Operational
Powered By
profound-logo
profound-logoProfound CMS
⌘K
Admin

支持编辑模式的静态渲染

解释文档站点如何在保持 CMS 编辑模式功能的同时实现快速的静态页面加载

Continue Reading
Previous‹设置管理面板代理Next模板构建器中的脚本编写›

混合

渲染器项目参数化路由组件类型SSE设置管理面板代理支持编辑模式的静态渲染模板构建器中的脚本编写Create Profound Next

无头

快速入门Json 与 Claude 代码组件 Zod 拉取

Mcp

Mcp

Cms 功能

功能文档模板模板构建器功能翻译功能组织功能

激励

我们的方法

术语

混合式与无头式对比

本指南解释了文档站点如何在保持 CMS 编辑模式功能的同时实现快速的静态页面加载。

双路由架构

我们为同一份内容使用两条路由:

app/
├── [...slug]/page.tsx          # 生产环境:force-static(快速)
└── preview/[...slug]/page.tsx  # 编辑模式:force-dynamic(读取 searchParams)

一个代理中间件会透明地重写编辑模式请求:

用户请求:/en/headless/quickstart?edit_mode=true
       ↓
代理检测到 ?edit_mode=true
       ↓
内部重写为:/preview/en/headless/quickstart?edit_mode=true
       ↓
动态路由会携带编辑包装进行渲染

用户永远不会在其 URL 中看到 /preview —— 这只是一次内部重写。

工作原理

生产路径(默认)

// app/[...slug]/page.tsx
export const dynamic = 'force-static';
export const revalidate = 60;

export default async function Page({ params }) {
  // 无 searchParams —— 页面完全静态
  return <
  • 页面在构建时预渲染
  • 从 CDN 边缘缓存即时提供
  • 每 60 秒重新验证一次(ISR)作为安全保障

编辑模式路径

// app/preview/[...slug]/page.tsx
export const dynamic = 'force-dynamic';

export default async function PreviewPage({ params, searchParams }) {
  // searchParams 可用,可检测 edit_mode
  return <ParametricRoutePage params={params} 
  • 每次请求都会渲染
  • 可以从 URL 中读取 ?edit_mode=true
  • 使用 CMS 可编辑包装和区块轮廓进行渲染

代理重写

// src/proxy.ts
export const proxy = async (request: NextRequest) => {
  const { pathname, searchParams } = request.nextUrl;

  const editMode = searchParams.get('edit_mode');

性能对比

场景响应时间渲染
生产页面(缓存命中)~50-100ms来自 CDN 的静态内容
生产页面(缓存过期)~50-100ms + 后台刷新静态,然后 ISR
编辑模式~500-1500ms动态 SSR

理解 ISR(增量静态再生)

revalidate = 60 设置启用了 ISR。这并不意味着页面每隔 60 秒重新计算。

ISR 使用 stale-while-revalidate 模式:

请求到来:
  → 缓存页面是否小于 60 秒?→ 从缓存提供(即时)
  → 缓存页面是否超过 60 秒?→ 提供过期缓存(即时)
                                + 在后台重新验证供下一次请求使用

没有请求 = 永不重新计算。

示例:

  • 页面在上午 10:00 被缓存
  • 直到下午 3:00 都没有访客
  • 下午 3:00 的第一位访客即时获得过期缓存
  • 后台刷新完成后,下一位访客获得最新内容

60 秒窗口只是安全保障。理想情况下,我们会在 CMS 内容变更时通过 Webhook 触发按需重新验证。

何时使用各自的路由

使用场景URL使用的路由
正常浏览/en/headless/quickstart静态
CMS 模板构建器/en/headless/quickstart?edit_mode=true预览(通过重写)
AI 区块预览/en/headless/quickstart?ai_preview=1预览(通过重写)

为什么不直接使用动态渲染?

这种简单方法(没有 force-static,也没有预览路由)虽然可行,但速度很慢:

// 简单方法 —— 可用,但每个请求约 1-2 秒
export default async function Page({ params, searchParams }) {
  return <ParametricRoutePage params={params} searchParams={searchParams} />;
}

这会在每次请求时进行动态渲染。对于拥有大量页面的文档站点来说,这意味着:

  • 每个页面都会冷启动
  • 无法利用 CDN 边缘缓存优势
  • 1-2 秒的加载时间对比毫秒级

双路由架构让我们兼得两者:为读者提供静态速度,为编辑者提供动态功能。

ParametricRoutePage
params
={
params
} />;
}
searchParams
={
searchParams
} />;
}
const
aiPreview
=
searchParams.
get
(
'ai_preview'
);
// 如果存在 edit_mode 或 ai_preview 且路径不以 /preview 开头,则重写到预览路由
if ((editMode === 'true' || editMode === '1' || aiPreview) && !pathname.startsWith('/preview')) {
const url = request.nextUrl.clone();
url.pathname = `/preview${pathname}`;
return NextResponse.rewrite(url);
}
return NextResponse.next();
};