ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

使用 TinaCMS 与 Astro 构建零 JS 的可视化编辑站点:Kitchen Sink 示例全解析

使用 TinaCMS 与 Astro 构建零 JS 的可视化编辑站点:Kitchen Sink 示例全解析 使用 TinaCMS 与 Astro 构建零 JS 的可视化编辑站点Kitchen Sink 示例全解析【免费下载链接】tinacmsTinaCMS is the leading open-source headless CMS that supports Markdown and Visual Editing. Your content is stored in your own GitHub repo ❤️项目地址: https://gitcode.com/GitHub_Trending/ti/tinacms本文基于 TinaCMS 官方 monorepo 中的 Astro Kitchen Sink 示例examples/astro/kitchen-sink/README.md完整讲解如何在 Astro 6/7 项目中接入 TinaCMS从零 JS 的生产页面、client:tina自定义指令、块级页面Block-based Pages、6 大内容集合到可视化编辑tinaField()useTina()的完整实现链路。读完本文你将掌握一套可直接复制运行的「Astro TinaCMS」内容站点骨架并理解其底层源码级的工作原理。项目概览Astro 版 Kitchen Sink 是什么Kitchen Sink厨房水槽是 TinaCMS 用来演示全部核心功能的示例应用系列覆盖 Astro、Next.js、React、Hugo、Web Components 等多个框架examples/目录下均有对应实现。本文聚焦的 Astro 版本位于 examples/astro/kitchen-sink它的定位非常明确用 Astro 构建演示 TinaCMS 的视觉编辑、块级页面、富文本内容与多集合 schema且生产环境零客户端 JavaScript。这个组合代表了 TinaCMS 在静态站点生成SSG场景下的典型形态内容以 Markdown/MDX 形式存放在 Git 仓库中由 TinaCMS 提供可视化编辑体验最终由 Astro 在构建时静态生成所有页面。环境准备与快速启动示例 README 声明的先决条件只有两条Node.js 18pnpm因为本项目位于 TinaCMS pnpm monorepo 中使用 workspace 协议管理依赖在仓库根目录执行安装与启动pnpm install cd examples/astro/kitchen-sink pnpm dev # Astro TinaCMS可视化编辑面板位于 /admin/ pnpm dev:astro # 仅 Astro不启动 TinaCMS站点默认运行在http://localhost:4321/。两个 dev 命令的区别在于pnpm dev由 TinaCMS CLI 托管 Astro同时启动内容 API 与/admin/面板pnpm dev:astro则跳过 TinaCMS只跑纯 Astro 开发服务器。构建与预览命令pnpm build # 完整构建TinaCMS Astro pnpm build:local # 不连接云端的本地构建仅本地内容 pnpm preview # 预览构建产物从 package.json 的 scripts 可以看到这些命令的底层实现dev: cross-env MONOREPO_DEVtrue tinacms dev -c \astro dev\, dev:astro: astro dev, build: tinacms build astro build, build:local: tinacms build --local --skip-cloud-checks -c \astro build\, preview: astro preview值得注意的细节MONOREPO_DEVtrue告诉 TinaCMS CLI 当前处于 monorepo 开发模式build:local通过--local --skip-cloud-checks跳过云端连接检查在完全没有配置TINA_CLIENT_ID/TINA_TOKEN的情况下也能构建出纯本地内容站点依赖采用 pnpm workspace 协议tinacms: workspace:*、tinacms/cli: workspace:*与仓库根目录的pnpm-workspace.yaml对应。站点路由内容如何映射为页面README 给出了完整的路由表每一类内容都对应独立的渲染路径路由说明/首页块级页面hero、features、CTA、testimonial、content/posts/文章列表含作者头像与日期/posts/:slug文章详情支持嵌套路径/blog/博客列表Hero 图 卡片网格/blog/:filename博客详情富文本正文/authors/作者列表爱好徽章/authors/:filename作者详情渐变标题/projects-built-with-tina静态页块级页面/admin/TinaCMS 管理面板对应的 Astro 页面文件位于 src/pagesindex.astro首页、[...urlSegments].astro兜底动态路由posts/index.astro与posts/[...urlSegments].astro支持嵌套路径的文章对应内容目录content/posts/下的子目录结构blog/[filename].astro、authors/[filename].astro等按文件名为参数。以首页 src/pages/index.astro 为例页面通过 TinaCMS 生成的 GraphQL 客户端取数再交给 React 组件渲染--- import PageRenderer from ../components/tina/PageRenderer; import Layout from ../layouts/Layout.astro; const client (await import(../../tina/__generated__/client)).default; const result await client.queries.page({ relativePath: home.md }); --- Layout titleTinaCMS Astro Kitchen Sink PageRenderer client:tina data{result.data} query{result.query} variables{result.variables} / /Layout__generated__/client是 TinaCMS CLI 根据 schema 自动生成的类型化查询客户端relativePath: home.md精确指定读取首页内容文件。TinaCMS 集合体系内容 Schema 的完整设计README 声明示例包含6 个核心集合Tag、Author、Global、Post、Blog、Page。而实际的 tina/config.tsx 注册了 8 个集合README 聚焦前 6 个另外还有 SEO 与 Announcement 两个辅助集合集合作用Tag文章的标签分类Author作者资料头像、简介、爱好Global全站配置顶部导航、页脚社交链接、主题PostMDX 文章富文本摘要、作者引用、标签支持BlogMDX 博客Hero 图、发布日期Page块级页面hero、features、CTA、testimonial、contentSEO / Announcement全站 SEO 元数据与公告config 中补充注册config.tsx的完整配置如下import { defineConfig } from tinacms; // 面向主流托管平台的分支探测 const branch process.env.GITHUB_BRANCH || process.env.VERCEL_GIT_COMMIT_REF || process.env.HEAD || main; export default defineConfig({ branch, clientId: process.env.TINA_CLIENT_ID || null, token: process.env.TINA_TOKEN || null, localContentPath: ../../../shared, build: { outputFolder: admin, publicFolder: public, }, media: { tina: { mediaRoot: uploads, publicFolder: public, }, }, schema: { collections: [Tag, Author, Global, Post, Blog, Page, SEO, Announcement], }, });几个关键配置项的源码级解读branch依次从GITHUB_BRANCH、VERCEL_GIT_COMMIT_REF、HEAD环境变量探测当前 Git 分支兜底为main适配 GitHub/Vercel 等主流托管平台localContentPath: ../../../shared指向 monorepo 内共享的内容目录 examples/shared/content所有示例框架Astro/Next/React/Hugo共用同一份作者、文章、页面数据media.tina.mediaRoot: uploads媒体文件默认上传至public/uploads对应 examples/shared/public/uploads 中的示例图片build.outputFolder: admin管理面板构建产物输出到public/admin即http://localhost:4321/admin/所服务的静态资源。Post 集合一个字段级别的完整范式Post 集合 是理解 TinaCMS 字段能力的最佳样本它展示了几乎所有常用字段类型与 UI 定制const Post: Collection { label: Posts, name: post, path: content/posts, format: md, ui: { router: ({ document }) { return /posts/${document._sys.breadcrumbs.join(/)}; }, filename: { slugify: makeSlugify(post), readonly: true, }, }, fields: [ // ... ], };ui.router定义编辑器中点击『在站点打开』的跳转逻辑用_sys.breadcrumbs拼接出/posts/...的真实路由嵌套目录也天然支持ui.filename.slugify标题自动生成文件名slugreadonly: true禁止手动改名保证路由稳定title字段isTitle: true标记为列表显示标题required: true必填并通过ui.validate自定义校验——标题少于 5 个字符即报错heroImgtype: image图片字段uploadDir: () posts指定上传子目录excerpttype: rich-text富文本用overrides.toolbar裁剪工具栏为[bold, italic, link]authortype: reference引用字段collections: [author]限定可引用的集合——这是 TinaCMS 实现跨文档关系如文章→作者的方式datedatetime字段定制dateFormat: MMMM DD YYYY与timeFormat: hh:mm A同样带ui.validate发布日期不能晚于当前时间tags复用共享的tagsFieldSchema见下文并通过itemProps让每个标签项以标签名显示_body正文富文本parser: { type: mdx }表示以 MDX 解析isBody: true声明正文主体还内嵌了 3 个 MDX 模板BlockQuote、DateTime、NewsletterSignup。Page 集合块级页面的编排核心Page 集合 只有一个blocks字段却是块级页面的灵魂fields: [ { type: object, list: true, name: blocks, label: Sections, ui: { visualSelector: true, // 启用可视化块选择器 }, templates: [ heroBlockSchema, featureBlockSchema, ctaBlockSchema, testimonialBlockSchema, contentBlockSchema, ], }, ],ui.visualSelector: true让编辑器以所见即所得的方式插入区块配合每个 block schema 中的ui.previewSrc预览图如/blocks/hero.png编辑者无需理解数据模型即可拼装页面。首页/正是home.md中的 blocks 数组渲染出来的结果。共享字段 Schema避免重复的最佳实践示例把跨集合复用的字段抽到了 tina/schemas/shared-fields.ts源码注释明确说明其目的是集中公共字段模式保持同步makeSlugify(prefix)生成带集合前缀兜底的 slugify 函数title为空时回退为prefix-时间戳tagsFieldSchema可复用的标签引用列表字段objectlistreferencedateFieldSchemas发布/更新日期字段对actionsFieldSchema按钮/链接列表label、type 二选一 button/link、link、icon 布尔值colorFieldSchema区块背景色选择器default / tint / primary 三档。而 tina/schemas/blocks.ts 定义了 5 种块 schemahero、features、cta、testimonial、content每种块都包含previewSrc预览图、defaultItem默认数据与字段定义。例如heroBlockSchema包含 tagline、headline、rich-text 文本、图片对象srcalt、actions 与 colortestimonialBlockSchema的默认引用是编程界的经典名言There are only two hard things in Computer Science: cache invalidation and naming things.。零 JS 生产页面client:tina指令的实现原理这是本示例最具技术含金量的特性。默认情况下TinaCMS 的可视化编辑依赖 React 在页面中运行但 Kitchen Sink 通过自定义 Astro 客户端指令实现了生产页面零 JS仅编辑器 iframe 内水合 React。指令注册astro-tina-directive/register.js 是一个 Astro 集成integration在astro:config:setup钩子中注册名为tina的客户端指令指向./astro-tina-directive/tina.jsexport default () ({ name: client:tina, hooks: { astro:config:setup: ({ addClientDirective }) { addClientDirective({ name: tina, entrypoint: ./astro-tina-directive/tina.js, }); }, }, });该集成在 astro.config.mjs 中启用export default defineConfig({ integrations: [react(), mdx(), tinaDirective()], vite: { plugins: [tailwindcss()], ssr: { noExternal: [react-icons] }, build: { rollupOptions: { onwarn(warning, warn) { // 忽略 TinaCMS 生成文件产生的 UNUSED_EXTERNAL_IMPORT 警告 if (warning.code UNUSED_EXTERNAL_IMPORT warning.exporter tinacms/dist/client) return; warn(warning); }, }, }, }, });配置文件里还包含两个值得留意的工程细节ssr.noExternal: [react-icons]规避 react-icons 目录导入在 Node ESM 下的解析错误onwarn静默 TinaCMS 生成文件的未使用导入警告源码中已注释关联 issue。水合判定逻辑astro-tina-directive/tina.js 是判断是否水合的核心export default async (load, options, el) { try { const isInIframe window.self ! window.top; if (!isInIframe) { return; // 不在 iframe 中什么都不做保持零 JS } const hydrate await load(); await hydrate(); } catch (error) { console.error(An error occurred in the Tina client directive:, error); } };原理一句话通过window.self ! window.top判断当前页面是否运行在 iframe 中。TinaCMS 管理面板/admin/会把站点渲染进预览 iframe此时指令触发 React 水合激活useTina()实时数据订阅而普通访客直接访问生产页面时不在 iframe 内指令直接返回组件保持纯静态 HTML。类型声明在 astro-tina-directive/index.d.ts 中为 Astro 客户端指令注册了client:tina?: boolean的类型。可视化编辑tinaField()与useTina()的配合README 指出所有可编辑字段通过tinaField()标记修改通过useTina()实时反映。以首页渲染器 src/components/tina/PageRenderer.tsx 为例import { Blocks } from /components/blocks; import { tinaField, useTina } from tinacms/dist/react; export default function PageRenderer(props: TinaPagePropsany) { const { data } useTina({ ...props }); const page data?.page; if (!page) { return div classNamep-6 text-red-600Error: No page data found/div; } return ( div />富文本与自定义 MDX 组件README 强调富文本能力TinaMarkdown 配合自定义组件代码块、引用块、日期时间、新闻订阅。支撑它的正是 Post 集合_body字段里的 3 个 MDX 模板tina/collections/post.tsxBlockQuote引用块含childrenrich-text与authorName两个字段DateTimeinline: true的行内模板通过format字段utc/iso/local三选一控制日期输出格式NewsletterSignup新闻订阅组件字段含childrenCTA、placeholder、buttonText、disclaimer且ui.defaultItem预置了placeholder: Enter your email与buttonText: Notify Me的默认值。这些模板在实际页面中的渲染实现位于 src/components/markdown-components.tsx编辑者在面板中直接以组件形式插入富文本正文由 MDX 解析器序列化存储——这正是parser: { type: mdx }的意义所在。视觉编辑使用流程按 README 的说明运行pnpm dev后打开http://localhost:4321/admin/即可体验完整工作流侧边栏列出全部集合Tag、Author、Global、Post、Blog、Page 等均可直接编辑对于 Page、Post、Blog 三类内容进入视觉编辑模式站点渲染在预览 iframe 中点击任意被tinaField()标记的字段即可就地编辑修改通过useTina()实时反映到预览由于client:tina指令的存在水合只发生在编辑器的 iframe 内访客看到的页面始终是零 JS 的纯静态 HTML。/admin/面板本身由tinacms dev/tinacms build生成输出到public/admin见config.tsx的build.outputFolder配置。静态生成与内容本地化示例的「静态生成」特性体现在两个层面Astro 侧所有页面在构建期通过生成好的 GraphQL client 取数并输出静态 HTML无需服务端运行时TinaCMS 侧build:local使用--local模式连接本地内容层tina/database.ts配置本地 datalayer依赖tinacms/datalayerworkspace 包配合localContentPath读取 examples/shared/content 中的 Markdown/MDX/JSON 内容完全不需要云端账号即可演示全部编辑能力。另外示例还通过 e2e 目录下的 Playwright 测试home.spec.ts、posts.spec.ts、blog.spec.ts、navigation.spec.ts、edge-cases.spec.ts及admin/下的 author/blog/page/post 管理端测试对上述所有能力做了端到端验证覆盖页面渲染、导航、边缘情况、管理端增删改等场景可作为理解示例行为边界的补充阅读。小结Astro Kitchen Sink 示例的价值在于它示范了一套生产可用的内容驱动站点架构内容与代码同仓存放Markdown/MDX Gitschema 即内容的类型系统块级页面 视觉选择器让非技术人员也能拼装页面client:tina指令把可视化编辑与零 JS 生产页面这两个看似矛盾的目标同时实现8 个集合、共享字段 schema、MDX 自定义组件共同构成了一个内容模型的完整范式。如果你正在评估Astro 可视化 CMS的落地方式这个示例是当前仓库中可直接运行、结构清晰、源码可循的最佳起点。【免费下载链接】tinacmsTinaCMS is the leading open-source headless CMS that supports Markdown and Visual Editing. Your content is stored in your own GitHub repo ❤️项目地址: https://gitcode.com/GitHub_Trending/ti/tinacms创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表