Builder.io 和 Astro
Builder.io 是一个可视化的 CMS,支持通过拖放内容来编辑和构建网站。
本指南将向你展示如何在零客户端 JavaScript 的情况下将你的 Builder 空间连接到 Astro。
先决条件
“先决条件”部分要开始,你需要具备以下条件
- 一个 Builder 帐户和空间 - 如果你还没有帐户,请免费注册并创建一个新空间。如果你已经有了一个 Builder 空间,可以随意使用,但你需要修改代码以匹配模型名称(
blogpost
)和自定义数据字段。 - 一个 Builder API 密钥 - 这个公钥将用于从 Builder 获取你的内容。 阅读 Builder 关于如何找到你的密钥的指南。
设置凭据
“设置凭据”部分要将你的 Builder API 密钥和 Builder 模型名称添加到 Astro,请在你的项目根目录下创建一个 .env
文件(如果尚不存在),并添加以下变量:
BUILDER_API_PUBLIC_KEY=YOUR_API_KEYBUILDER_BLOGPOST_MODEL='blogpost'
现在,你应该可以在你的项目中使用这个 API 密钥了。
在撰写本文时,这个密钥是公开的,所以你不必担心隐藏或加密它。
如果你希望为你的环境变量提供 IntelliSense,可以在 src/
目录下创建一个 env.d.ts
文件,并像这样配置 ImportMetaEnv
:
interface ImportMetaEnv { readonly BUILDER_API_PUBLIC_KEY: string;}
你的项目现在应该包含这些文件:
目录src/
- env.d.ts
- .env
- astro.config.mjs
- package.json
使用 Astro 和 Builder 创建博客
“使用 Astro 和 Builder 创建博客”部分为博文创建模型
“为博文创建模型”部分以下说明将创建一个 Astro 博客,使用一个名为 blogpost
的 Builder 模型(类型:“Section”),该模型包含两个必填文本字段:title
和 slug
。
你可以在 Builder 的官方教程中找到展示此过程的视频。
在 Builder 应用中,创建将代表博文的模型:转到 Models 选项卡,然后单击 + Create Model 按钮,以使用以下字段和值创建模型:
- 类型: Section
- 名称: “blogpost”
- 描述: “此模型用于博文”
在你的新模型中,使用 + New Custom Field 按钮创建 2 个新字段:
-
文本字段
- 名称: “title”
- 必填: 是
- 默认值 “我忘了给这个起标题”
(将其他参数保留为默认值)
-
文本字段
- 名称: “slug”
- 必填: 是
- 默认值 “some-slugs-take-their-time”
(将其他参数保留为默认值)
然后在右上角单击 Save 按钮。
使用 slug
字段时存在一些陷阱:
-
确保你的 slug 不仅仅是一个数字。这似乎会破坏对 Builder API 的 fetch 请求。
-
确保你的 slug 是唯一的,因为你网站的路由将依赖于此。
设置预览
“设置预览”部分要使用 Builder 的可视化编辑器,请创建页面 src/pages/builder-preview.astro
,它将渲染特殊的 <builder-component>
。
目录src/
目录pages/
- builder-preview.astro
- env.d.ts
- .env
- astro.config.mjs
- package.json
然后添加以下内容:
---const builderAPIpublicKey = import.meta.env.BUILDER_API_PUBLIC_KEY;const builderModel = import.meta.env.BUILDER_BLOGPOST_MODEL;---
<html lang="en"> <head> <title>Preview for builder.io</title> </head> <body> <header>This is your header</header>
<builder-component model={builderModel} api-key={builderAPIpublicKey} ></builder-component> <script async src="https://cdn.builder.io/js/webcomponents"></script>
<footer>This is your footer</footer> </body></html>
在上面的示例中,<builder-component>
告诉 Builder 在哪里插入来自其 CMS 的内容。
将新路由设置为预览 URL
“将新路由设置为预览 URL”部分-
将预览的完整 URL(包括协议)复制到剪贴板(例如
https://{your host}/builder-preview
)。 -
转到你的 Builder 空间中的 Models 选项卡,选择你创建的模型,然后将步骤 1 中的 URL 粘贴到 Preview URL 字段中。确保 URL 是完整的并包含协议,例如
https://
。 -
单击右上角的 Save 按钮。
当你部署你的网站时,将预览 URL 更改为与你的生产 URL 匹配,例如 https://myAwesomeAstroBlog.com/builder-preview
。
测试预览 URL 设置
“测试预览 URL 设置”部分-
确保你的网站已上线(例如,你的开发服务器正在运行)并且
/builder-preview
路由正在工作。 -
在你的 Builder 空间的 Content 选项卡下,单击 New 为你的
blogpost
模型创建一个新的内容条目。 -
在刚刚打开的 Builder 编辑器中,你应该能看到
builder-preview.astro
页面,中间有一个大大的 Add Block。
设置预览时有时会出现问题。如果有什么不对劲,你可以尝试以下方法之一:
- 确保网站已上线 - 例如,你的开发服务器正在运行。
- 确保 URL 完全匹配 - Astro 项目中的 URL 和 Builder 应用中设置的 URL。
- 确保它是包含协议的完整 URL,例如
https://
。 - 如果你在虚拟环境(如 IDX、StackBlitz 或 Gitpod)中工作,重新启动工作区时可能需要再次复制并粘贴 URL,因为这通常会为你的项目生成一个新的 URL。
更多想法,请阅读 Builder 的故障排除指南。
创建博文
“创建博文”部分-
在 Builder 的可视化编辑器中,创建一个具有以下值的新内容条目:
- title: ‘第一篇文章,哇哦!‘
- slug: ‘first-post-woohoo’
-
使用 Add Block 按钮完成你的文章,并添加一个包含一些文章内容的文本字段。
-
在编辑器上方的文本字段中,为你的条目命名。它将以此名称在 Builder 应用中列出。
-
准备好后,单击右上角的 Publish 按钮。
-
你可以创建任意数量的文章,确保所有内容条目都包含
title
和slug
以及一些文章内容。
显示博文列表
“显示博文列表”部分将以下内容添加到 src/pages/index.astro
,以获取并显示所有文章标题的列表,每个标题都链接到其自己的页面:
---
const builderAPIpublicKey = import.meta.env.BUILDER_API_PUBLIC_KEY;const builderModel = import.meta.env.BUILDER_BLOGPOST_MODEL;
const { results: posts } = await fetch( `https://cdn.builder.io/api/v3/content/${builderModel}?${new URLSearchParams({ apiKey: builderAPIpublicKey, fields: ["data.slug", "data.title"].join(","), cachebust: "true", }).toString()}`) .then((res) => res.json()) .catch();---
<html lang="en"> <head> <title>Blog Index</title> </head> <body> <ul> { posts.flatMap(({ data: { slug, title } }) => ( <li> <a href={`/posts/${slug}`}>{title}</a> </li> )) } </ul> </body></html>
通过内容 API 进行 fetch 会返回一个对象数组,其中包含每篇文章的数据。 fields
查询参数告诉 Builder 包含哪些数据(见高亮代码)。 slug
和 title
应与你添加到 Builder 模型中的自定义数据字段的名称匹配。
从 fetch 返回的 posts
数组会在主页上显示一个博文标题列表。单个页面路由将在下一步中创建。
如果你在 Astro 项目中使用 JavaScript 框架(例如 Svelte、Vue 或 React),你可以使用 Builder 的一个集成,作为通过 REST API 进行原始 fetch 调用的替代方案。
转到你的索引路由,你应该能看到一个链接列表,每个链接都是一篇博文的标题!
显示单篇博文
“显示单篇博文”部分创建页面 src/pages/posts/[slug].astro
,它将为每篇文章动态生成一个页面。
目录src/
目录pages/
- index.astro
目录posts/
- [slug].astro
- env.d.ts
- .env
- astro.config.mjs
- package.json
这个文件必须包含:
- 一个
getStaticPaths()
函数,用于从 Builder 获取slug
信息,并为每篇博文创建一个静态路由。 - 一个使用
slug
标识符对 Builder API 的fetch()
调用,以返回文章内容和元数据(例如title
)。 - 模板中的一个
<Fragment />
,用于将文章内容渲染为 HTML。
以下代码片段中高亮显示了这些内容。
---export async function getStaticPaths() { const builderModel = import.meta.env.BUILDER_BLOGPOST_MODEL; const builderAPIpublicKey = import.meta.env.BUILDER_API_PUBLIC_KEY; const { results: posts } = await fetch( `https://cdn.builder.io/api/v3/content/${builderModel}?${new URLSearchParams( { apiKey: builderAPIpublicKey, fields: ["data.slug", "data.title"].join(","), cachebust: "true", } ).toString()}` ) .then((res) => res.json()) .catch // ...catch some errors...); (); return posts.map(({ data: { slug, title } }) => ({ params: { slug }, props: { title }, }))}const { slug } = Astro.params;const { title } = Astro.props;const builderModel = import.meta.env.BUILDER_BLOGPOST_MODEL;const builderAPIpublicKey = import.meta.env.BUILDER_API_PUBLIC_KEY;// Builder's API requires this field but for this use case the url doesn't seem to matter - the API returns the same HTMLconst encodedUrl = encodeURIComponent("moot");const { html: postHTML } = await fetch( `https://cdn.builder.io/api/v1/qwik/${builderModel}?${new URLSearchParams({ apiKey: builderAPIpublicKey, url: encodedUrl, "query.data.slug": slug, cachebust: "true", }).toString()}`) .then((res) => res.json()) .catch();---<html lang="en"> <head> <title>{title}</title> </head> <body> <header>This is your header</header> <article> <Fragment set:html={postHTML} /> </article> <footer>This is your footer</footer> </body></html>
变量 builderModel
和 builderAPIpublicKey
需要创建两次,因为 getStaticPaths()
在其自己的隔离作用域中运行。
现在,当你点击索引路由上的链接时,你将被带到单个博文页面。
发布你的站点
“发布你的网站”部分要部署你的网站,请访问我们的部署指南并按照你偏好的托管提供商的说明进行操作。
在 Builder 内容更改时重建
“在 Builder 内容更改时重建”部分如果你的项目使用 Astro 的默认静态模式,你需要设置一个 webhook,以便在内容更改时触发新的构建。如果你使用 Netlify 或 Vercel 作为托管提供商,你可以使用它们的 webhook 功能,在 Builder 编辑器中点击 Publish 时触发新的构建。
Netlify
“Netlify”部分-
转到你的网站仪表板,然后是 Site Settings,并单击 Build & deploy。
-
在 Continuous Deployment 选项卡下,找到 Build hooks 部分,然后点击 Add build hook。
-
为你的 webhook 提供一个名称,并选择你想要触发构建的分支。点击 Save 并复制生成的 URL。
Vercel
“Vercel”部分-
转到你的项目仪表盘,然后点击 Settings。
-
在 Git 选项卡下,找到 Deploy Hooks 部分。
-
为你的 webhook 提供一个名称,并选择你想要触发构建的分支。点击 Add 并复制生成的 URL。
向 Builder 添加 webhook
“向 Builder 添加 webhook”部分有关更多信息,请参阅 Builder 关于添加 webhook 的指南。
-
在你的 Builder 仪表板中,进入你的
blogpost
模型。在 Show More Options 下,选择底部的 Edit Webhooks。 -
通过单击 Webhook 添加一个新的 webhook。将你的托管提供商生成的 URL 粘贴到 Url 字段中。
-
单击 URL 字段下的 Show Advanced,并切换选项以选择 Disable Payload。禁用 payload 后,Builder 会向你的托管提供商发送一个更简单的 POST 请求,这在你网站规模增长时会很有帮助。单击 Done 保存此选择。
有了这个 webhook,每当你在 Builder 编辑器中点击 Publish 按钮时,你的托管提供商就会重建你的网站——Astro 也会为你获取新发布的数据。你所要做的就是放松下来,尽情创作那些美妙的内容!
官方资源
“官方资源”部分- 查看官方的 Builder.io 入门项目,该项目使用了 Astro 和 SolidJS。
- 官方的 Builder 快速入门指南涵盖了 REST API 的使用以及通过与 Qwik、React 或 Vue 等 JavaScript 框架的集成进行数据获取。
- 如果你需要对 API 调用进行故障排除,Builder 的 API 浏览器可以提供帮助。
社区资源
“社区资源”部分- 阅读 Yoav Ganbar 的文章《将 Builder.io 的可视化 CMS 连接到 Astro》。