제퍼넷 로고

워드 프레스 데이터로 개츠비 사이트 만들기

시간

내에서 이전 기사 지난주에 부분적으로 포팅되는 것을 언급했습니다 WordPress-Gatsby 사이트. 이 기사는 후드 아래의 단계별 연습을 통해 계속됩니다.

개츠비정적 사이트를위한 React 기반 프레임 워크 인 JavaScript는 JavaScript 개발자뿐만 아니라 WordPress 개발자 및 사용자로부터도 주목을 받고 있습니다. 초고속 이미지 처리 및 해커의 향상된 보안 보호와 같은 많은 WordPress 사용자는 매력적인 기능을 발견하지만 WordPress 관리자 및 편집기를 사용하여 콘텐츠를 계속 관리하면서 기능을 사용하려고합니다.

크리스는 개츠비와 워드 프레스 결합 CSS-Tricks에 앞서. 워드 프레스 애호가로서, 나는 그것을 시도하기로 결정했습니다. 이 기사는 내가 배우고 문서화 한 내용을 기반으로합니다.

참고하여 주시기 바랍니다 WPGraphQL개츠비 클리 이후 버전의 변경 사항을 유지하면서 지속적으로 개발하고 있습니다. 이 프로젝트는 WPGraphQL 0.8.3gatsby-source-wpgraphql 2.5.1 및 gatsby-cli 2.12.21을 참조하십시오. WordPress와 달리 최신 WPGraphQL 릴리스는 이전 버전과의 호환성을 지원하지 않습니다. 담당자에게 문의하십시오 WPGraphQL & 개츠비 박사 최신 변경 사항을 확인하고 사용하기 전에주의하여 진행하십시오.

바로 사용할 수있는 프로젝트가 있습니다 개츠비 스타터 도서관. 두 가지 훌륭한 예는 Alexandra Spalato 's입니다 개츠비 워드 프레스 테마 블로그 그리고 스물 아홉 개츠비 테마 Zac Gordon과 Muhammad Muhsin이

사전 조건

따라하고 싶다면 다음이 필요합니다.

자산과 자원

과거에 Gatsby 학습 프로젝트를 이미 수행 했으므로 타이포그래피, 레이아웃 및 기타 재사용 가능한 구성 요소와 같은 자산을 적용 할 수있었습니다. 또한이 프로젝트를 준비하는 데 도움이되는 다음과 같은 최신 자습서 안내서를 살펴 보았습니다.

헨릭 위스의 가이드는 완전 이해와 철저합니다. Jason의 단계별 기사는 훌륭한 리소스이며 프로세스가 진행되는 것을 볼 수있는 유용한 비디오를 포함합니다. Muhammad의 기사는 Gatsby의 정적 페이지를 작성하는 방법을 설명합니다. 페이지 만들기 API 및 다양한 기능, 템플릿 파일 및 React 구성 요소를 분류합니다.

나는 크게 따랐다 Henrik 님의 가이드 이 기사를 비슷한 섹션으로 나누었습니다. Henrik 님의 가이드 포함 이미지 처리 추가 ACF Flexible Content 기능이있는 PageBuilder 우리는 여기에 들어 가지 않습니다.

섹션 1 : WordPress 및 Gatsby 설정

먼저, 데이터 소스를위한 WordPress 사이트를 설정해 봅시다. 기존 사이트이거나 새로운 사이트 일 수 있습니다. 로컬 워드 프레스 설치도 괜찮습니다. 나는이 프로젝트를 위해 새로운 테스트 WordPress 사이트로 시작하기로 결정했습니다. 스물 스물 스물 테마 WordPress와 함께 제공됩니다.

WPGraphQL 및 WPGraphiQL 플러그인 설치

WordPress에 몇 가지 플러그인을 설치하여 시작해 봅시다. 우리는 사용할 것이다 WPGraphQL WordPress에서 GraphQL API를 활성화하고 데이터 소스로 WordPress를 엽니 다. 우리는 또한 사용할 것입니다 WPGraphiQL (이름에서“i”를 참고하십시오). 이것은 실제로 선택 사항이지만 WordPress 대시 보드에서 직접 GraphQL 쿼리를 테스트하기위한 인터페이스를 생성하므로 매우 편리합니다. 당신은 내가 연결하는 것을 알 수 있습니다 GitHub 저장소 WordPress 플러그인 디렉토리 대신 플러그인의 경우 의도적입니다.이 글을 쓰는 시점에는 디렉토리에서 플러그인을 사용할 수 없습니다. 따라서 ZIP 파일을 다운로드하여 수동으로 WordPress에 설치합니다. /wp-content/plugins 디렉토리.

활성화되면 그라피큐엘 API가 WordPress 대시 보드에 표시됩니다.

XNUMXD덴탈의 GraphiQL API는 테스트 할 놀이터를 제공합니다 GraphQL WordPress 사이트에서 쿼리합니다.

WordPress 대시 보드에서 GraphQL 플레이 그라운드 인터페이스의 스크린 샷
GraphiQL 화면은 XNUMX 개의 패널을 제공합니다. 하나는 서로 다른 객체 사이를 탐색하기위한 것입니다 (왼쪽), 하나는 데이터를 쿼리하기위한 것입니다 (가운데), 다른 하나는 반환 된 데이터를 시각화하기위한 것입니다 (오른쪽).

로컬 개츠비 사이트 설정

우리는 설치하여 로컬 개츠비 사이트를 설정합니다 개츠비의 스타터 기본값 FBI 증오 범죄 보고서 wordpress-gatsby 커맨드 라인에서 이것을 가진 프로젝트의 디렉토리 :

#! create a new Gatsby site using the default starter
gatsby new wordpress-gatsby https://github.com/gatsbyjs/gatsby-starter-default

로 서버를 다시 시작하십시오. gatsby develop으로 이동하여 localhost:8000 새 브라우저 탭에서 브라우저에서 시작 페이지를 가져와야합니다.

에 대한 링크 개츠비 사이트를 로컬로 만드는 방법 Gatsby 문서에서 구할 수 있습니다.

다음으로, 우리는 설치하고 구성 할 것입니다 개츠비 소스 그래프 플러그인. WordPress를 설정할 때와 마찬가지로 설치 및 구성해야합니다 WPGraphQL 개츠비 사이트에서.

#! install wpgraphql plugin
#! add with yarn
yarn add gatsby-source-graphql
#! install with npm
npm install --save gatsby-source-graphql

이제 구성 할 차례입니다. 개츠비 소스 그래프 플러그인. 열어 gatsby-config.js 파일을 만들고 다음 설정을 사용하겠습니다.

// plugin configuration
module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-graphql",
      options: {
        typeName: "WPGraphQL",
        fieldName: "wpcontent",
        // GraphQL endpoint, relative to your WordPress home URL.
        url: "https://tinjurewp.com/wp-gatsby/graphql",
        // GraphQL endpoint using env variable
       // url: "${process.env.WORDPRESS_URL}/graphql",
      },
    },
  ],
}

이 정확한 구성을 어떻게 얻었습니까? 나는 엄격히 따랐다 개츠비 문서에 설명 된 내용. 플러그인은 GraphQL 엔드 포인트의 URL (위에서 강조 표시됨)과 두 가지 구성 옵션을 지정하여 Gatsby 인스턴스에 추가되었습니다. typeName, 원격 스키마 쿼리 유형 및 fieldNameGatsby 쿼리에서 사용할 수 있습니다. 양해 바랍니다 최신 WPGraphQL 문서 사용 제안 fieldName: "wpcontent" 대신 "wpgraphql"에 설명 된대로 안내.

대체 설정 : dotenv 모듈 사용

선택적으로 우리는 dotenv npm 모듈 정의하기 환경 변수 개발 환경을 사용자 정의하는 데 사용됩니다. Henrik는이 방법을 그의 안내 뿐만 아니라.

이 방법을 사용하는 경우 .env.production 플러그인 구성 파일 WORDPRESS_URL, WordPress URL을 노출하는 대신 정의하여 사용할 수 있습니다.

# .env.production
# Don't put any sensible data here!!!
WORDPRESS_URL=https://tinjurewp.com/wp-gatsby/

내 테스트 환경은 WordPress 인스턴스와 데이터를 동일하게 노출합니다. WPGraphQL.

Colby Fayock에는 유용한 단계별 가이드가 있습니다 Gatsby 및 Netlify와 함께 환경 변수 사용에 대해

개발 서버를 다시 시작한 후 WPGraphQL API Gatsby와 함께 WordPress 사이트에서 쿼리 된 특정 데이터를 쿼리 및 검색하고 로컬 호스트 GraphQL URL을 통해 Gatsby 사이트에 표시 할 수 있습니다. https//localhost:8000/___graphql/.

왼쪽에 탐색기가 있고 가운데에 쿼리가 있고 오른쪽에 반환 된 데이터가있는 GraphQL 쿼리 인터페이스를 보여주는 스크린 샷
WordPress 사이트 자체와 달리 여기의 데이터는 WPGraphQL에 노출됩니다. WPGraphQL API에 대해 쿼리하여 WordPress 사이트의 모든 필드를 표시 할 수 있습니다.

섹션 2 : WordPress에서 게시물 및 페이지 포팅

Gatsby에서는 GraphQL로 데이터를 쿼리하고 쿼리 결과를 게시물 또는 페이지 템플릿에 매핑하여 빌드시 게시물 및 페이지를 만들 수 있습니다. 프로세스는 개츠비 튜토리얼 프로그래밍 방식으로 데이터에서 페이지를 만드는 방법 개츠비는 두 가지 API를 사용합니다. onCreateNodecreatePages, 자습서에는 구현 방법에 대한 자세한 설명이 포함되어 있습니다.

여기의 코드 스 니펫은 Henrik 님의 가이드. WordPress가 다른 데이터 형식 및 범주로 데이터베이스에 데이터를 저장하는 방식으로 인해 모든 내용을 포팅하는 것이 간단하지 않은 것으로 나타났습니다. 그러나 Gatsby를 사용하여 페이지 및 게시물을 작성하는 데 대한 사전 지식이 있으면 createPages API와 노드 API따라갈 수있었습니다. 실제 세계도 많이 있습니다 초보자 사이트 예를 들어 참조 할 수 있습니다.

1 단계 : WordPress 사이트에 게시물 및 페이지 컨텐츠 추가

아직없는 경우 WordPress 사이트에 게시물과 페이지를 추가하십시오. 해당 컨텐츠에 대한 페이지를 작성하기 전에 삭제해야합니다 index.jspage-2.js Gatsby 사이트의 페이지 폴더에서 이 두 파일은 이식 된 WordPress 데이터를 방해하는 것 같습니다.

2 단계 : 페이지 및 게시물 템플릿 만들기

콘텐츠 용 템플릿 파일 XNUMX 개, 게시물 용 템플릿 파일 (/src/templates/posts/index.js) 및 페이지 (/src/templates/pages/index.js).

게시물 템플릿은 다음과 같습니다. 기본적으로 게시물 제목은 SEO 페이지 제목으로, 제목은 게시물 제목으로 두 번, 게시물 내용은 게시물 구성 요소로 사용합니다.

// src/templates/post/index.js
import React  from "react"
import Layout from "../../components/layout"
import SEO from "../../components/SEO"


const Post = ({ pageContext }) => {
  const post = pageContext.post


  return (
    <Layout>
      <SEO title={post.title} />


      <h1> {post.title} </h1>
      <div dangerouslySetInnerHTML={{__html: post.content}} />


    </Layout>
  )
}


export default Post

페이지 템플릿에 대해 거의 동일한 작업을 수행합니다.

//src/templates/pages/index.js import React  from "react"
import Layout from "../../components/layout"
import SEO from "../../components/seo"


const Page = ({ pageContext }) => {
  const page = pageContext.page


  return (
    <Layout>
      <SEO title={page.title} />


      <h1>{page.title}</h1>
      <div dangerouslySetInnerHTML={{__html: page.content}} />


    </Layout>
  )
}


export default Page

3 단계 : createPages API를 사용하여 정적 게시물 및 페이지 작성

여기서 다루는 전체 코드는 node.js 파일. 그러나 읽기 쉽도록 게시물과 페이지는 이름이 지정된 폴더로 구분됩니다. create 다음 프로젝트 루트 디렉토리에서 Henrik 님의 가이드.

GraphQL로 손이 더러워 질 것입니다. createPages API! 우리는 다음을 추가하여 시작합니다 gatsby-node.js.

// gatsby-node.js
const createPages = require("./create/createPages")
const createPosts = require("./create/createPosts")


 exports.createPagesStatefully = async ({ graphql, actions, reporter }, options) => {
  await createPages({ actions, graphql, reporter }, options)
  await createPosts({ actions, graphql, reporter }, options)
 }

무하마드의 포스트 여기에서 호출 할 가치가있는 좋은 지적을합니다. 

XNUMXD덴탈의 생성페이지 API Gatsby가 공개하는 노드 API의 일부입니다. 본질적으로 Gatsby가 페이지를 추가하도록 지시합니다. 이 안에서 우리는 다음을 사용하여 몇 가지 메소드를 호출합니다. async/await (ECMAScript 2017의 기능).

즉, 두 함수 모두 관련 정적 페이지를 만듭니다. 이를 염두에두고 사용할 데이터를 정의하고 데이터를 가져 오도록하겠습니다. create/createPages.js 파일. 큰 코드 덤프는 유감이지만 Henrik의 의견은 현재 상황을 설명하는 데 도움이됩니다.

//create/createPages.js
const pageTemplate = require.resolve('../src/templates/page/index.js');


const GET_PAGES = `
  query GET_PAGES($first:Int $after:String) {
    wpgraphql {
      pages(
        first: $first
        after: $after
        # This will make sure to only get the parent nodes and no children
        where: {
          parent: null
         }
      ) {
        pageInfo {
         hasNextPage
         endCursor
        }
       nodes {
          id
         title
          pageId
         content
          uri
          isFrontPage
       }
      }
   }
  }
`


const allPages = []
let pageNumber = 0
const itemsPerPage = 10


/** This is the export which Gatbsy will use to process.
 * @param { actions, graphql }
 * @returns {Promise<void>} */
module.exports = async ({ actions, graphql, reporter }, options) => {


  /** This is the method from Gatsby that we're going
   * to use to create pages in our static site. */
  const { createPage } = actions
  /** Fetch pages method. This accepts variables to alter
   * the query. The variable `first` controls how many items to
   * request per fetch and the `after` controls where to start in
   * the dataset.
   * @param variables
   * @returns {Promise<*>} */
  const fetchPages = async (variables) =>
    /** Fetch pages using the GET_PAGES query and the variables passed in. */
    await graphql(GET_PAGES, variables).then(({ data }) => {
      /** Extract the data from the GraphQL query results */
      const {
        wpgraphql: {
          pages: {
            nodes,
            pageInfo: { hasNextPage, endCursor },
          },
        },
      } = data


      /** Map over the pages for later creation */
      nodes
      && nodes.map((pages) => {
        allPages.push(pages)
      })


      /** If there's another page, fetch more
       * so we can have all the data we need. */
      if (hasNextPage) {
        pageNumber++
        reporter.info(`fetch page ${pageNumber} of pages...`)
        return fetchPages({ first: itemsPerPage, after: endCursor })
      }


      /** Once we're done, return all the pages
       * so we can create the necessary pages with
       * all the data on hand. */
      return allPages
    })


  /** Kick off our `fetchPages` method which will get us all
   * the pages we need to create individual pages. */
  await fetchPages({ first: itemsPerPage, after: null }).then((wpPages) => {


    wpPages && wpPages.map((page) => {
      let pagePath = `${page.uri}`


      /** If the page is the front page, the page path should not be the uri,
       * but the root path '/'. */
      if(page.isFrontPage) {
        pagePath = '/'
      }


      createPage({
        path: pagePath,
        component: pageTemplate,
        context: {
          page: page,
        },
      })


      reporter.info(`page created: ${page.uri}`)
    })


    reporter.info(`# -----> PAGES TOTAL: ${wpPages.length}`)
  })
}

다시 말하지만, 무하마드의 포스트 그것이 무엇을 분해하기 때문에 훌륭한 도움입니다 createPages.jscreatePosts.js 기능은 할 수 있습니다. Henrik 님의 가이드 또한 각 단계에 유용한 의견을 제공합니다. 

4 단계 : 게시물 작성

XNUMXD덴탈의 createPosts.js 파일은 거의 동일합니다 createPages.js. 유일한 차이점은 경로 앞에 blog/ 코드 전체에서 '페이지'를 '게시물'로 바꿉니다.

여기서 멈추고 개발 서버를 다시 시작하면 gatsby develop 터미널에서 개발 로그는 페이지 빌드를 표시합니다.

우리가 열면 localhost:8000 브라우저에서 404 오류가 발생합니다. 

그다지 좋지 않을 수도 있지만 모두 좋습니다. 404 페이지의 링크를 클릭하면 WordPress 데이터 소스의 올바른 페이지 또는 게시물이 표시됩니다. 예를 들어, 샘플 페이지 링크를 클릭하면 브라우저에 WordPress의 샘플 페이지 컨텐츠가 표시됩니다.


섹션 3 : 탐색 작업

사이트의 탐색 메뉴로 넘어 갑시다. WordPress에는 페이지, 게시물, 보관 파일, 분류 및 심지어 사용자 정의 링크에 대한 링크를 사용하여 메뉴를 구성 할 수있는 탐색 관리 기능이 있습니다. WordPress에서 기본 메뉴에 대한 탐색을 작성하고이를 자체 사이트에 대해 조회 할 수있는 GraphQL로 보냅니다.

페이지 및 게시물 링크를 포함한 탐색 링크는 Gatsby에서 개츠비 링크 API내장형을 모두 사용하는 <Link> 구성 요소 navigate 함수. 그만큼 <Link> component는 내부 페이지에 연결하는 데 사용되지만 외부 링크에는 연결되지 않습니다.

WordPress에서 Gatsby 사이트로 이동하는 탐색 메뉴는 작성 해야하는 까다로운 작은 작업으로 판명되었습니다. <Menu><MenuItems> 구성 요소 및 리팩토링 <Layout> 구성 요소에 따라. 작동 방식은 다음과 같습니다.

이 섹션에서 사용 된 코드 스 니펫은 Henrik 님의 가이드 완전성을 위해이 코드 스 니펫은 다른 표준에서 사용되는 표준으로 보입니다. 개츠비 워드 프레스 스타터 약간의 변화.

1 단계 : 워드 프레스 메뉴 만들기

이 안내서에 설명 된대로 "XNUMX"테마에 정의 된 "PRIMARY"라는 메뉴를 설정하는 것이 중요합니다. 우리는 거기에 세 개의 링크를 던질 것입니다.

  • 홈 : 당사 홈페이지로 연결되는 링크로, 사이트의 색인을 가리키는 사용자 정의 링크입니다.
  • 샘플 페이지 : WordPress가 새 WordPress 설치에서 작성하는 기본 페이지입니다.
  • 첫 페이지: 이것은 일반적으로 WordPress의 홈페이지 이름입니다. 편집기에서이 페이지를 작성해야합니다.

2 단계 : GraphiQL Explorer로 메뉴 항목 쿼리

다음으로 메뉴 항목에 대한 쿼리를 작성합니다. GraphiQL 상호 작용. 탐색기를 사용하여 몇 개의 확인란을 선택하여 실제로 작성할 수 있습니다.

query MyQuery {
  menuItems(where: {location: PRIMARY}) {
    nodes {
      label
      url
      title
      target
    }
  }
}

3 단계 : Gatsby에서 메뉴 및 링크 유틸리티 구성 요소 작성

데이터의 URL이 절대적이며 전체 주소를 표시하는 방법을 참조하십시오. 상대 URL로 다시 변환하려면 유틸리티 함수가 필요합니다. <Link> 구성 요소 지원.

Henrik 님의 가이드 절대 WordPress URL을 Gatsby에 필요한 상대 URL로 변환하는 다음 유틸리티 기능을 제공합니다.

// src/utils/index.js
/** Parses a menu item object and returns Gatsby-field URI.
 * @param {object} menuItem a single menu item
 * @param wordPressUrl
 * @param blogURI */
export const CreateLocalLink = (menuItem, wordPressUrl, blogURI='blog/') => {
  const { url, connectedObject } = menuItem;


  if (url === '#') {
    return null;
  }
  /** Always want to pull of our API URL */
  let newUri = url.replace(wordPressUrl, '');


  /** If it's a blog link, respect the users blogURI setting */
  if (connectedObject && connectedObject.__typename === 'WPGraphQL_Post') {
    newUri = blogURI + newUri;
  }


  return newUri;
};

4 단계 : 메뉴 항목 구성 요소 작성

다음 단계는 <MenuItem> 이전 단계에서 생성 된 유틸리티 기능을 활용하는 구성 요소. 결과는 Gatsby 사이트 메뉴에서 사용하는 완전한 형식의 링크입니다.

// src/components/MenuItem.js
import React from "react"
import { CreateLocalLink } from "../utils"
import { Link } from "gatsby"


const MenuItem = ({ menuItem, wordPressUrl }) => {
  return (
    <Link style={{marginRight: '20px' }}
     to={CreateLocalLink(menuItem, wordPressUrl)}>
     {menuItem.label}
     </Link>
  )
}


export default MenuItem

5 단계 : 메뉴 구성 요소 작성 

좋아, 우리는 URL과 기능을 만들었습니다 <MenuItem> 구성 요소. 새로운 것을 만들어 보자 <Menu> 우리의 구성 요소 <MenuItem> 구성 요소가 갈 수 있습니다. 개츠비 StaticQuery API GraphQL로 모든 기본 메뉴 항목을 쿼리하는 데 사용됩니다.

// src/components/Menu.js
import React from "react"
import { StaticQuery, graphql } from "gatsby"
import MenuItem from "./MenuItem"


/** Define MenuItem fragment and get all primary menu items */
const MENU_QUERY = graphql`
  fragment MenuItem on WPGraphQL_MenuItem {
    id
    label
    url
    title
    target
  }


  query GETMAINMENU {
    wpgraphql {
      menuItems(where: {location: PRIMARY}) {
        nodes {
          ...MenuItem
        }
      }
      generalSettings {
        url
     }
    }
  }
`


const Menu = () => {
  return (
    <StaticQuery
      query={MENU_QUERY}
      render={(data) => {
        if (data.wpgraphql.menuItems) {
          const menuItems = data.wpgraphql.menuItems.nodes
          const wordPressUrl = data.wpgraphql.generalSettings.url


       return (
         <div style={{ marginBottom: "20px" }}>
           {
            menuItems &&
            menuItems.map((menuItem) => (
            <MenuItem key={menuItem.id}
              menuItem={menuItem} wordPressUrl={wordPressUrl}/>
            ) )}
         </div>
       )
      }
      return null
   }}
  />
  )
}


export default Menu

6 단계 : 레이아웃 구성 요소에 메뉴 추가

이제 WordPress 데이터를 사용하여 Gatsby 사이트 메뉴를 구성하는 데 필요한 모든 것이 있습니다. 우리는 그냥 드롭해야합니다 <Menu> 우리의 구성 요소 <Layout> 구성 요소:

// src/components/layout.js
import React from "react"
import PropTypes from "prop-types"
import useSiteMetadata from '../components/siteMetadata';
import Header from "./Header"
import Footer from "./Footer"
import Menu from "./Menu"
import "./layout.css"


const Layout = ({ children }) => {
  const { title, description } = useSiteMetadata();


  return (
    <section>
      <Header siteTitle={title} description={description} />
      <div
      style={{ margin: `0 auto`, maxWidth: 960,
               padding: `0 1.0875rem 1.45rem`,}}>
        <Menu />
        <main>{children}</main>
        <Footer />
      </div>
    </section>
  )
}


Layout.propTypes = {
  children: PropTypes.node.isRequired,
}


export default Layout

7 단계 : 외부 링크 경로에 대한 지원 추가

개츠비 에 대한 문서 <Link> 구성 요소 WordPress와 같은 외부 CMS에서 들어오는 데이터는 이상적으로 검사해야한다고 설명합니다. <Link> Gatsby와 함께 <Link> 또는 규칙적으로 <a> 그에 따라 태그를 지정하십시오. 이를 통해 WordPress 측의 외부 링크가 절대로 그대로 유지됩니다. <Link> 구성 요소입니다.

이를 위해서는 정확히 그렇게하는 다른 구성 요소가 필요합니다. Gatsby Docs에서는 <UniversalLink> 개츠비와 호환되는 <Link> 구성 요소 또는 전통적인 <a> 요소:

//src/components/UniversalLink.js
import React from "react"
import { Link as GatsbyLink } from "gatsby"


const UniversalLink = ({ children, to, activeClassName, partiallyActive, ...other }) => {
  const internal = /^/(?!/)/.test(to)
  // Use Gatsby Link for internal links, and <a> for others
  if (internal) {
    return (
      <GatsbyLink
        to={to}
        activeClassName={activeClassName}
        partiallyActive={partiallyActive}
        {...other}
      >
        {children}
      </GatsbyLink>
    )
  }
  return (
    <a href={to} {...other}>
      {children}
    </a>
  )
}
export default UniversalLink

이제 다시 돌아가 <MenuItem> 구성 요소를 업데이트하고 <UniversalLink>:

/ src/components/MenuItem.js
import React from "react"
import { CreateLocalLink } from "../utils"
import UniversalLink from "./UniversalLink"


const MenuItem = ({ menuItem, wordPressUrl }) => {
  return (
    <UniversalLink style={{marginRight: '20px' }}
      to={CreateLocalLink(menuItem, wordPressUrl)}>
      {menuItem.label}
    </UniversalLink>
  )
}


export default MenuItem

당신은 물건을 확인할 준비가 되셨습니까? 로 로컬 서버를 다시 시작하십시오. gatsby develop 브라우저는 상대 페이지 경로에 대한 링크가 포함 된 항목이있는 탐색 메뉴를 표시해야합니다.

사이트 탐색 및 사이트 항목 아래에 동일한 페이지 제목 및 내용을 보여주는 스크린 샷
Gatsby에 표시되는 WordPress에서 작성되었습니다.

섹션 4 : Gatsby에 블로그 게시물 표시

이 시점에서 우리는 꽤 좋은 상태에 있지만 우리가 해결해야 할 큰 부분이 있습니다. 바로 사이트에 페이지를 표시하는 것입니다. 이 섹션에서는 특히 모든 것을 함께 묶기 전에 블로그 게시물 템플릿과 게시물 이미지에 대한 몇 가지 새로운 구성 요소를 만들어이를 수행하는 단계를 살펴 보겠습니다. createPages.jscreatePosts.js.

WordPress에서 이미 페이지와 게시물을 만들었습니까? 그렇지 않다면, 여기에 뛰어 들어 좋은 시간입니다.

1 단계 : 프로젝트 디렉토리의 루트에 글로벌 변수 파일 추가

// global variable
const Globals = {
  blogURI: ''
}
module.exports = Globals

XNUMXD덴탈의 blogURI = ' ' URL 경로는 WordPress 관리자의 홈페이지 설정 (SettingsReading)가 '최근 게시물'옵션으로 설정되어 있습니다.

'정적 페이지'옵션을 대신 사용하려는 경우 blogURI= 'blog' 전역 변수 파일에서 사용해야합니다.

2 단계 : 템플릿 폴더 내에 블로그 템플릿 만들기

이 템플릿은 게시 된 모든 게시물 표시를 처리합니다. 두 가지 구성 요소는 PostEntryPagination, 둘 다 아직 존재하지는 않음) — 여기에 사용됩니다. 우리는 잠시 후에 그 사람들에게 갈 것입니다.

// src/templates/post/blog.js
import React from "react"
import Layout from "../../components/Layout"
import PostEntry from "../../components/PostEntry"
import Pagination from "../../components/Pagination"
import SEO from "../../components/SEO"


const Blog = ({ pageContext }) => {
  const { nodes, pageNumber, hasNextPage, itemsPerPage, allPosts }
  = pageContext


  return (
    <Layout>
      <SEO
        title="Blog"
        description="Blog posts"
        keywords={[`blog`]}
      />
      {nodes && nodes.map(post => <PostEntry key={post.postId}
        post={post}/>)}
      <Pagination
        pageNumber={pageNumber}
        hasNextPage={hasNextPage}
        allPosts={allPosts}
        itemsPerPage={itemsPerPage}
      />
    </Layout>
  )
}


export default Blog

3 단계. 게시물 입력 구성 요소 생성

이 구성 요소는 archive.js 및 게시물을 통해 반복하여 게시물 항목 제목, 추천 이미지 (있는 경우), 발췌 및 URL (WordPress 용어에서 "슬러그")을 표시하는 기타 구성 요소.

// src/components/PostEntry.js
import React from "react"
import { Link } from "gatsby"
import Image from "./Image"
import { blogURI } from "../../globals"


const PostEntry = ({ post }) => {
  const { uri, title, featuredImage, excerpt } = post

  return (
    <div style={{ marginBottom: "30px" }}>
      <header>
        <Link to={`${blogURI}/${uri}/`}>
          <h2 style={{ marginBottom: "5px" }}>{title}</h2>
          <Image image={featuredImage} style={{ margin: 0 }}/>
        </Link>
      </header>


      <div dangerouslySetInnerHTML={{ __html: excerpt }}/>
    </div>
  )
} export default PostEntry

4 단계 : (선택적) 이미지 구성 요소 생성

개츠비 기본 스타터는 Image 구성 요소와 대부분의 경우 제대로 작동합니다. 이 예에서는 WordPress에서 게시물의 추천 이미지로 사용 된 이미지 파일을 가져 와서 설명 된대로 추천 이미지가없는 경우 대체 이미지를 할당합니다. Henrik 님의 가이드.

// src/components/Image.js
import React from "react"
import { useStaticQuery, graphql } from "gatsby"


const Image = ({ image, withFallback = false, ...props }) => {
  const data = useStaticQuery(graphql`
    query {
      fallBackImage: file(relativePath: { eq: "fallback.svg" }) {
        publicURL
      }
    }
  `)


  /* Fallback image */
  if (!image) {
    return withFallback ? <img src={data.fallBackImage.publicURL}
      alt={"Fallback"} {...props}/> : null
  }


  return <img src={image.sourceUrl} alt={image.altText} {...props}/>
}


export default Image

If withFallbackfalse (기본 Gatsby 구성 요소 파일에있는 것처럼) DOM 요소를 렌더링하지 않습니다.

5 단계 : 페이지 매김 구성 요소 작성

페이지 매김 구성 요소를 사용하면 게시물 색인에 페이지 당 지정된 게시물 수를 표시 할 수 있습니다. 워드 프레스에는 두 가지 유형의 페이지 매김이 있습니다. 다음 및 이전 링크를 반환하는 링크 한 번에 한 페이지 씩 탐색하고 링크 된 페이지 번호를 제공하는 것. 우리는이 구성 요소에서 전자와 협력하고 있습니다.

// src/components/Pagination.js
import React from "react"
import { Link } from "gatsby"
import { blogURI } from "../../globals"


const Pagination = ({ pageNumber, hasNextPage }) => {
  if (pageNumber === 1 && !hasNextPage) return null


  return (
    <div style={{ margin: "60px auto 20px", textAlign: "center" }}>
      <div className="nav-links">
        {
          pageNumber > 1 && (
            <Link
              className="prev page-numbers"
              style={{
                padding: "8px 8px 5px 4px",
              }}
           to={pageNumber > 2 ? `${blogURI}/page/${pageNumber - 1}`: `${blogURI}/`}
            >
              ← <span> Previous</span>
            </Link>
          )
        }
          <span className="meta-nav screen-reader-text"></span>
          {pageNumber}
        </span>


        {
          hasNextPage && (
            <Link
              style={{
                padding: "4px 8px 5px 8px",
              }}
              className="next page-numbers"
              to={`${blogURI}/page/${pageNumber + 1}`
              }
            >
              <span>Next </span> →
            </Link>
          )
        }
      </div>
    </div>
  )
}


export default Pagination

7 행에는 다음을 리턴하는 조건문이 있습니다. null if pageNumber === 1 && !hasNextPage. 즉, 현재 페이지의 hasPageNumber 보다 큰 1, 이전 버튼 (13-24 행)이 표시됩니다. 마찬가지로 현재 페이지가 hasNextPage 적어도 1을 클릭하면 다음 버튼 (30-42 행)이 표시됩니다.

6 단계 : createPages 리팩토링

우리는 청소해야합니다 createPages.js 파일을 만든 후 수행 한 모든 작업을 반영합니다. 추적하는 모든 파일이 파일이 너무 커집니다. 코드를 체계적이고 체계적으로 유지하기 위해 GraphQL 조각"복잡한 검색어를 더 작고 이해하기 쉬운 구성 요소로 나눌 수 있습니다." 문서에 따르면.

GraphQL 조각은 재사용 가능한 단위로 필드 집합을 구성한 다음 필요할 때마다 쿼리에 포함 할 수 있습니다.

우리가 따라 가면 Henrik 님의 가이드게시물 템플릿 및 게시물 미리보기에 대한 GraphQL 쿼리 필드는 data.js 파일 :

// src/templates/posts/data.js
const PostTemplateFragment = `
  fragment PostTemplateFragment on WPGraphQL_Post {
    id
    postId
    title
    content
    link
    featuredImage {
      sourceUrl
    }
    categories {
      nodes {
        name
        slug
        id
      }
    }
    tags {
      nodes {
        slug
        name
        id
      }
    }
    author {
      name
      slug
    }
  }
`


const BlogPreviewFragment = `
  fragment BlogPreviewFragment on WPGraphQL_Post {
    id
    postId
    title
    uri
    date
    slug
    excerpt
    content
    featuredImage {
      sourceUrl
    }
    author {
      name
      slug
    }
  }
`


module.exports.PostTemplateFragment = PostTemplateFragment
module.exports.BlogPreviewFragment = BlogPreviewFragment

다음으로 리팩토링 create/createPosts.js 에 설명 된 파일 안내 의 상단 섹션에 다음 코드를 추가해야합니다 createPosts.js (2-10 행) 바로 위 const = GET_POSTS=` 4 행의 쿼리 문

// create/createPosts.js
const {
  PostTemplateFragment,
  BlogPreviewFragment,
} = require("../src/templates/posts/data.js")


const { blogURI } = require("../globals")


const postTemplate = require.resolve("../src/templates/posts/index.js")
const blogTemplate = require.resolve("../src/templates/posts/blog.js")


const GET_POSTS = `
  # Here we make use of the imported fragments which are referenced above
  ${PostTemplateFragment}
  ${BlogPreviewFragment}
  query GET_POSTS($first:Int $after:String) {
    wpgraphql {
      posts(
       first: $first
       after: $after
       # This will make sure to only get the parent nodes and no children
       where: {
         parent: null
       }
      ) {
         pageInfo {
           hasNextPage
           endCursor
         }
         nodes {
           uri


           # This is the fragment used for the Post Template
           ...PostTemplateFragment


           #This is the fragment used for the blog preview on archive pages
          ...BlogPreviewFragment
        }
      }
    }
 }
`

여기에서 이전 단계 (9-10 행)에서 생성 된 조각 문자열을 가져 와서 GET_POSTS 쿼리 (12 행)이며 내부의 조각 (34 행 및 37 행)으로 사용됩니다. GET_POSTS($first:Int $after:String) 질문.

의 하단에있는 createPosts.js 파일 blogPage 경로는 전역으로 정의됩니다 blogURI 변수 (36-41 행) 및 페이지가 지정된 블로그 페이지 (99-111 행)를 작성하는 코드를 추가했습니다.

// create/createPosts.js
// Previous code excluded


const allPosts = []
const blogPages = [];
let pageNumber = 0;
const itemsPerPage = 10;


/** This is the export which Gatbsy will use to process.
 * @param { actions, graphql }
 * @returns {Promise<void>} */
module.exports = async ({ actions, graphql, reporter }, options) => {


  /** This is the method from Gatsby that we're going
   * to use to create posts in our static site */
  const { createPage } = actions


  /** Fetch posts method. This accepts variables to alter
   * the query. The variable `first` controls how many items to
   * request per fetch and the `after` controls where to start in
   * the dataset.
   * @param variables
   * @returns {Promise<*>} */
  const fetchPosts = async (variables) =>
    /** Fetch posts using the GET_POSTS query and the variables passed in */
    await graphql(GET_POSTS, variables).then(({ data }) => {
      /** Extract the data from the GraphQL query results */
      const {
        wpgraphql: {
          posts: {
            nodes,
            pageInfo: { hasNextPage, endCursor },
          },
        },
      } = data


      /** Define the path for the paginated blog page.
       * This is the url the page will live at
       * @type {string} */
      const blogPagePath = !variables.after
        ? `${blogURI}/`
        : `${blogURI}/page/${pageNumber + 1}`


      /** Add config for the blogPage to the blogPage array for creating later
       * @type {{
       *   path: string,
       *   component: string,
       *   context: {nodes: *, pageNumber: number, hasNextPage: *} }} */
      blogPages[pageNumber] = {
        path: blogPagePath,
        component: blogTemplate,
        context: {
          nodes,
          pageNumber: pageNumber + 1,
          hasNextPage,
          itemsPerPage,
          allPosts,
        },
      }


      /** Map over the posts for later creation */
      nodes
      && nodes.map((posts) => {
        allPosts.push(posts)
      })


     /** If there's another post, fetch more so we can have all the data we need */
      if (hasNextPage) {
        pageNumber++
        reporter.info(`fetch post ${pageNumber} of posts...`)
        return fetchPosts({ first: itemsPerPage, after: endCursor })
      }


      /** Once we're done, return all the posts so we can
       * create the necessary posts with all the data on hand */
      return allPosts
    })


  /** Kick off our `fetchPosts` method which will get us all
   * the posts we need to create individual posts */
  await fetchPosts({ first: itemsPerPage, after: null }).then((wpPosts) => {


    wpPosts && wpPosts.map((post) => {
      /** Build post path based of theme blogURI setting */
      const path = `${blogURI}${post.uri}`


      createPage({
        path: path,
        component: postTemplate,
        context: {
          post: post,
        },
      })


      reporter.info(`post created:  ${path}`)
    })


    reporter.info(`# -----> POSTS TOTAL: ${wpPosts.length}`)


    /** Map over the `blogPages` array to create the
     * paginated blog pages */
    blogPages
    && blogPages.map((blogPage) => {
      if (blogPage.context.pageNumber === 1) {
        blogPage.context.publisher = true;
        blogPage.context.label = blogPage.path.replace('/', '');
      }
      createPage(blogPage);
      reporter.info(`created blog archive page ${blogPage.context.pageNumber}`);
    });
  })
}

최종 업데이트 create/createPosts.jscreate/createPage.js 파일은 이 GitHub 리포지토리에서 사용 가능.

그의 있음 스물 아홉 포팅 튜토리얼 포스트, Muhammad는 Gatsby의 createPage 이 예제에서 사용 된 것과 거의 동일한 코드 및 파일 구조를 사용하십시오. 참고 문헌 사이에 일관성이 형성되는 것을 보게되어 기쁩니다.

로 로컬 서버를 다시 시작한 후 gatsby develop이제 게시물 제목과 발췌문이 포함 된 게시 된 게시물의 루프를 보여주는 화면을 브라우저에 표시해야합니다.


섹션 5 : 스타일링 및 배포

스타일링, 타이포그래피 및 배포는 여기에서 다루는 범위를 벗어나지 만 약간만 다루면됩니다. Gatsby의 문서는 두 가지 모두에 대한 훌륭한 자료를 제공합니다 스타일링배포 / 호스팅 옵션을 제공합니다.

기본 사이트 스타일링

개츠비의 문서는 글로벌 CSS 파일, 모듈 식 스타일 시트CSS-in-JS. 있다 다른 스타일링 옵션 포함하여 타이포그래피.js, 말대꾸, JSS, 첨필포스트 CSS.

Twenty Nineteen WordPress 테마를 Gatsby로 이식하는 동안, 무하마드는 테마의 스타일을 포함 Gatsby 사이트에서 사용할 수 있습니다. 그는 일부 단위와 값이 Gatsby와 호환되지 않기 때문에 일부 조정이 필요하다고 경고합니다. 예를 들어, 그는 조정해야 vw CSS의 단위는 일부 구성 요소에 flexbox와 함께 사용합니다. 마찬가지로 포팅 개츠비에게 XNUMX 개의 테마Henrik도 비슷한 과정을 밟았습니다. 개츠비 스타터-스물 스물 스물 포팅하여 스물 스물 스물 스타일 시트 만큼 잘 글꼴.

내 프로젝트에서 Sass를 사용하기로 결정했습니다. 설치가 필요합니다 개츠비 플러그인 sass 그리고 그 필수 node-sass 의존:

#! install node-sass & gatsby-sass
yarn add node-sass gatsby-plugin-sass
#! or with npm
npm install --save node-sass gatsby-plugin-sass

그런 다음 플러그인을 추가 할 수 있습니다 gatsby-config.js구성 여기에 표시된대로.

// gatsby-config.js
module.exports = {
  siteMetadata: {
    plugins: [
      `gatsby-plugin-sass`
    ],
  }
}

이제 스타일을 쓸 수 있습니다 .scss 다른 Sass 프로젝트에서와 마찬가지로 파일을 가져옵니다.

// using import in a component file
import("./src/styles/global.scss")


// using require in the gatsby-browser.js file
require('./src/styles/global.scss')

XNUMXD덴탈의 .scss 스타일 시트는 전 세계적으로 가져올 수 있습니다 <Layout> 구성 요소 또는 추가 gatsby-browser.jsrequire 성명서. 이 데모 프로젝트에서는 메인 페이지에 Gatsby의 기본 스타일을 사용하고 있으며 컨텐츠를 그대로 게시했습니다. 나는 리팩토링했다 Header.js 아주 기본적인 스타일링으로 조금 정리하십시오.

//src/components/Header.js
import { Link } from "gatsby"
import PropTypes from "prop-types"
import React from "react"
import useSiteMetadata from '../components/siteMetadata';
import Menu from "./Menu"
import "../styles/header.css"


const Header = () =>{
  const { title } = useSiteMetadata();


  return (
    <header className="header">
      <div className="nav-container brand">
        <Link  to="/"> {title} </Link>
        {/* Menu here */}
        <Menu />
      </div>
    </header> )
}


Header.propTypes = {
  siteTitle: PropTypes.string,
  description: PropTypes.string,
}


Header.defaultProps = {
  siteTitle: ``,
  description: ``,
}


export default Header

이것은 우리가 서버를 다시 시작할 때 사이트 헤더를 제공해야합니다. gatsby develop.

지원 WordPress 블록 스타일

지금까지 WordPress 블록 편집기에 익숙하고 블록이 일반적으로 작동하는 방식을 알고 있다면 잘 알고 있다고 가정합니다. 블록 편집기를 출시 한 이후로 WordPress는 블록 내용을 위해 별도의 스타일 세트를 유지했습니다.

즉, 테마 스타일을 사용하여 개츠비로 포팅하려면 추가 단계가 필요합니다. 제이슨 렝스 토프 그의 설명 자습서 가이드. 먼저 WordPress 블록 패키지가 설치됩니다.

# install wordpress/block-library
npm install @wordpress/block-library
# with yarn add
yarn add @wordpress/block-library

그런 다음 해당 스타일을 Gatsby 구성 요소로 가져올 수 있습니다. 함께 가자 <Layout> 구성 요소:

// src/components/layout.js
import React from "react"
  import { Link } from "gatsby"


import "@wordpress/block-library/build-style/style.css"
  import "../styles/layout.css"


const Layout = ({ children }) => {
  return (
    <section>
    <header>
       <Link to="/" className="home">
          Gatsby + WP
        </Link>
      </header>
      <main>{children}</main>
    </section>
  )
}


export default Layout

블록 편집기는 여전히 활발히 개발 중이므로 예상치 못한 일이 발생하기 쉽습니다. 따라서 사용하려는 경우 신중하게 진행하십시오.

사이트 배포

내가 선택한 이유를 설명 할 때 배포에 대해 조금 이야기했습니다. 네티 파이Netlify Functions 덕분에 프로젝트의 GitHub 리포지토리에 연결되어 특정 지점으로 푸시 할 때 자동으로 배포되므로 선택했습니다.

Netlify는 훌륭한 단계별 가이드를 제공합니다. Gatsby 사이트를 Netlify에 연결하는 방법을 다룹니다. 개츠비 문서는 또한 설명합니다 Netlify에 배포.

마지막으로, 배포 된 내 Netlify에 연결 데모 사이트.

다시 말하지만 변경 사항이 리포지토리로 푸시 될 때 사이트가 자동으로 다시 구축되는 지속적인 배포를 제공합니다. 게시물을 게시하거나 페이지를 편집하는 것과 같이 WordPress에서 변경 될 때마다 유사한 프로세스를 원할 경우 JAMstack 배포 플러그인 에 설명 된대로 사용될 수 있습니다 Jason의 가이드.


이것은 여전히 ​​진행중인 작업입니다!

WordPress 테마를 Gatsby로 이식하는 과정에서 배운 내용은 블로그의 기본 빌딩 블록을 구성하는 데 유용하지만 여전히 다루어야 할 많은 작업이 있음을 깨달았습니다. 워드 프레스는 저자, 카테고리, 태그, 게시물 상태, 사용자 정의 게시물 유형 등을 포함하여 너무 많은 데이터를 저장하므로 모두 고려해야 할 사항이 있습니다.

그러나 분리 된 Gatsby WordPress 사이트 예제 목록이 점점 늘어나고 있으며 그 중 일부는 아래에 참고 용으로 나열 할 것입니다. 헨릭 멋진 WordPress-Gatsby 자료 목록 WordPress-Gatsby 디커플링에 대해 자세히 알아볼 수 있습니다.

크레딧 

이 게시물 전체에서 언급했지만 큰 소리로 헨릭 위스, 제이슨 렝스 토프무하마드 무신 WordPress를 Gatsby로 이식하는 데 필요한 모든 것을 문서화하고 공유하기 위해 수행 한 모든 작업에 대해 여기에서 다룬 모든 내용은 단지 훌륭한 작업의 축적 일 뿐이며, 본인과 같은 초보자에게도 도움이되는 유용한 안내서를 만들어 주신 것에 대해 감사합니다. 이 기사를 편집 해 주신 CSS-Tricks의 Geoff Graham에게 특별한 감사를드립니다.

출처 : https://css-tricks.com/creating-a-gatsby-site-with-wordpress-data/

spot_img

최신 인텔리전스

spot_img