本文介绍了无头CMS的概念,这是一个仅有后台的内容管理系统,允许开发者使用Fauna和Vercel功能通过API创建、存储、管理和发布内容。这改善了前端-后端的工作流程,使开发者能够快速建立优秀的用户体验。
在本教程中,我们将学习并使用无头CMS、Fauna和Vercel函数来建立一个博客平台Blogify🚀。之后,你可以使用无头CMS、Fauna和Vercel功能轻松地构建任何网络应用。
简介
根据MDN,内容管理系统(CMS)是一种计算机软件,用于管理数字内容的创建和修改。CMS通常有两个主要组成部分:一个是内容管理应用程序(CMA),作为前端的用户界面,允许用户,即使专业知识有限,也可以在没有网站管理员干预的情况下添加、修改和删除网站的内容;另一个是内容交付应用程序(CDA),负责编译内容和更新网站。
传统CMS与无头CMS的利与弊
在这两者之间做出选择可能会相当混乱和复杂。但它们都有潜在的优点和缺点。
传统CMS的优点
- 在传统CMS上设置你的内容要容易得多,因为你所需要的一切(内容管理、设计等)都提供给你了。
- 很多传统的内容管理系统有拖放功能,使一个没有编程经验的人很容易使用它们。它还支持零或很少的编码知识,可以轻松地进行定制。
传统CMS的缺点
- 传统CMS所依赖的插件和主题可能包含恶意代码或错误,并降低网站或博客的速度。
- 传统的前端和后端耦合,肯定需要更多的时间和金钱来维护和定制。
无头CMS的优点
- 可以灵活地选择使用前端框架,因为前端和后端是相互分离的,这使得你可以选择适合你需求的前端技术。在开发阶段,你可以自由选择构建前端所需的工具--灵活性。
- 使用无头CMS,部署工作更容易。使用无头CMS构建的应用程序(博客、网站等)可以很容易地被部署到各种显示器上,如网络设备、移动设备、AR/VR设备。
无头CMS的缺点
- 你要担心管理你的后端基础设施,设置你的网站和应用程序的用户界面组件。
- 与传统CMS相比,实施无头CMS的成本较高。构建包含分析功能的无头CMS应用程序并不具有成本效益。
FaunaVercel功能使用预先存在的基础设施来构建Web应用程序,而不需要通常设置一个自定义的API服务器。这有效地帮助节省了开发人员的时间,而且在其他数据库中存在的选择区域和配置存储的压力;默认情况下是全局/多区域的,在Fauna中是不存在的。我们需要的所有维护工作都由Fauna的工程师和自动化的DevOps积极处理。我们将使用Fauna作为我们唯一的后台内容管理系统。
使用Fauna的优点
- 在Netlify或Vercel等托管平台的开发环境中,易于使用和创建Fauna数据库实例。
- 非常支持通过GraphQL或使用Fauna自己的查询语言来查询数据。Fauna查询语言(FQL),用于复杂的功能。
- 访问多种模型的数据,包括关系型、文档型、图形型和时间型。
- 像内置认证、透明的可扩展性和多租户的能力在Fauna上完全可用。
- 通过Fauna Console以及Fauna Shell的插件,可以非常容易地管理数据库实例。
根据文档,Vercel函数,也被称为无服务器函数,是用后端语言编写的代码片段,接受HTTP请求并提供响应。
前提条件
为了充分利用本教程,请确保在你的本地开发环境中可以使用或安装以下工具:
- 访问Fauna仪表板
- 关于React和React Hooks的基本知识
- 有
[create-react-app](https://reactjs.org/docs/create-a-new-react-app.html)以全局包的形式安装,或使用npx来引导项目。 - 在你的本地机器上安装了Node.js版本>=
12.x.x。 - 确保
npm或yarn也作为包管理器安装。
用Fauna设置数据库
登录到你的Fauna账户开始使用Fauna,或者首先使用电子邮件凭证/细节或使用现有的Github账户作为新用户注册一个新账户。你可以在这里注册一个新的账户。一旦你创建了一个新的账户或登录,你将会受到仪表盘屏幕的欢迎。如果你喜欢shell环境,我们还可以利用fauna shell。它很容易让你
通过终端
创建和/或
修改Fauna的资源。
使用fauna shell,命令是:
npm install --global fauna-shell
fauna cloud-login
但我们将在本教程中使用网站。一旦登录,仪表板屏幕就会欢迎你:

现在我们已经登录或创建了我们的账户,我们可以继续创建我们的Fauna。我们将通过以下简单步骤,使用Fauna服务创建新的Fauna数据库。我们从命名我们的数据库开始,我们将使用它作为我们的内容管理系统。在本教程中,我们将命名我们的数据库为blogify。

数据库创建后,下一步是在Fauna仪表板上创建一个新的数据集合。导航到侧面菜单上的集合标签,点击NEW COLLECTION ,创建一个新的集合。

然后,我们将继续给我们的集合起一个合适的名字。这里我们将称之为blogify_posts。

让我们的数据库做好准备的下一步是创建一个新的index 。导航到Indexes标签来创建一个索引。在Fauna中搜索文档可以通过使用indexes ,特别是通过与索引的terms 字段匹配输入。点击NEW INDEX 按钮来创建一个索引。一旦进入创建索引界面,填写表格:选择我们之前创建的集合,然后给我们的索引取个名字。在本教程中,我们将命名为all_posts。现在我们可以保存我们的索引。

创建完索引后,现在是创建我们的DOCUMENT的时候了,这将包含我们想用于CMS网站的内容/数据。点击NEW DOCUMENT 按钮来开始。用文本编辑器来创建我们的文档,我们将创建一个对象数据来满足我们对网站的需求。

上面的post 对象代表了我们创建博文所需的单元数据。你所选择的数据可以与我们这里的不同,为你的网站中任何你想要的目的服务。你可以为你的CMS网站创建尽可能多的文件,你可能需要。为了保持简单,我们只有三个博客文章。

现在,我们已经完成了数据库的设置,我们可以继续创建我们的React应用程序,即前端。
创建一个新的React应用程序并安装依赖性
对于前端开发,我们将需要在我们的React应用程序中依赖诸如Fauna SDK,styled-components 和vercel 。我们将使用styled-components 进行UI造型,在我们的终端中使用vercel 来承载我们的应用程序。Fauna SDK 将被用于访问我们所设置的数据库中的内容。你可以随时将styled-components 替换为你决定用于UI风格设计的任何库。也可以使用你喜欢的任何UI框架或库,而不是其他。
npx create-react-app blogify
# install dependencies once directory is done/created
yarn add fauna styled-components
# install vercel globally
yarn global add vercel
fauna 包是Fauna的JavaScript驱动。库styled-components ,允许你编写实际的CSS代码来设计你的组件。一旦完成了项目依赖的所有安装,检查package.json 文件以确认所有安装都成功了
。

现在让我们开始实际构建我们的博客网站用户界面。我们将从页眉部分开始。Navigation 我们将在components 文件夹中创建一个src 文件夹中的src/components ,以包含我们的博客名称,Blogify🚀:
import styled from "styled-components";
function Navigation() {
return (
<Wrapper>
<h1>Blogify🚀</h1>
</Wrapper>
);
}
const Wrapper = styled.div`
background-color: #23001e;
color: #f3e0ec;
padding: 1.5rem 5rem;
& > h1 {
margin: 0px;
}
`;
export default Navigation;
在导入App 组件后,上述代码加上通过styled-components 库的样式,将变成下面的用户界面。

现在是时候创建网站的主体了,它将包含来自我们数据库的post 数据。我们构造了一个名为Post的组件,它将包含我们在后台创建的博客文章。
import styled from "styled-components";
function Posts() {
return (
<Wrapper>
<h3>My Recent Articles</h3>
<div className="container"></div>
</Wrapper>
);
}
const Wrapper = styled.div`
margin-top: 3rem;
padding-left: 5rem;
color: #23001e;
& > .container {
display: flex;
flex-wrap: wrap;
}
& > .container > div {
width: 50%;
padding: 1rem;
border: 2px dotted #ca9ce1;
margin-bottom: 1rem;
border-radius: 0.2rem;
}
& > .container > div > h4 {
margin: 0px 0px 5px 0px;
}
& > .container > div > button {
padding: 0.4rem 0.5rem;
border: 1px solid #f2befc;
border-radius: 0.35rem;
background-color: #23001e;
color: #ffffff;
font-weight: medium;
margin-top: 1rem;
cursor: pointer;
}
& > .container > div > article {
margin-top: 1rem;
}
`;
export default Posts;
上面的代码包含了JSX的样式,一旦我们开始从后端向前端查询数据,我们仍将创建这些样式。
将Fauna SDK集成到我们的React应用程序中
为了将fauna 客户端与React应用程序集成,你必须从应用程序中建立一个初始连接。在目录路径src/config/ ,创建一个新文件db.js 。然后导入fauna 驱动程序并定义一个新的客户端。
作为参数传递给fauna.Client() 方法的secret ,将持有来自.env 文件的访问密钥。
import fauna from 'fauna';
const client = new fauna.Client({
secret: process.env.REACT_APP_DB_KEY,
});
const q = fauna.query;
export { client, q };
在Posts 组件中,使用useState React Hooks创建一个名为posts 的状态变量,默认值为一个数组。它将存储我们将使用setPosts 函数从数据库获取的内容的值。然后定义第二个状态变量,visible ,默认值为false ,我们将使用handleDisplay 函数来隐藏或显示更多的帖子内容,我们将在本教程的后面添加一个按钮来触发。
function App() {
const [posts, setPosts] = useState([]);
const [visible, setVisibility] = useState(false);
const handleDisplay = () => setVisibility(!visible);
// ...
}
通过编写查询来创建无服务器功能
由于我们的博客网站只需要执行一个操作,那就是获取我们在数据库中创建的数据/内容,所以我们创建一个新的目录,名为src/api/ ,并在其中创建一个新的文件,名为index.js 。使用ES6进行请求,我们将使用import ,从config/db.js 文件中导入client 和query 实例:
export const getAllPosts = client
.query(q.Paginate(q.Match(q.Ref('indexes/all_posts'))))
.then(response => {
const expenseRef = response.data;
const getAllDataQuery = expenseRef.map(ref => {
return q.Get(ref);
});
return client.query(getAllDataQuery).then(data => data);
})
.catch(error => console.error('Error: ', error.message));
})
.catch(error => console.error('Error: ', error.message));
上面对数据库的查询将返回一个ref ,我们可以通过映射来获得应用程序所需的实际结果。我们将确保附加catch ,这将有助于在查询数据库时检查是否有错误,这样我们就可以把它记录下来。
接下来是显示从我们的CMS、数据库--从Fauna集合中返回的所有数据。我们将通过在我们的Posts 组件内的useEffect Hook中调用./api/index.js 文件中的查询getAllPosts 来做到这一点。这是因为当Posts 组件第一次渲染时,它将迭代数据,检查数据库中是否有任何帖子。
useEffect(() => {
getAllPosts.then((res) => {
setPosts(res);
console.log(res);
});
}, []);
打开浏览器的控制台,检查从数据库返回的数据。如果所有的事情都是正确的,而且你密切关注的话,返回的数据应该如下所示:

有了这些从数据库成功返回的数据,我们现在可以完成我们的Posts 组件,添加所有必要的JSX元素,我们已经使用styled-components 库的样式。我们将使用JavaScriptmap 循环浏览posts 状态,数组,只有当数组不是空的时候。
import { useEffect, useState } from "react";
import styled from "styled-components";
import { getAllPosts } from "../api";
function Posts() {
useEffect(() => {
getAllPosts.then((res) => {
setPosts(res);
console.log(res);
});
}, []);
const [posts, setPosts] = useState([]);
const [visible, setVisibility] = useState(false);
const handleDisplay = () => setVisibility(!visible);
return (
<Wrapper>
<h3>My Recent Articles</h3>
<div className="container">
{posts &&
posts.map((post) => (
<div key={post.ref.id} id={post.ref.id}>
<h4>{post.data.post.title}</h4>
<em>{post.data.post.date}</em>
<article>
{post.data.post.mainContent}
<p style={{ display: visible ? "block" : "none" }}>
{post.data.post.subContent}
</p>
</article>
<button onClick={handleDisplay}>
{visible ? "Show less" : "Show more"}
</button>
</div>
))}
</div>
</Wrapper>
);
}
const Wrapper = styled.div`
margin-top: 3rem;
padding-left: 5rem;
color: #23001e;
& > .container {
display: flex;
flex-wrap: wrap;
}
& > .container > div {
width: 50%;
padding: 1rem;
border: 2px dotted #ca9ce1;
margin-bottom: 1rem;
border-radius: 0.2rem;
}
& > .container > div > h4 {
margin: 0px 0px 5px 0px;
}
& > .container > div > button {
padding: 0.4rem 0.5rem;
border: 1px solid #f2befc;
border-radius: 0.35rem;
background-color: #23001e;
color: #ffffff;
font-weight: medium;
margin-top: 1rem;
cursor: pointer;
}
& > .container > div > article {
margin-top: 1rem;
}
`;
export default Posts;
有了上面完整的代码结构,我们的博客网站Blogify🚀,将看起来像下面的用户界面:

部署到Vercel
Vercel CLIFauna提供了一套命令,使你能够部署和管理你的项目。以下步骤将使你的项目从你的终端快速而容易地托管到vercel平台上。
vercel login
按照指示在终端上登录你的Vercel账户
vercel
从项目目录的根部使用vercel 命令。这将提示一些问题,我们将根据问题的内容提供答案。
vercel
? Set up and deploy “~/Projects/JavaScript/React JS/blogify”? [Y/n]
? Which scope do you want to deploy to? ikehakinyemi
? Link to existing project? [y/N] n
? What’s your project’s name? (blogify)
# click enter if you don't want to change the name of the project
? In which directory is your code located? ./
# click enter if you running this deployment from root directory
? ? Want to override the settings? [y/N] n
这将把你的项目部署到vercel。访问你的vercel账户,完成CI/CD目的所需的任何其他设置。
总结
我很高兴你跟随教程到这里,希望你已经学会了如何将Fauna作为无头CMS使用。