使用Strapi Webhooks和NextJS创建SSG(静态站点生成)应用程序
#javascript #strapi #nextjs #webhooks

作者:olaoluwa ajibadde

Next.js is a popular and widely-used React framework.允许我们使用各种预渲染技术。在Next.js应用程序中,我们可以使用客户端渲染,服务器端渲染(SSR)和静态站点生成(SSG)。

在本文中,我们将研究Next.js提供的每种渲染方法的优势。然后,我们将使用Strapi,Next.js和webhooks构建SSG(静态站点生成)博客应用程序。

通过使我们的博客应用程序成为静态网站,我们可以避免在每个数据请求或更新上击中服务器,这会带来许多优势,例如降低成本,快速博客响应时间等。当将新内容添加到我们的博客数据库中时,我们可以使用GET POST更改通知Strapi Webhook立即更新,重建和重新部署我们的静态博客应用程序。

先决条件

要进行,您必须对以下内容有基本的了解:

  • node.js的JavaScript的基本知识
  • 对Next.js的基本理解
  • Strapi的基本理解
  • git和github

next.js渲染方法

在这里,我们将探索Next.js所提供的不同渲染方法。

客户端渲染

这是使用useEffect钩获取的通常的数据;数据主要由客户端的API调用获取。客户端将接收此代码,执行请求并构建页面。

客户端渲染非常适合登录的体验和单页应用程序。客户端渲染是如果我们需要在每次交互中对用户进行身份验证。

服务器端渲染

服务器端渲染非常适合以快速加载速度创建页面。这对页面SEO也有益。在服务器端渲染中,服务器生成HTML并将整个页面发送到客户端请求中。

服务器端渲染是在服务器上执行的,因此在将网站交付给浏览器之前,所有工作均已完成。

要在Next.js中创建一个SSR页面,我们提供了一个称为koude3的函数。此功能告诉应用程序在离开服务器并将数据作为Props馈送到组件之前要检索其数据。之后,将HTML渲染并交付给客户。使用getServerSideProps,我们的页面将在运行时进行预渲染。

静态站点生成

如果网站不依赖任何外部数据,并且仅提供很少更改的静态页面,则静态站点的生成可能非常有用。 SSG描述了构建在构建时间渲染的网站的过程。输出是HTML文件,JavaScript和CSS等资产以及其他一些静态文件。

在将SSG与next.js一起使用时,该页面是在构建时间预渲染的。也就是说,用户不必等待页面加载到浏览器中。相反,该页面将立即渲染。当浏览器收到页面时,通常是一个简单的HTML,没有很多内容。

然后将脚本加载到页面上,这是一个称为水合的过程。允许我们在第一个负载上服务整个内容。在此过程中,脚本仍然可以补充页面的水合,但理想情况下,更改或根本没有更改。

用于数据获取,在SSG应用程序Next.js中为我们提供了两个功能:

  • getStaticProps:此功能在构建时间预先呈现页面,并将数据作为道具发送到我们的页面组件。
  • getStaticPaths:此功能生成了将在构建时间预渲染的页面列表。如果我们想创建动态路线,我们可以使用koude6. next.js将动态渲染getStaticPaths指定的所有路径。

next.js开箱即用。默认情况下,它将尝试检测您的应用程序正在使用并获取数据的预渲染技术。

然后,将使用SSG渲染方法构建我们文章的演示应用程序。

我们需要两件事来使用SSG渲染方法:

  • 要在我们的页面上显示的数据
  • 动态页面模板

首先,我们需要创建将在我们的博客应用程序中使用的数据。在下一节中,我们将使用Strapi生成我们的博客数据API及其内容。

设置strapi

Strapi is the leading open-source, customizable, headless content management system (CMS) based on Node.js。 Strapi具有用于构建API的不错的用户界面。

strapi生成应用程序端点而不强迫我们编写任何服务器代码。使用Strapi Admin面板功能,我们可以轻松输入所有应用程序的端点详细信息。有关更多信息,see the Strapi documentation.

让我们开始从事我们的项目。

脚手架strapi后端

在终端中,创建一个新的文件夹blog。这是我们的应用程序所在的地方:

    mkdir blog
    cd blog

要创建一个strapi项目,run /blog终端目录中的以下命令记住要插入您的自定义应用程序名称:

    npx create-strapi-app@latest <app-name> --quickstart
    # or
    yarn create strapi-app <app-name> --quickstart

这将生成一个Strapi项目。 --quickstart标志使用SQLite数据库配置我们的Strapi应用程序。如果提示在运行命令后继续安装,请键入'y'。允许Strapi及其依赖项完成安装。

完成安装后,您将被重定向到Strapi Admin面板:浏览器上的http://localhost:1337/admin,您将被要求注册。输入您的详细信息并注册。

下一步是使用Strapi Admin面板创建博客集合类型。

我们正在构建博客应用程序,每个博客文章都将具有以下模型:

    blog {
            title
            description
            draft
            imageUrl
        }

创建博客收藏类型

在管理面板上,在侧边栏中,单击内容类型构建器按钮。这将使我们进入内容类型构建器插件页面。单击+创建新收藏类型。这将弹出创建收藏类型模式。

输入显示名称blog,Strapi将自动生成我们的 api iD(单数) api id(plural),这里:

strapi blog

之后,单击继续,以带有收集类型的字段选项的模态。

select field type

在上面的模态框中选择文本。将出现添加新的文本字段模式。对于字段名称,输入title,为字段选择Short text type ,然后单击+添加另一个字段

strapi collection field

这些都是我们将添加到我们的集合中的所有字段和类型:

  • 字段名称 title;类型文本 Short text
  • 字段名称 description;类型文本 Long text
  • 字段名称 draft;类型丰富的文本
  • 字段名称 imageUrl;类型文本 Short text

将上述字段添加到博客集合中后,单击完成按钮。这将带有您刚刚创建的四个字段的Blog集合类型的视图:

saving strapi collection field

单击保存,然后等待服务器完全重新启动。

STRAPI数据库将在服务器重新启动完成后使用新创建的博客集合类型进行更新。

播种数据库

接下来,我们将为数据库添加内容。单击侧边栏上的内容管理器。在收集类型下,选择博客。

然后,单击+创建新条目按钮以创建博客的条目数据。

我们可以输入以下数据以获取我们的条目:
creating strapi blog post

在上面的条目中,我们以宣传格式编写了Blog draft内容; strapi允许我们将标记添加到丰富的文本类型。

单击保存,然后发布以发布博客条目。我们可以根据需要创建尽可能多的博客文章。

让我们再添加一个条目:

creating strapi blog post

单击保存,请记住发布所有新博客条目。

开放访问博客文章条目

默认情况下,只有身份验证的用户才能访问上面创建的新博客条目的端点。让我们向公众提供端点。为此:

  • 单击侧边栏上的设置
  • 用户和权限插件中,单击角色
  • 角色上 strapi roles
  • 向下滚动到权限节。
  • 选择博客并检查查找 findOne 复选框。通过此检查,我们仅允许公共端点检索OneAll 博客使用这些URL:

现在返回页面顶部,然后单击保存保存新角色设置。

我们现在可以继续设置我们的下一个.js ssg应用程序。

如何创建next.js SSG应用程序

从Next.js开始,就像在终端中运行一个命令一样简单。在博客文件夹目录中的新终端窗口中粘贴并运行以下代码:

    npx create-next-app blog-ssg

上面的代码将生成一个名为blog-ssg的next.js应用程序。接下来,在新项目目录中导航;在这里,我们将为我们的博客应用程序安装所需的依赖项。

在应用程序终端中运行以下命令:

    npm install front-matter marked

在上面的命令中,您正在安装:

  • 正面记录:此依赖性检查我们的草稿是否包含前结构标题属性,我们可以使用它轻松地将元数据添加到博客文章中。
  • 标记:此依赖性用于解析降级到html字符串

安装完成后,我们可以通过运行以下命令来启动我们的应用程序:

    npm run dev

当我们的应用程序启动和运行时,我们可以打开浏览器并访问http://localhost:3000以查看我们的New Next.js App。

next.js使我们为每个页面选择最佳的预渲染技术变得非常简单。在开始开发SSG应用程序之前,我们必须首先设置应用程序的环境变量,造型, config

blog-ssg的根目录中,我们将创建一个新的.env文件。在.env文件中输入以下内容:

    NEXT_PUBLIC_STRAPI_URL="http://localhost:1337/api"
    DOMAIN="i.imgur.com"

在上面的代码块中,我们将应用程序凭据存储在.env文件中。当我们部署应用程序并保护敏感数据时,这有助于从开发到生产的过渡。

接下来,我们将设置应用程序。在样式文件夹中,将styles/Home.module.css文件中的代码替换为下面的CSS代码。该文件包含我们的应用程序样式:

    .container, .post {
    width: 100%;
    min-height: 100vh;
    margin: 0  auto;
    padding: 40px  0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    }
    .container  h1, .post  h1 {
    font-size: 2em;
    }
    .card {
    display: flex;
    flex-direction: row;
    justify-content: center;
    flex-wrap: wrap;
    padding: 40px  0;
    }
    .flexing {
    width: 30%;
    box-sizing: content-box;
    background: #f8f6f8;
    margin: 1%;
    padding: 30px;
    border-radius: 8px;
    }

接下来,要保护我们的应用程序免受Next.js应用程序中的恶意用户的侵害,我们必须定义我们的图像域提供商。将next.config.js文件中的配置更改为:

    /** @type {import('next').NextConfig} */
    const nextConfig = {
      reactStrictMode: true,
      swcMinify: true,
      images: {
        domains: [`${process.env.DOMAIN}`]
      },
    };

    module.exports = nextConfig

我们在此处使用.env文件的环境变量DOMAIN。可变DOMAIN包含我们图像供应商的域名。我们现在可以开始在SSG应用程序页面上工作。

在我们的Next.js应用程序中,导航到page/index.js文件。这是渲染我们的应用程序主页的地方。在这里,我们将使用next.js getStaticProps函数将道具传递给我们的组件。

复制并将以下代码粘贴到page/index.js文件中:

    import Head from "next/head";
    import Image from "next/image";
    import Link from "next/link";
    import styles from "../styles/Home.module.css";

    export const getStaticProps = async () => {
      const resulting = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/blogs`);
      const result = await resulting.json();
      return {
        props: {
          result: result.data,
        },
      };
    };

    export default function Home({ images, result }) {
      return (
        <>
          <Head>
            <title>thisBlog</title>
            <meta title="description" content="This is an example of our blog" />
          </Head>
          <div className={styles.container}>
            <h1>Blog Post Links:</h1>
            <div className={styles.card}>
              {result.map(result => {
                return (
                  <div className={styles.flexing} key={result.id}>
                    <Link href={`/blog/${result.id}`}>
                        <Image
                          src={`${result.attributes.imageUrl}`}
                          alt="blog-post"
                          priority={true}
                          className="rounded-full"
                          width={300}
                          height={300}
                        />
                        <h2>{result.attributes.title}</h2>
                        <div>
                          <p>{result.attributes.description}</p>
                        </div>
                    </Link>
                  </div>
                );
              })}
            </div>
          </div>
        </>
      );
    }

在上述代码块中,我们:

  • 导入Next.js构建我们的SSG页面所需的所有依赖项
  • 使用函数getStaticProps。这是Next.js介绍的功能,可用于生成静态站点。 getStaticProps函数用于获取我们博客文章的内容,并将其作为props传递给Home组件。
  • 破坏并利用了家用组件中的getStaticProps功能返回的道具。
  • 使用Next.js Head设置页面的元数据。
  • Link是我们可以用来导航页面的Next.js的特殊组件。

我们的next.js应用程序主页正在运行并利用来自Strapi Backend CMS的博客数据。我们的应用程序应在保存和运行浏览器中的http://localhost:3000路线后显示如下:

blog homepage

voilaðä!!

现在我们拥有主页,我们现在可以为每个博客文章创建动态页面模板。

在Next.js中,如果我们想要动态页面,我们必须首先创建动态路由,可以通过将文件名封闭在方括号中([id])(a.k.a. url slugs,pretty urls等)来创建动态路由) 。

从技术上讲,我们可以输入[ID]的任何值,并且该页面将加载到特定的路径名​​。这就是Next.js生成动态页面的方式。然后,在文件中,我们创建一个组件并导出它,next.js基于该组件为我们生成了路由。

让我们为我们的博客文章制作动态页面。在我们应用程序的page文件夹中,创建一个新的文件夹博客。现在,在新创建的博客文件夹中,创建一个名为[id].js的文件。

在新文件pages/blog/[id].js中输入以下代码:

    import React from "react";
    import fm from "front-matter";
    import Head from "next/head";
    import { marked } from "marked";
    import Image from "next/image";
    import styles from "../../styles/Home.module.css";

    export const getStaticPaths = async () => {
      let result = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/blogs`);
      result = await result.json()
      return {
        paths: result.data.map(result => ({
          params: { id: result.id.toString() },
        })),
        fallback: false,
      };
    };

    export const getStaticProps = async ({ params }) => {
      const res = await fetch(
        `${process.env.NEXT_PUBLIC_STRAPI_URL}/blogs/${params.id}`
      );
      const markdownWithMeta = await res.json();
      const parsedMarkdown = fm(markdownWithMeta.data.attributes.draft);
      const htmlString = marked(parsedMarkdown.body);
      const image = markdownWithMeta.data.attributes.imageUrl;
      return {
        props: {
          image,
          htmlString,
          data: parsedMarkdown.attributes,
        },
      };
    };

    export default function Post({ image, htmlString, data }) {
      return (
        <>
          <Head>
            <title>{data.title}</title>
            <meta name="description" content={data.description} />
          </Head>
          <div className={styles.post}>
            <Image
              src={`${image}`}
              alt="blog-post"
              priority={true}
              className="rounded-full"
              width={600}
              height={400}
            />
            <div dangerouslySetInnerHTML={{ __html: htmlString }} />
          </div>
        </>
      );
    }

在上面的代码块中:

  • 此文件包含我们的博客文章[id].js动态路由模板。
  • 要动态设置我们的元数据,我们还导入了front-matter依赖关系。
  • 此外,mark依赖关系将我们的草稿的降价转换为HTMLString
  • 我们正在使用next.js getStaticPath此函数将返回带有一个数组的路径属性的对象,并且fallback设置为false,这意味着getstaticpaths未返回的任何路径都会在404页中导致。<<<<<<<<<<<<<<<<<<<<<<<<<<< /li>
  • getStaticProps函数中,我们正在返回我们的image htmlstring和parsedmarkdown。
  • parsedmarkDown包含我们的页面元数据,而HTMLString是我们转换后的元数据。所有这些都以要传递到Post组件的道具对象发送。
  • dangerouslySetInnerHTML Prop提供为React的替代DOM元素的InnerHTML属性。

保存您的工作,然后转到浏览器。当我们单击博客文章时,我们将被带到看起来像这样的新页面:

Blog Post Image

现在,一切都设置了,我们可以自动生成页面并使用我们的Strapi CMS创建新的博客文章。我们需要考虑的最后一件事是如何部署和添加Webhooks在数据更新时自动构建应用程序。

部署strapi和next.js应用程序

要成功使用Strapi Webhooks,我们必须部署我们的应用程序。 Strapi为我们提供了许多部署CMS后端的选项。将您的Strapi应用程序部署到您的preferred host provider

我们的Next.js应用程序将部署在Vercel上。在我们可以将Next.js SSG应用程序部署到Vercel之前,我们必须首先将blog-ssg应用程序上传到GitHub。

在此阶段,我们将将下一个项目推向GitHub。如果您是Github的新手,follow this article,您会没事的。

成功推到github后,应在git回购上显示类似的图像。

Repo Image

让我们现在部署到Vercel。如果您是新手,则带有GitHub帐户的sign up and register

对于导入git存储库选项选择继续使用github

vercel

接下来,单击我们的blog-ssg项目的导入按钮:

vercel

接下来,填写项目名称 blog-ssg。对于环境变量,插入:

  • NEXT_PUBLIC_STRAPI_URL:这是我们部署的Strapi CMS的URL。
  • DOMAIN:这是我们博客文章图像提供商的域名。 setting env variable

最后,单击Deploy按钮。恭喜!我们刚刚将SSG应用程序部署到Vercel。

Strapi Webhook设置

最后,webhook将在听众中操作,只要对博客数据进行更改,就可以简单地提醒和更新我们已部署的静态生成的应用程序。从本质上讲,这是一种解决方案,允许应用程序相互通知和跟踪事件。

设置strapi webhook只需要几个简单的步骤:

  • 为了使用Webhook启动部署并重新启动我们的应用程序,我们必须首先建立HTTP POST URL钩。要实现这一目标,请转到我们的Vercel仪表板的设置部分,选择Git向下滚动,然后单击Create Hook

    我们可以给挂钩任何名称,但是在这种情况下,我们称其为应用程序挂钩并说明 main ,这意味着当激活挂钩时,应用程序为main分支将被重建并重新部署。要创建我们的挂钩URL,请单击创建挂钩按钮。
    webhook

  • 复制生成的应用程序钩 URL。要将钩子连接到我们的数据库,请导航到已部署的Strapi仪表板。在设置菜单中。选择 webhooks ,然后单击+创建新的webhook 按钮。

给Webhook一个您选择的名称,然后将应用程序挂钩 url链接粘贴到Vercel中。最后,在下面的事件部分中,选择您希望Webhook聆听和提醒我们的静态网站的所有操作。

单击保存。

webhook

我们的应用程序已完成,并在数据库中有活动的Webhook侦听事件更新。要测试触发我们的Webhook,让我们为应用程序创建一个新的博客文章。

我们可以在下面看到我们的Webhook,我们发布了一篇新博客文章,我们的Strapi Webhook通知SSG网站以重建和更新其数据:

webhook in action

结论

Webhooks是您应用程序相互通知并在发生新事件时接收通知的一种简单方法。希望您喜欢阅读这篇文章。有关如何在strapi应用程序中使用webhooks的更多信息,您可以在此处检查: