Next.js 静态生成博客实战:基于 Prismic CMS 的内容驱动型官网搭建指南
本文以 Next.js 仓库中的 examples/cms-prismic 示例为蓝本,讲解如何用 Prismic 作为数据源构建一个静态生成(Static Generation)博客站点:涵盖通过 Slice Machine 初始化内容模型、填充内容、本地开发、Preview 预览草稿以及部署上线的完整流程,并结合示例源码说明 getStaticProps/getStaticPaths 的数据拉取逻辑与 Preview Mode 的底层实现机制,读完你可以独立搭建并理解一个 CMS 驱动的博客系统。
示例定位:用 Prismic 做数据源的静态生成博客
该示例展示了 Next.js 的 Static Generation 特性,以 Prismic 作为内容来源:构建时通过 Prismic API 拉取内容生成静态页面,而非运行时逐页渲染。示例自带一个已配置好的演示仓库端点 sm.json:
{
"apiEndpoint": "https://nextjs-example-cms-prismic.prismic.io/api/v2",
"libraries": ["@/slices"],
"localSliceSimulatorURL": "http://localhost:3000/slice-simulator",
"_latest": "0.4.2"
}
其中 apiEndpoint 指向 Prismic 内容 API,libraries 指向 Slice 组件库目录,localSliceSimulatorURL 是 Slice Simulator 页面的本地地址。依赖方面,package.json 声明了 @prismicio/client、@prismicio/helpers、@prismicio/next、@prismicio/react、@prismicio/slice-simulator-react、prismic-ts-codegen 等官方 SDK,以及 slice-machine-ui(Slice Machine 开发工具),说明该示例完整覆盖了「内容建模—本地开发—代码生成—预览—部署」的 Prismic 工作流。
快速启动:create-next-app 脚手架
使用 create-next-app 配合 --example 参数即可一键拉起示例项目,支持 npm、Yarn、pnpm 三种方式:
npx create-next-app --example cms-prismic cms-prismic-app
yarn create next-app --example cms-prismic cms-prismic-app
pnpm create next-app --example cms-prismic cms-prismic-app
脚手架执行后,你得到的就是本文分析的 examples/cms-prismic 目录结构:pages/ 路由、slices/ Slice 组件、customtypes/ 内容模型定义、components/ 页面组件、lib/ 工具函数。
配置步骤一:创建 Prismic 账户与内容仓库
在项目中执行以下命令完成 Prismic 仓库初始化:
npx @slicemachine/init
该命令会依次完成三件事:
- 要求你登录 Prismic 或创建账户;
- 创建一个预置了 Author 和 Post 两种内容模型(content model)的新 Prismic 仓库;
- 将 Prismic 仓库与你的应用建立连接。
可选:启动 Slice Machine 查看预置的内容模型:
npm run slicemachine
启动后 Slice Machine 界面运行在 http://localhost:9999。
这里的「内容模型」在仓库中以 JSON 文件形式落地,例如 customtypes/post/index.json 定义了 post 文档类型,包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
title |
StructuredText | 文章标题(单一 heading1) |
uid |
UID | 文章 URL slug |
date |
Date | 发布日期 |
author |
Link(document) | 关联 author 类型文档 |
excerpt |
Text | 摘要 |
cover_image |
Image | 封面图 |
slices |
Slices | Slice Zone,承载正文内容块 |
这种「字段即 schema」的设计与前端类型系统是联动的:lib/types.ts 中通过 Content.PostDocument 扩展出带 author 关联字段文档类型 PostDocumentWithAuthor,由 prismic-ts-codegen 依据 prismicCodegen.config.ts 生成,保证拉取数据的字段访问有类型约束。
配置步骤二:填充内容(Author 与 Post 文档)
- 进入 Prismic 控制台,选择你的仓库;
- 点击 Create new,先创建一个 Author 类型文档——只需 1 个即可,文本用占位数据,头像可从 Unsplash 下载;保存后务必点击 Publish;
- 返回文档列表,再创建至少 2 个 Post 类型文档:正文使用 Text 和 Image 两种 Slice 组合,封面图同样可用 Unsplash 图片,并关联上一步创建的 author。
重要提示:每个文档保存后必须点击 Publish 发布,否则文档处于草稿(draft)状态,站点查询不到。
配置步骤三:本地开发
npm run dev
# 或
yarn dev
博客运行在 http://localhost:3000。
从源码看,首页与文章页的数据都通过 Prismic 客户端在构建/静态生成阶段拉取:
- 首页 pages/index.tsx:
getStaticProps中调用client.getAllByType("post", { fetchLinks: [...], orderings: [{ field: "my.post.date", direction: "desc" }] })按发布日期倒序取回全部已发布文章,fetchLinks同时拉取关联 author 的name与picture字段;页面将第一篇作为HeroPost头条,其余交给MoreStories组件展示。 - 文章页 pages/posts/[slug].tsx:
getStaticPaths同样调用getAllByType("post")并返回{ paths: allPosts.map((post) => post.url), fallback: true }——fallback: true意味着构建后新增的文章也能被访问,浏览器先看到加载占位(对应组件中router.isFallback ? <PostTitle>Loading…</PostTitle> : ...),服务端再按需生成;getStaticProps用client.getByUID("post", params.slug)精确取文,并用predicate.not("my.post.uid", params.slug)排除当前文章后取最近 2 篇作为「更多文章」区块,查不到时返回notFound: true。
两个页面共用的 Prismic 客户端封装在 lib/prismic.ts:
const routes: prismic.Route[] = [
{
type: "post",
path: "/posts/:uid",
},
];
export const createClient = ({
previewData,
req,
...config
}: prismicNext.CreateClientConfig = {}) => {
const client = prismic.createClient(sm.apiEndpoint, {
routes,
...config,
});
prismicNext.enableAutoPreviews({ client, previewData, req });
return client;
};
两个关键设计值得注意:
routes声明:告诉 Prismic 客户端post类型文档的访问路径是/posts/:uid,这样post.url(getStaticPaths与首页链接跳转都依赖它)能自动解析为/posts/<uid>;enableAutoPreviews:@prismicio/next提供的辅助函数,根据传入的previewData或req自动切换到草稿查询模式,是整个 Preview 功能的核心开关。
配置步骤四:体验 Preview Mode(草稿预览)
在 Prismic 仓库页面的 Settings → Previews → Create a New Preview 中填写开发预览配置:
- Site Name:任意,如 "Development";
- Domain of Your Application:
http://localhost:3000; - Link Resolver:
/api/preview。
保存后,打开任意一篇文章文档:修改标题(例如在标题前加 [Draft]),点击 Save 但不要点击 Publish(使文档保持草稿状态),然后点击 Publish 按钮旁带眼睛图标的 Preview 按钮。此时浏览器即可看到修改后的草稿标题;点击页面左下角紫色 Prismic 工具栏中的 "x" 图标可退出预览模式。
这条流程在源码中对应两个 API 路由:
- pages/api/preview.ts:Prismic 的 Link Resolver 回调端点。它用
createClient({ req })创建客户端,先调用setPreviewData({ req, res })写入预览 Cookie(Next.js Preview Mode 的令牌),再调用redirectToPreviewURL({ req, res, client })解析 Prismic 查询串(?prismic-preview=...)并 302 跳转到目标文档页。后续请求命中getStaticProps时,previewData存在,enableAutoPreviews就会让客户端以草稿身份查询内容; - pages/api/exit-preview.ts:调用
exitPreview({ res, req })清除预览 Cookie 并跳回原页,对应界面上「退出预览」的入口——components/alert.tsx 在preview为 true 时展示提示条并链接到/api/exit-preview。
也就是说,README 里「点 Preview 按钮」与「点 x 退出」这两步 UI 操作,底层就是 /api/preview 设置预览态、/api/exit-preview 清除预览态这一对端点在驱动。
Slice 机制:正文内容块的组件化渲染
Prismic 用 Slice 将正文拆成可复用的内容块。示例提供 Text 与 Image 两种 Slice,注册表 slices/index.js(由 Slice Machine 生成)将其映射到组件:
export const components = {
image: Image,
text: Text,
};
文章正文通过 components/post-body.tsx 渲染:
export default function PostBody({ slices }: PostBodyProps) {
return (
<div className="max-w-2xl mx-auto">
<SliceZone slices={slices} components={components} />
</div>
);
}
SliceZone 按文档中 slices 数组的顺序逐一匹配 components 映射并渲染。以 slices/Text/index.tsx 为例,它用 @prismicio/react 的 PrismicRichText 将富文本字段映射为带 Tailwind 样式的 React 组件(heading2、heading3、paragraph、list、oList),这是 Prismic 富文本结构到 JSX 的标准转换模式。
此外,示例还内置了 Slice Simulator 页面 pages/slice-simulator.tsx:它使用 @prismicio/slice-simulator-react 的 SliceSimulator 组件,在 http://localhost:3000/slice-simulator 上预览每个 Slice 的各种数据变体,供编辑与开发两侧对齐预期效果。
配置步骤五:部署上线
将项目推送至代码托管平台并导入 Vercel 即可部署,也可以直接使用 README 提供的模板一键部署(需配置 PRISMIC_API_TOKEN、PRISMIC_REPOSITORY_NAME 两个环境变量来连接你的 Prismic 仓库)。仓库内的 next.config.js 与 tsconfig.json 均已就绪,无需额外调整构建配置。
与其他 CMS 示例的关系
该示例并非孤立存在,examples/cms-prismic/README.md 末尾列出了仓库内一系列同构的 CMS 集成示例,例如 examples/cms-contentful、examples/cms-datocms、examples/cms-graphcms、examples/cms-storyblok、examples/cms-wordpress、examples/cms-tina 等,以及一个不依赖 CMS 的 examples/blog-starter。这些示例共享相同的「静态生成 + Preview Mode」骨架,若你熟悉其中任意一个,切换到 Prismic 的主要成本在于替换数据层(客户端与内容模型),页面层结构基本一致。
小结
- 数据流:Prismic 内容仓库 →
@prismicio/client(lib/prismic.ts 封装)→getStaticProps/getStaticPaths静态生成 → 静态 HTML; - 路由约定:
routes中声明的/posts/:uid与 pages/posts/[slug].tsx 的动态路由一一对应; - 预览闭环:Prismic Preview 按钮 →
/api/preview(setPreviewData+redirectToPreviewURL)→ 草稿态渲染 + components/alert.tsx 提示条 →/api/exit-preview(exitPreview)退出; - 内容建模:
customtypes/下的 JSON 模型驱动 Prismic 编辑界面,prismic-ts-codegen生成的Content.*类型驱动前端类型安全,Slice 组件通过SliceZone完成正文渲染。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00