WordPress jako headless CMS i Next.js - konfiguracja projektu

Damian Wróblewski - lipiec 2021

WordPress jako headless CMS i Next.js - konfiguracja projektu

Spis treści

  1. Instalacja i konfiguracja WordPress'a jako headless CMS
  2. Utworzenie i konfiguracja projektu Next.js

O tym, czym jest headless CMS, co zyskasz wybierając WordPress'a w tej formie oraz kiedy nie warto wybierać tego rozwiązania, pisałem już w artykule opublikowanym na LinkedIn, który traktować można jako wprowadzenie do dzisiejszego tematu. W tym wpisie natomiast skonfigurujemy już konkretne rozwiązanie jakim będzie połączenie headless'owego WordPress'a z framework'iem Next.js. To właśnie Next będzie generował statyczne strony na podstawie informacji pobranych z WordPress'a.

Co będzie nam potrzebne?

  1. Instancja WordPress'a wraz z odpowiednimi wtyczkami umożliwiającymi komunikację za pomocą zapytań GraphQL,
  2. Odpowiednio skonfigurowany projekt Next.js.

Do dzieła!

Instalacja i konfiguracja WordPress'a jako headless CMS

Pierwszym krokiem będzie instalacja WordPress'a. Możesz to zrobić np. lokalnie za pomocą XAMPP (tutaj znajdziesz instrukcję) lub na serwerze obsługującym PHP i MySQL (instrukcja tutaj).

Headless WordPress

Jeśli WP jest już zainstalowany, możemy przejść do instalacji i konfiguracji wtyczek.

Instalacja wtyczek

Do komunikacji z headless'owym WP można wykorzystać RestAPI lub GraphQL. My skorzystamy z tego drugiego rozwiązania, które zapewnia w tym przypadku lepszą wydajność. A wydajność to przecież jeden z głównych powodów, dla których warto rozważyć wykorzystanie wersji headless WordPress'a.

Pierwszą wtyczką jaką musimy zainstalować jest WPGraphQL. Wtyczkę instalujemy poprzez przesłanie pliku zip:

  • Pobieramy plik zip wtyczki z repozytorium,
  • W panelu administratora WP przechodzimy do zakładki Wtyczki > Dodaj nową > Wyślij wtyczkę na serwer i przesyłamy plik zip z naszą wtyczką,
  • Kiedy wtyczka zostanie przesłana, włączamy ją z poziomu zakładki Wtyczki > Zainstalowane wtyczki klikając "Włącz"

Kiedy wtyczka jest już uruchomiona, przechodzimy do ustawień. Najważniejszą pozycją na ten moment jest GraphQL Endpoint. To tutaj defiuniujemy endpoint, na który będziemy się komunikować z naszym API.

WPGraphQL - ustawienia

Już z pomocą samego WPGraphQL możemy się łączyć i pobierać treści z naszego WordPress'a. Jednak dopiero dodanie wtyczki Advanced Custom Fields pozwoli nam w pełni wykorzystać potencjał tego rozwiązania. ACF to popularny plugin, który umożliwia dodawanie do stron i wpisów dodatkowych pól z treścią.

By zainstalować wtyczkę:

  • Przechodzimy do Wtyczki > Dodaj nową i wyszukujemy wtyczkę wpisując w pasku wyszukiwania "Advanced Custom Fields"
  • Instalujemy i włączamy wtyczkę

Advanced Custom Fields

By skorzystać z ACF w naszym projekcie oprócz samej wtyczki, będziemy musieli zainstalować jeszcze jeden plugin - WPGraphQL for Advanced Custom Fields. Instalujemy podobnie jak WPGraphQL - plik zip pobieramy z tego repozytorium.

Dodatkowe pola ACF

Uzbrojeni w wszelkie niezbędne narzędzia, możemy dodać na naszej stronie jakieś testowe treści i sprawdzić zwracane dane za pomocą wbudowanego w WPGraphQL narzędzia GraphiQL IDE. Spróbujemy dodać do strony głównej dodatkowe pola i zawrzeć w nich treść, która docelowo będzie wyświetlana w topbarze strony.

W celu utworzenia nowych pól, w panelu WordPress'a przechodzimy do Własne pola > Grupy pól i wybieramy "Dodaj nową". Naszą grupę pól nazywamy np. "Topbar" i w ustawieniach grupy pól określamy, że grupa ma być widoczna dla strony głównej:

Advanced Custom Fields - nowe pola

Musimy również włączyć widoczność grupy dla GraphQL i nadać nazwę, którą posługować się będziemy w zapytaniach.

Advanced Custom Fields - GraphQL

Teraz możemy przejść do dodawania pól. Dodamy dwa pola: Phone number oraz Email o typach odpowiednio Tekst i E-mail:

Advanced Custom Fields - edycja pól

Czas na dodanie treści. Przechodzimy więc do edycji strony (w naszym przypadku to Strona główna) i dodajemy treść do pól:

Advanced Custom Fields - dodanie treści dla pól

Możemy także w edytorze dodać testową treść dla strony:

WordPress - edycja strony

Zapytania GraphQL

Za pomocą narzędzia GraphiQL IDE możemy teraz sprawdzić czy nasze treści są dostępne, tworząc odpowiednie zapytanie GraphQL. GraphiQL to kreator, dzięki któremu w prosty sposób możemy tworzyć i testować zapytania GraphQL. Wystarczy, że w oknie Explorer po lewej stronie wybierzemy interesujące nas dane, a w środkowym oknie zobaczymy odpowiadające tym danym zapytanie. Dodatkowo klikając przycisk ► możemy przetestować zapytanie i w prawym oknie podejrzeć zwracane dane. W naszym przykładzie zbudujemy zapytanie, które zwróci nam tytuł strony, jej treść oraz informacje zawarte w utworzonej przez nas grupie pól topBar. Jako że interesują nas dane związane tylko ze Stroną główną, stosując filtr, wybierzemy tylko stronę o konkretnym ID. ID strony w WordPress sprawdzić możemy np. w URL kiedy edytujemy daną stronę.

/wp-admin/post.php?post=25&action=edit

W naszym przypadku ID to 25.

Sprawdźmy jak wyglądać będzie zatem całe zapytanie i co nam zwróci:

GraphiQL

Jak widać nasz WordPress jest poprawnie skonfigurowany, więc możemy przejść do drugiej części, czyli utworzenia projektu Next.js.

Utworzenie i konfiguracja projektu Next.js

Tworzymy nowy projekt

W celu utworzenia nowego projektu wykorzystamy narzędzie create-next-app. W katalogu docelowym uruchamiamy:

npx create-next-app headless-wp-website

Jeśli chcemy korzystać z Typescript'a dodajemy flagę --ts lub --typescript:

npx create-next-app headless-wp-website --ts

Po utworzeniu, jeśli wszystko przebiegło pomyślnie możemy przejść do katalogu projektu:

cd headless-wp-website

I uruchomić nasz projekt w wersji developerskiej:

npm run dev

Kiedy projekt się zbuduje, możesz go podejrzeć uruchamiając w przeglądarce http://localhost:3000

Jeśli wszystko przebiegło pomyślnie, możemy przejść do konfiguracji projektu.

Konfiguracja projektu Next.js

Na początek dodajmy nową zmienną środowiskową, która zawierać będzie adres naszego endpoint'a. W tym celu w głównym katalogu projektu tworzymy plik .env, w którym dodajemy:

WP_API_URL=http://naszadomena.pl/graphql

Więcej na temat zmiennych środowiskowych w Next możesz przeczytać tutaj.

Kolejnym krokiem będzie utworzenie pliku api.js, w którym znajdować się będą wszelkie funkcje pobierające dane oraz zapytania GraphQL. Plik dla porządku umieścimy w katalogu /lib/api.js.

Na początku pliku dodajemy utworzoną wcześniej zmienną środowiskową:

const API_URL = process.env.WP_API_URL;

Następnie dodajemy główną funkcję pobierającą dane:

1const API_URL = process.env.WP_API_URL;
2
4async function fetchAPI (query, { variables } = {}) {
5 const headers = { 'Content-Type': 'application/json' };
6 const res = await fetch(API_URL, {
7 method: 'POST',
8 headers,
9 body: JSON.stringify({ query, variables })
10 });
11
12 const json = await res.json();
13 if (json.errors) {
14 console.log(json.errors);
15 console.log('error details', query, variables);
16 throw new Error('Failed to fetch API');
17 }
18 return json.data;
19}

I wykorzystujemy ją wstawiając jako argument query nasze zapytanie skopiowane z GraphiQL:

1const API_URL = process.env.WP_API_URL;
2
3async function fetchAPI (query, { variables } = {}) {
4 const headers = { 'Content-Type': 'application/json' };
5 const res = await fetch(API_URL, {
6 method: 'POST',
7 headers,
8 body: JSON.stringify({ query, variables })
9 });
10
11 const json = await res.json();
12 if (json.errors) {
13 console.log(json.errors);
14 console.log('error details', query, variables);
15 throw new Error('Failed to fetch API');
16 }
17 return json.data;
18}
19
21export async function getHomePageData() {
22 const data = await fetchAPI(
23 `
24 {
25 page(id: "25", idType: DATABASE_ID) {
26 topBar {
27 email
28 phoneNumber
29 }
30 }
31 }
32 `
33 );
34 return data?.page;
35}

Z pomocą zdefiniowanych właśnie funkcji możemy pobrać dane, a następnie przekazać je do odpowiedniego komponentu w pliku pages/index.js, który odpowiada za stronę główną naszej aplikacji. Najpierw utworzymy prosty komponent TopBar który będzie wyświetlał nasze dane. Tworzymy plik components/TopBar.js:

1import styles from '../../../styles/TopBar.module.scss';
2
3function TopBar({ phone, email }) {
4 return (
5 <div className={styles.Topbar}>
6 <div className={styles.Container}>
7 <div className={styles.InfoElement}>{email}</div>
8 <div className={styles.InfoElement}>{phone}</div>
9 </div>
10 </div>
11 );
12}
13
14export default TopBar;

Dodamy jeszcze plik z podstawowymi stylami dla komoponentu:

1.Topbar {
2 width: 100vw;
3 background-color: #000;
4 margin: auto;
5 .Container {
6 max-width: 1200px;
7 display: flex;
8 flex-direction: row;
9 justify-content: flex-end;
10 }
11 .InfoElement {
12 padding-right: 20px;
13 }
14}

I możemy teraz przejść do pliku pages/index.js. Domyślną zawartość pliku, dodaną podczas tworzenia projektu możesz usunąć.

Najpierw zaimportujemy funkcję pobierającą dane oraz komponent TopBar:

import { getHomePageData } from '../lib/api';
import TopBar from '../components/organisms/TopBar/TopBar';

Następnie utworzymy komponent naszej strony:

1import { getHomePageData } from '../lib/api';
2import TopBar from '../components/organisms/TopBar/TopBar';
3
5function IndexPage() {
6
7 return (
8 <>
9 <TopBar phone={} email={} />
10 </>
11 );
12}
13
14export default IndexPage;

Kolejnym krokiem będzie utworzenie funkcji asynchronicznej getStaticProps. Jest to specjalna funkcja, którą Next.js uruchamia w trakcie budowania aplikacji. Pobrane za jej pomocą dane mogą być następnie przekazane jako propsy do komponentu naszej strony. W ten sposób Next.js może na etapie budowania aplikacji wygenerować wszystkie strony statyczne na podstawie pobranych z zewnątrz danych. Więcej na temat pobierania danych w Next możesz przeczytać w dokumentacji.

1import { getHomePageData } from '../lib/api';
2import TopBar from '../components/organisms/TopBar/TopBar';
3
4function IndexPage() {
5
6 return (
7 <>
8 <TopBar phone={} email={} />
9 </>
10 );
11}
12
13export default IndexPage;
14
16export const getStaticProps = async () => {
17 const homePageData = await getHomePageData();
18 return {
19 props: {
20 homePageData
21 }
22 };
23};

Zwrócone przez funkcję getStaticProps() propsy przekażemy teraz do komponentu strony, dokonamy destrukturyzacji przypisując do zmiennej topBar odpowiednie dane i następnie przekażemy te dane do komponentu TopBar.

1import { getHomePageData } from '../lib/api';
2import TopBar from '../components/organisms/TopBar/TopBar';
3
5function IndexPage({ homePageData }) {
6 const { topBar } = homePageData;
7
8 return (
9 <>
10 <TopBar phone={topBar.phoneNumber} email={topBar.email} />
11 </>
12 );
13}
15
16export default IndexPage;
17
18export const getStaticProps = async () => {
19 const homePageData = await getHomePageData();
20 return {
21 props: {
22 homePageData
23 }
24 };
25};

Możemy teraz sprawdzić czy wszystko poszło zgodnie z planem uruchamiając:

npm run dev

Headless WordPress i Next.js

Gotowe! Nasz komponent poprawnie wyświetla informacje pobrane z naszej headless'owej instancji WordPress'a.

Takie połączenie daje wysoką wydajność i bezpieczeństwo stron statycznych oraz przyjazne i dobrze znane środowisko do tworzenia i edycji treści.

Bądź ze mną w kontakcie na Twitterze lub LinkedIn, jeśli interesuje Cię świat aplikacji webowych 😉


Dołącz do dyskusji