Loving Tina? us on GitHub0.0k

文档

学习

v.Latest
Documentation
Next.js App路由
目录
👆本指南假设您正在使用 Next.js app router.

视频指南

安装依赖

在您网站的目录中运行:

npx @tinacms/cli@latest init

这将询问您一些设置问题。当提示输入公共资产目录时,输入:public

更新构建脚本

tina init 应该已经更新了您的 package.json 脚本。

"scripts": {
"dev": "tinacms dev -c \"next dev\"",
"build": "tinacms build && next build",
"start": "tinacms build && next start"
}

如果这些没有被CLI设置,您需要手动应用。

启动TinaCMS

您可以通过以下命令启动TinaCMS:

pnpm dev

我们推荐使用pnpm。

在TinaCMS运行后,导航到 http://localhost:3000/admin/index.html

❓ 提示:如果运行此命令时出现错误,请查看常见错误页面。

此时,您应该能够看到Tina管理界面,选择一个帖子,保存更改,并看到更改持久化到您的本地markdown文件中。

TinaCMS 管理界面截图

TinaCMS 配置文件

运行 tina init 命令后,创建了一些文件以帮助您快速入门。其中之一是 tina/config.ts 文件。这是一个必需的配置文件,定义了所有的tina模式。

它看起来如下:

import { defineConfig } from 'tinacms';
// 您的托管提供商可能将此作为环境变量公开
const branch =
process.env.GITHUB_BRANCH ||
process.env.VERCEL_GIT_COMMIT_REF ||
process.env.HEAD ||
'main';
export default defineConfig({
branch,
// 从 tina.io 获取
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID,
// 从 tina.io 获取
token: process.env.TINA_TOKEN,
build: {
outputFolder: 'admin',
publicFolder: 'public',
},
media: {
tina: {
mediaRoot: '',
publicFolder: 'public',
},
},
schema: {
collections: [
{
name: 'post',
label: 'Posts',
path: 'content/posts',
fields: [
{
type: 'string',
name: 'title',
label: 'Title',
isTitle: true,
required: true,
},
{
type: 'rich-text',
name: 'body',
label: 'Body',
isBody: true,
},
],
},
],
},
});

有关配置的更详细概述,请参阅TinaCMS内容建模

💡 如果您按照本指南使用 tina init 命令,您可能已经注意到创建了一个 content 和一个 pages 文件夹:
Adding file at content/posts/hello-world.md... ✅
Adding file at pages/demo/blog/[filename].tsx... ✅
这些可以用作快速参考,但可以安全删除。

创建新帖子

💡 如 tina/config.ts 文件中定义的,我们有一个名为 post 的集合,它将被TinaCMS拾取并映射到您在TinaCMS管理页面中看到的内容。
  1. 前往 /admin/index.html
  2. 点击 Posts
  3. 点击 Create
  4. 输入必填字段
  5. 保存

现在,让我们回去检查创建了什么。您将看到一个 /content 文件夹,其中保存了您的新帖子作为 .md 文件。此路径在 tina/config.ts 文件的post集合中定义!

content
└── posts
└── hello-world.md

渲染帖子集合

让我们从创建一个 /posts 文件夹开始。这里的页面将列出我们所有的帖子。

文件: app/posts/page.tsx

import PostList from './client-page';
import { client } from '../../tina/__generated__/client';
export default async function Page() {
const { data } = await client.queries.postConnection();
return (
<>
<h1>Posts</h1>
<div>
{data.postConnection.edges.map((post) => (
<div key={post.node.id}>
<Link href={`/posts/${post.node._sys.filename}`}>
{post.node._sys.filename}
</Link>
</div>
))}
</div>
</>
);
}

您可能已经注意到这是一个服务器渲染的页面。根据此页面的生成方式,Next将会:

  • A. 将其构建为动态/服务器渲染页面
  • B. 将其构建为静态页面。

这取决于您希望如何渲染此页面。

渲染单个帖子

为了使其与TinaCMS可视化编辑器一起工作,我们将其分为两个组件。一个将在构建时构建页面。另一个将是一个可以与TinaCMS交互并工作的客户端渲染页面。

文件: app/posts/[...filename].tsx

import Post from './client-page';
import client from '../../../tina/__generated__/client';
export async function generateStaticParams() {
const pages = await client.queries.postConnection();
const paths = pages.data?.postConnection?.edges?.map((edge) => ({
filename: edge?.node?._sys.breadcrumbs,
}));
return paths || [];
}
export default async function PostPage({
params,
}: {
params: { filename: string[] };
}) {
const data = await client.queries.post({
relativePath: `${params.filename}.md`,
});
return <Post {...data}></Post>;
}

在这里,我们使用 generateStaticParams 将这些页面构建为SSG。您可以根据需要随意更改。

现在,为了使可视化编辑器工作,我们将创建一个新的“客户端页面”:

文件: app/posts/[...filename]/client-page.tsx

'use client';
import { useTina } from 'tinacms/dist/react';
import { PostQuery } from '../../../tina/__generated__/types';
interface ClientPageProps {
query: string;
variables: {
relativePath: string;
};
data: PostQuery;
}
export default function Post(props: ClientPageProps) {
// 数据在生产模式下传递,并在编辑模式下更新为侧边栏数据
const { data } = useTina({
query: props.query,
variables: props.variables,
data: props.data,
});
return (
<code>
<pre
style={{
backgroundColor: 'lightgray',
}}
>
{JSON.stringify(data.post, null, 2)}
</pre>
</code>
);
}

常见问题

页面上的更新未正确反映

在使用App Router的Next.js项目中使用TinaCMS时,您可能会遇到Vercel过于积极地缓存内容,导致某些更新未正确反映的情况。

根本原因是 Vercel数据缓存 正在缓存来自TinaCloud内容API的响应。这可以通过查询GraphQL API并查找更新的内容,或检查Vercel中的缓存使用情况来确认。

有两种方法可以修改您的网站以最佳方式使用Vercel数据缓存:

  1. 手动更新路由段的默认重新验证时间。这将导致增量静态生成在运行时重新验证缓存的内容API响应时重建页面并更新内容。更多信息请参见:https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate
  2. 在您的查询(TinaCMS生成的)中添加一个额外的参数,例如
    const response = await client.queries.page({ relativePath: 'pages/home.mdx'}, { fetchOptions: { next: { revalidate: 60 } })})
    这将传递给底层的 fetch 请求。有关Next.js如何扩展 fetch 的更多信息,请参见:https://nextjs.org/docs/app/api-reference/functions/fetch

新创建的内容项未出现在页面上

在使用App Router的Next.js项目中使用TinaCMS时,您可能会遇到新创建的内容项未立即出现在相应页面上的情况。这种行为通常是由于Next.js和浏览器采用的积极缓存机制造成的。

为了确保在本地开发期间看到最新的内容,您可以在浏览器的开发者工具中禁用浏览器缓存:

  1. 在浏览器中打开开发者工具(例如,Chrome,Firefox)。
  2. 导航到网络选项卡。
  3. 勾选禁用缓存选项(此设置在开发者工具打开时有效)。


在开发者工具中禁用缓存


有关Next.js中缓存的更详细信息,请参阅Next.js官方文档: Next.js缓存文档

下一步

上次编辑: March 10, 2025