使用Fauna和Vercel Functions构建无头CMS

本文介绍了无头CMS的概念,这是一种仅后端的內容管理系统,允许开发人员使用Fauna和Vercel Functions通过API创建、存储、管理和发布内容。这改善了前端-后端的工作流程,使开发人员能够快速构建出色的用户体验。

在本教程中,我们将学习并使用无头CMS、Fauna和Vercel Functions来构建一个博客平台Blogify🚀。之后,您可以轻松地使用无头CMS、Fauna和Vercel Functions构建任何Web应用程序。

简介

根据MDN,内容管理系统(CMS)是一种用于管理数字内容创建和修改的计算机软件。CMS通常有两个主要组件:内容管理应用程序(CMA),作为允许用户(即使是经验有限的用户)添加、修改和删除网站内容的前端用户界面,无需网站管理员干预;以及内容交付应用程序(CDA),它编译内容并更新网站。

传统CMS与无头CMS的优缺点

在这两者之间进行选择可能会令人困惑和复杂。但它们都具有潜在的优势和劣势。

传统CMS优点

  • 在传统CMS上设置内容要容易得多,因为您需要的一切(内容管理、设计等)都可供您使用。
  • 许多传统CMS都具有拖放功能,使没有编程经验的人员也能轻松使用它们。它还支持无需或只需少量编码知识即可轻松自定义。

传统CMS缺点

  • 传统CMS依赖的插件和主题可能包含恶意代码或错误,从而降低网站或博客的速度。
  • 前端和后端之间的传统耦合肯定会花费更多的时间和金钱用于维护和自定义。

无头CMS优点

  • 由于前端和后端彼此分离,因此可以选择使用的前端框架,这使您可以选择最适合您需求的前端技术。它提供了自由选择构建前端所需的工具——在开发阶段的灵活性。
  • 使用无头CMS部署更轻松。使用无头CMS构建的应用程序(博客、网站等)可以轻松部署到各种显示器上,例如Web设备、移动设备、AR/VR设备。

无头CMS缺点

  • 您需要负责管理后端基础设施,设置网站、应用程序的UI组件。
  • 无头CMS的实施成本通常高于传统CMS。构建包含分析功能的无头CMS应用程序并不具有成本效益。

Fauna 使用预先存在的基础设施来构建Web应用程序,而无需通常设置自定义API服务器。这有效地帮助开发人员节省了时间,以及在其他数据库中存在的选择区域和配置存储的压力;默认情况下是全局/多区域的,在Fauna中不存在。我们需要的全部维护都由Fauna的工程师和自动化的DevOps积极处理。我们将使用Fauna作为我们的仅后端内容管理系统

使用Fauna的优点

  • 轻松地在托管平台(如Netlify或Vercel)的开发环境中使用和创建Fauna数据库实例。
  • 通过GraphQL查询数据或使用Fauna自己的查询语言(FQL)进行复杂函数的强大支持。
  • 访问多种模型中的数据,包括关系型、文档型、图形型和时间序列型。
  • Fauna完全支持内置身份验证、透明扩展性和多租户等功能。
  • 通过Fauna控制台和Fauna Shell进行的附加操作使管理数据库实例变得非常容易。

Vercel Functions,也称为无服务器函数,根据文档,是用后端语言编写的代码片段,接收HTTP请求并提供响应。

先决条件

要充分利用本教程,请确保以下工具在您的本地开发环境中可用或已安装。

  • 访问Fauna仪表盘
  • React和React Hooks的基本知识
  • 已将create-react-app安装为全局包,或使用npx引导项目。
  • 在您的本地计算机上安装Node.js版本>=12.x.x
  • 确保也已安装npmyarn作为包管理器。

使用Fauna设置数据库

登录您的Fauna帐户以开始使用Fauna,或首先使用电子邮件凭据/详细信息或使用现有的Github帐户注册新帐户作为新用户。您可以在此处注册新帐户。创建新帐户或登录后,您将受到仪表盘屏幕的欢迎。如果喜欢使用shell环境,我们也可以使用fauna shell。它允许您轻松地通过终端在Fauna上创建
和/或修改资源。

使用fauna shell,命令为

npm install --global fauna-shell
fauna cloud-login

但我们将在本教程中使用网站。登录后,仪表盘屏幕将欢迎您。

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

创建数据库后,下一步是从Fauna仪表盘创建新的数据集合。导航到侧边菜单上的“集合”选项卡,然后单击“新建集合”按钮创建新的集合。

然后,我们将继续为集合提供合适的名称。这里我们将它命名为blogify_posts

准备数据库的下一步是创建一个新的索引。导航到“索引”选项卡以创建索引。可以通过使用索引在Fauna中搜索文档,特别是通过将输入与索引的terms字段进行匹配。单击“新建索引”按钮以创建索引。进入创建索引屏幕后,填写表单:选择之前创建的集合,然后为索引命名。在本教程中,我们将它命名为all_posts。现在我们可以保存索引了。

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

上面的post对象表示我们创建博客文章所需的单元数据。您选择的数据可能与我们这里提供的完全不同,可以满足您在网站中任何目的的需求。您可以为 CMS 网站创建尽可能多的文档。为了简单起见,我们只有三个博客文章。

现在我们的数据库已根据我们的选择完成设置,我们可以继续创建我们的 React 应用(前端)。

创建新的 React 应用并安装依赖项

对于前端开发,我们需要在我们的 React 应用中安装诸如Fauna SDKstyled-componentsvercel之类的依赖项。我们将使用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文件以确认所有安装都已完成。
成功。

现在让我们开始实际构建博客网站的 UI。我们将从标题部分开始。我们将在src文件夹内的components文件夹中创建一个Navigation组件,即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库进行的样式设置相结合,将显示如下 UI

现在是时候创建网站的主体了,它将包含来自我们数据库的post数据。我们构建了一个名为 Posts 的组件,其中将包含我们在后端创建的博客文章。

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 Hook 创建一个名为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 发出请求,我们将使用importconfig/db.js文件导入clientquery实例。

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组件,添加我们使用styled-components库设置样式的所有必要的 JSX 元素。我们将在数组不为空时使用 JavaScript map遍历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🚀将如下所示 UI

部署到 Vercel

Vercel CLI提供了一组命令,允许您部署和管理您的项目。以下步骤将使您的项目快速轻松地从您的终端在 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。Fauna 与无头 CMS 概念的结合,您可以构建出色的 Web 应用程序,从电子商务应用程序到笔记保存应用程序,任何需要存储和检索数据以供前端使用的 Web 应用程序。这是我们教程中使用的代码示例的GitHub 链接,以及托管在 Vercel 上的实时演示