如何使用WordPress、Next.js和GraphQL查询(WPGraphQL)创建一个无头CMS网站

287 阅读9分钟

如何使用WordPress、Next.js和GraphQL查询(WPGraphQL)创建一个无头CMS网站

在当前的网络世界中,建立一个网站可能会让人不知所措,尤其是在没有极端的建站知识的情况下。但是,如果有一个完善的、现成的内容管理系统,如WordPress,建立一个网站会更容易。

WordPress是一个开源的内容管理系统(CMS)。内容管理系统是一种在网络服务器上运行的软件,用于托管现成的和可定制的网站模板。这意味着你可以免费使用或修改WordPress建立一个成熟的网站。

作为一个CMS,它允许你管理网站的不同方面,如改变WordPress的外观,添加和修改内容,以及增强搜索引擎。

然而,由于WordPress对初学者友好,其后端技术是服务器端渲染(SSR)。这暗示你可能会遇到一些比其他技术(如Next.js)更高的性能开销。WordPress的内容是直接从服务器上提供的。

每一个请求都要经过服务器,请求提供必要的资源。由于有许多请求需要处理,当请求流量增加时,处理能力较弱的服务器会不堪重负。

Next.js等技术支持混合内容生成。他们同时支持静态网站生成的SSR和CSR。这意味着服务器端的内容是提前提供的。

Next.js使用静态渲染页面的生成器,使其提前加载。有了Next.js这样的卓越技术,你可以把它们与WordPress等CMS结合起来,以无头方式运行。这样,WordPress将运行一个无头的CMS。这将产生一个具有良好用户体验的高性能网站。

前提条件

以下先决条件将帮助你浏览本教程。

  • 对[Next.js]的工作有基本了解。
  • 充分了解[WordPress的工作原理]以及[如何使用它来建立网站]。

什么是无头CMS

在WordPress CMS中,后台(你管理内容的地方)和前台(向网站访问者显示内容的地方)被整合为一个整体系统。当WordPress作为一个无头CMS运行时,内容和内容展示都是解耦的。

这使得内容展示层变得灵活。你现在可以建立一个网站或一个移动应用程序来呈现原始的WordPress驱动的内容。后台和前端不再与CMS捆绑在一起。

你仍然有WordPress CMS用于内容创建,以及保存在数据库中的管理。唯一的区别是,内容呈现是通过应用编程接口(API)作为原始数据格式(如JSON)交付的。然后在网站、移动应用程序或任何其他渠道和设备中展示这些数据。

将WordPress作为无头CMS运行的原因

  • 它使你能够在你想要的时候改变内容交付渠道,而无需重新编写内容。
  • 由于内容是通过API以原始数据的形式交付的,你可以使用任何你希望的技术来展示这些数据。作为一个开发者,这使你能够专注于最重要的事情,例如为你的用户创造伟大的数字体验。
  • API驱动的数据促进了全渠道架构。你创建WordPress的内容,并通过API来引导它。因此,内容在所有接触点上都会发光。
  • 它创造了更有效、可扩展和更快的应用程序。后台和前台都与单片机CMS架构分离。如果WordPress支持的CMS有任何问题,渠道交付管道将不会受到影响。因此,交付渠道的性能不会受到影响。

在本指南中,我们将学习如何使用Next.js将WordPress作为无头CMS运行。

让我们深入了解一下。

添加一个帖子

首先,到你的远程WordPress网站管理仪表板去。

由于WordPress和Next.js是用来开发基于博客的网站,我们将使用这个方案,首先在WordPress管理中添加和发布一个帖子。

然后,从你的WordPress管理仪表板,导航到posts ,添加一个category 。在产生的页面的左窗格中,输入一个名称、slug和帖子类别的描述,然后点击按钮Add new category

下图显示了如何设置这些字段。

add-post-category

现在添加一个新的帖子。从管理仪表板,导航到左边的侧栏,点击posts 。在由此产生的右侧弹出窗口中,点击Add new

在出现的面板上,输入标题和一些假内容,如下所示。

add-post-form

WordPress博客中的每篇发表的文章都可以与一个特定的类别相关联。在右侧,点击Post 标签。

Categories 菜单标签中,选中你在上一步创建的类别。

post-category-selection

如果你想添加一个特色图片,你可以在Featured image 菜单标签中这样做。在Excerpt 菜单选项卡中,添加一个帖子的简短描述。

post-excerpt

完成后,导航到右上角,点击Publish ,你的帖子就会上线。

post-publish-button

这样,你就有一个帖子了。重复这个过程几次,以便有几个帖子可以查询。

安装WpGraphQL插件

WPGraphQL是一个免费的、开源的WordPress插件,为任何WordPress网站提供一个可扩展的GraphQL模式和API。我们将使用它来获取GraphQL模式,以帮助WordPress的API与Next.js通信。让我们继续安装这个插件。

从仪表板的左侧边栏,导航到插件。在右侧弹出的窗口中,点击Add new

在搜索栏中,搜索WpGraphQL

plugins-search-bar

在下面的结果中点击Install now

wp-graphql-plugin

一旦安装结束,确保激活该插件。

wp-graphql-plugin

从GraphiQL IDE运行查询

在你的WordPress网站上安装该插件后,你将在左侧边栏的底部有一个GraphQL 标签。导航到它,在弹出的窗口中,点击GraphiQL IDE 。这将使你重定向到一个GraphQL操场,在那里你可以写你的查询。

为了查询我们已经发布的帖子,我们将使用以下GraphQL模式。

query postsQuery{
  posts{
      edges{
      node{
          title
          categories{
          edges{
              node{
              name
              }
          }
          }
          excerpt
          slug
          content
      }
      }
  }
 }

我们从上述查询中获取所有的帖子,每个查询都会得到帖子的标题、类别、摘要和内容。在左侧窗格中,粘贴上述查询。然后,通过点击播放按钮执行查询,如图所示。

wp-graphql-playbutton

设置Next.js环境

要设置Next.js环境,请遵循以下步骤。

  • 通过运行以下命令,使用create-next-app创建一个简单的Next.js应用程序。
npx create-next-app cms-wordpress-app
  • 将创建一个文件夹cms-wordpress-app ,其中将包含开始处理Next.js项目的所有必要文件。使用Change Directory (cd) 命令,进入我们创建的项目文件夹cms-wordpress-app
cd cms-wordpress-app
  • 为了测试一切是否正常,运行以下命令,启动Next.js开发服务器。
npm run dev

上面的命令将在3000端口启动开发服务器,并将其暴露在你的本地主机上。打开你的浏览器,访问http://localhost:3000 。一个Next.js的模板博客将在你的浏览器上提供。

使用GraphQL模式将WordPress API添加到Next.js中

如下图所示,在根目录下创建一个.env.local 文件和一个WORDPRESS_API_URL

WORDPRESS_API_URL=your_wordpress_api_url

要获得你的API_URL

  • 进入你的WordPress管理页面。
  • 在左边的侧栏,点击GraphQL。
  • GraphQL端点下获得你的URL。

wpgraphql-endpoint

连接到WordPress CMS

为了连接到WordPress CMS,创建一个名为lib 的文件夹。在这个文件夹中,我们将处理从我们的应用程序到WordPress CMS的连接。

pages 文件夹里有一个api.js 文件,我们将在这里实现与WordPress API通信的各种功能。

因此,在api.js 文件中,通过添加这一行,得到我们保存在env.local 文件中的API_URL

const API_URL = process.env.WORDPRESS_API_URL;

配置一个要调用的函数来发送请求给API,如下图所示。

async function fetchAPI(query, { variables } = {}) {
    const headers = { 'Content-Type': 'application/json' }

    if (process.env.WORDPRESS_AUTH_REFRESH_TOKEN) {
      headers[
        'Authorization'
      ] = `Bearer ${process.env.WORDPRESS_AUTH_REFRESH_TOKEN}`
    }

    const res = await fetch(API_URL, {
      method: 'POST',
      headers,
      body: JSON.stringify({
        query,
        variables,
      }),
    })

    const json = await res.json()
    if (json.errors) {
      console.error(json.errors)
      throw new Error('Failed to fetch API')
    }
    return json.data
  }

上述函数将收到两个参数;要运行的查询和要与查询一起传递的变量。然后,我们将使用该查询从CMS中获取数据。

该请求将以POST方式使用Fetch发送。如果在运行查询时发生错误,将抛出一个消息,否则将返回数据。

取回所有WordPress的帖子

添加一个函数来获取所有的帖子,如下所示。

export async function getPosts(){
    const data = await fetchAPI(
        `query AllPosts {
          posts(first: 20) {
            edges {
              node {
                title
                categories{
                edges{
                    node{
                    name
                    }
                }
                }
                excerpt
                slug
                author {
                  node {
                    name
                    firstName
                    lastName
                  }
                }
              }
            }
          }
        }
      `,
        {
          variables: {},
        }
      );
    return data?.posts?.edges;
}

在上面的代码中,我们向WordPress API发送一个请求,以获取前20个帖子。

获取一个WordPress的帖子

同样地,我们可以添加一个函数来获取一个帖子,如下所示。

export async function getSinglePost(id){
    const data = await fetchAPI(`
    query getSinglePost($id:ID!){
        post(id:$id){           
              title
              categories{
              edges{
                  node{
                  name
                  }
              }
              }
              excerpt
              content
              slug
              id
              author {
                node {
                  name
                  firstName
                  lastName
                }
              }
        }
      }
    `,{id});

    return data?.post;
}

在上面的函数中,我们收到了我们想要获取的帖子的ID,并将它与查询一起发送,以获取其具体数据。

为了在我们的应用程序中显示这些帖子,我们将利用getServerSideProps()方法。该方法将在每次请求中运行,以便从CMS中获取数据。

该方法将在主页上实现,在那里我们获取所有的帖子,并在一个特定的帖子页面上实现。

要在主页上实现这个方法,请按照以下步骤进行:pages/index.js

  • 让我们导入getPosts 函数。
import {getPosts} from "../lib/api";
  • Home 函数的下面,调用getServerSideProps() ,如下图所示。
export async function getServerSideProps(ctx){
  let posts = await getPosts();
  return {
    props:{
      posts
    }
  }
}

在上面的getServerSideProps() 中,我们正在调用getPosts() 函数来获取帖子,并在props 对象中返回它们。这些数据将被发送到组件中。我们必须得到它并通过它来显示帖子。

  • 编辑Home 函数,如下图所示。
export default function Home({posts}) {
    return (
      <div className={styles.container}>
        <Head>
          <title>CMS blog</title>
          <meta name="description" content="CMS Wordpress with Next.js" />
          <link rel="icon" href="/favicon.ico" />
        </Head>

        <main>
        {
          posts.map((post,index) => (
            <div key={index}>

              <Link href={`/posts/${post.node.id}`}>
              <a style={{color:'blue'}}>{post.node.title}</a>
              </Link>
              
              <div dangerouslySetInnerHTML={{__html:post.node.excerpt}} />

              <p>By {post.node.author.node.name}</p>
            </div>
          ))
          }
        </main>

        <footer className={styles.footer}>
          <p>Posts</p>
        </footer>
      </div>
    )
  }

在上述函数中。

  • 我们正在获取从getServerSideProps() 发送的帖子。
  • 通过帖子的映射,为每个帖子显示标题、摘要和作者。标题是一个指向特定帖子页面的链接。

测试

为了测试,让我们使用以下命令确保开发服务器已经启动并运行。

npm run dev

在你的浏览器中,导航到http://localhost:3000 。你的帖子将根据你添加到WordPress博客的帖子来显示。

posts-page

用单篇文章测试

要显示一个单一的帖子页面,请导航到pages 目录并创建posts 目录。在posts 目录内,创建[id].js 文件。

[] 标志着该ID将是动态的。

[id].js 文件中,导入getSinglePost 函数。

import {getSinglePost} from "../../lib/api";

这个函数做两件事。

  • 它获取从getServerSideProps() 发送的帖子。
  • 它通过帖子进行映射,为每个帖子显示标题、摘要和作者。标题是一个指向特定帖子页面的链接。

接下来,实现getServerSideProps() ,如下所示。

export async function getServerSideProps(ctx){
    let {id} = ctx.params;
    let post = await getSinglePost(id);
    
    return {
        props:{
            post
        }
    }
}

从上面的代码块中,我们得到帖子的ID,根据该ID获取帖子,并将帖子发送到props对象内。下一步是为视图实现一个函数。

要做到这一点,从Next.js导入styles 模块和Head 包。

import Head from "next/head";
import styles from '../../styles/Home.module.css';

接下来,创建一个Post 函数,如下图所示。

export default function Post({post}) {
    return (
        <div className={styles.container}>

            <Head>
                <title>{post.title}</title>
            </Head>
            <main>                
                <div dangerouslySetInnerHTML={{__html:post.excerpt}} />
                <br />
                <br />
                <div dangerouslySetInnerHTML={{__html:post.content}} />
            </main>

        </div>
    )
}

在这里,我们得到传递的帖子,并通过显示其标题、摘录和内容,将其呈现在上述函数的视图中。你可以随意显示你想要的字段,但要确保它们在查询中。

为了测试这个,确保开发服务器正在运行,我们可以通过运行来启动它。

npm run dev

在你的浏览器中,导航到http://localhost:3000

post-page

要测试实现,请点击主页上的任何帖子的标题。你应该被重定向到一个单一的帖子页面。然后,点击后面的箭头,探索其他的帖子。

结论

我们已经成功地在WordPress中创建帖子,查询,并从Next.js应用程序中显示它们。要想获得有关各种技术和概念的更深入的知识,请查看参考资料部分列出的资源。