首页
/ Next.js 静态生成博客实战:基于 Prismic CMS 的内容驱动型官网搭建指南

Next.js 静态生成博客实战:基于 Prismic CMS 的内容驱动型官网搭建指南

2026-09-06 16:02:55作者:邬祺芯Juliet

本文以 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-reactprismic-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

该命令会依次完成三件事:

  1. 要求你登录 Prismic 或创建账户;
  2. 创建一个预置了 Author 和 Post 两种内容模型(content model)的新 Prismic 仓库;
  3. 将 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 文档)

  1. 进入 Prismic 控制台,选择你的仓库;
  2. 点击 Create new,先创建一个 Author 类型文档——只需 1 个即可,文本用占位数据,头像可从 Unsplash 下载;保存后务必点击 Publish
  3. 返回文档列表,再创建至少 2 个 Post 类型文档:正文使用 Text 和 Image 两种 Slice 组合,封面图同样可用 Unsplash 图片,并关联上一步创建的 author。

重要提示:每个文档保存后必须点击 Publish 发布,否则文档处于草稿(draft)状态,站点查询不到。

配置步骤三:本地开发

npm run dev

# 或

yarn dev

博客运行在 http://localhost:3000

从源码看,首页与文章页的数据都通过 Prismic 客户端在构建/静态生成阶段拉取:

  • 首页 pages/index.tsxgetStaticProps 中调用 client.getAllByType("post", { fetchLinks: [...], orderings: [{ field: "my.post.date", direction: "desc" }] }) 按发布日期倒序取回全部已发布文章,fetchLinks 同时拉取关联 author 的 namepicture 字段;页面将第一篇作为 HeroPost 头条,其余交给 MoreStories 组件展示。
  • 文章页 pages/posts/[slug].tsxgetStaticPaths 同样调用 getAllByType("post") 并返回 { paths: allPosts.map((post) => post.url), fallback: true }——fallback: true 意味着构建后新增的文章也能被访问,浏览器先看到加载占位(对应组件中 router.isFallback ? <PostTitle>Loading…</PostTitle> : ...),服务端再按需生成;getStaticPropsclient.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;
};

两个关键设计值得注意:

  1. routes 声明:告诉 Prismic 客户端 post 类型文档的访问路径是 /posts/:uid,这样 post.urlgetStaticPaths 与首页链接跳转都依赖它)能自动解析为 /posts/<uid>
  2. enableAutoPreviews@prismicio/next 提供的辅助函数,根据传入的 previewDatareq 自动切换到草稿查询模式,是整个 Preview 功能的核心开关。

配置步骤四:体验 Preview Mode(草稿预览)

在 Prismic 仓库页面的 Settings → Previews → Create a New Preview 中填写开发预览配置:

  • Site Name:任意,如 "Development";
  • Domain of Your Applicationhttp://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.tsxpreview 为 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/reactPrismicRichText 将富文本字段映射为带 Tailwind 样式的 React 组件(heading2heading3paragraphlistoList),这是 Prismic 富文本结构到 JSX 的标准转换模式。

此外,示例还内置了 Slice Simulator 页面 pages/slice-simulator.tsx:它使用 @prismicio/slice-simulator-reactSliceSimulator 组件,在 http://localhost:3000/slice-simulator 上预览每个 Slice 的各种数据变体,供编辑与开发两侧对齐预期效果。

配置步骤五:部署上线

将项目推送至代码托管平台并导入 Vercel 即可部署,也可以直接使用 README 提供的模板一键部署(需配置 PRISMIC_API_TOKENPRISMIC_REPOSITORY_NAME 两个环境变量来连接你的 Prismic 仓库)。仓库内的 next.config.jstsconfig.json 均已就绪,无需额外调整构建配置。

与其他 CMS 示例的关系

该示例并非孤立存在,examples/cms-prismic/README.md 末尾列出了仓库内一系列同构的 CMS 集成示例,例如 examples/cms-contentfulexamples/cms-datocmsexamples/cms-graphcmsexamples/cms-storyblokexamples/cms-wordpressexamples/cms-tina 等,以及一个不依赖 CMS 的 examples/blog-starter。这些示例共享相同的「静态生成 + Preview Mode」骨架,若你熟悉其中任意一个,切换到 Prismic 的主要成本在于替换数据层(客户端与内容模型),页面层结构基本一致。

小结

  • 数据流:Prismic 内容仓库 → @prismicio/clientlib/prismic.ts 封装)→ getStaticProps/getStaticPaths 静态生成 → 静态 HTML;
  • 路由约定:routes 中声明的 /posts/:uidpages/posts/[slug].tsx 的动态路由一一对应;
  • 预览闭环:Prismic Preview 按钮 → /api/previewsetPreviewData + redirectToPreviewURL)→ 草稿态渲染 + components/alert.tsx 提示条 → /api/exit-previewexitPreview)退出;
  • 内容建模:customtypes/ 下的 JSON 模型驱动 Prismic 编辑界面,prismic-ts-codegen 生成的 Content.* 类型驱动前端类型安全,Slice 组件通过 SliceZone 完成正文渲染。
登录后查看全文
热门项目推荐
相关项目推荐