Узнайте, что такое безголовая CMS и как ею воспользоваться с помощью Astro.

Всем привет!

Я уверен, что вы слышали о WordPress, и он может вам понравиться или не понравиться. В этой статье я покажу вам, как вы можете использовать только хорошие части WordPress, используя его в качестве безголовой CMS для вашего следующего проекта.

В качестве внешнего интерфейса мы будем использовать новый популярный генератор статических сайтов Astro.

Давайте немного углубимся в детали того, с чем мы работаем.

Что такое Астро?

Astro — это генератор статических сайтов (SSG), что означает, что он может создавать статические веб-сайты в формате HTML.

Вам может быть интересно, хорошо, но зачем нам это нужно? SSG превосходен, поскольку выводит статический HTML, что, в свою очередь, означает, что ваш сайт будет работать быстро. Нет ничего быстрее, чем обычный HTML-сайт.

Нам часто нужны динамические детали и компоненты на нашем веб-сайте. Вот где SSG пригодится.

Astro — довольно новый ребенок в этом блоке, но очень мощный и полный потенциала. Вот некоторые преимущества использования Astro:

  • SEO-фокус из коробки
  • Подход BYOF (Bring your own framework): используйте любой фреймворк, в котором вам нравится работать, и Astro заставит его работать.
  • Частичная гидратация, обеспечивающая визуализацию компонентов в нужное время
  • Много встроенной поддержки
  • Маршрутизация очень расширена
  • Активное сообщество

Это лишь некоторые из причин, по которым Astro довольно удивительна, если вы спросите меня. Но если вам интересно, как Astro сравнивается с другими инструментами, ознакомьтесь с этим удивительным документом, который они создали.

Что такое безголовая CMS?

Теперь, когда мы объяснили интерфейсную часть, давайте уделим немного времени, чтобы проверить, что такое Headless CMS.

Я уверен, что вы слышали о WordPress, раздутой и часто используемой системе CMS. WordPress — настоящий монстр пакетов, позволяющий людям управлять своими веб-сайтами с небольшим опытом разработки.

Сообщество разработчиков часто не любит WordPress, потому что он слишком раздут. Это означает, что веб-сайты работают медленно и полны вещей, которые нам не нужны.

Вот тут-то и появляется WordPress как безголовая система. Безголовая система означает, что вы можете использовать всю серверную систему WordPress, но вам не нужно использовать интерфейсный вывод.

Вместо этого мы используем API для запроса наших данных и использования их в другой системе. В нашем случае это будет интерфейс Astro.

Для системы API мы будем использовать GraphQL в качестве языка запросов, но подробнее об этом в шаге ниже.

Настройка WordPress в качестве безголовой CMS

Прежде чем мы продолжим, давайте настроим WordPress и особенно настроим его как безголовую CMS.

Самый простой способ настроить WordPress на локальном компьютере — использовать образ докера.

Если у вас не установлен Docker Desktop, следуйте этому руководству на веб-сайте Docker.

Затем создайте новую папку и перейдите к ней:

mkdir wordpress && cd wordpress

Затем создайте файл docker-compose.yml и заполните следующие данные:

version: '3.9'
services:
  db:
    image: mariadb
    volumes:
      - db_data:/var/lib/mysql
    restart: unless-stopped
    ports:
      - 3307:3306
    environment:
      MYSQL_ROOT_PASSWORD: rootpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - wordpress_data:/var/www/html
    ports:
      - '8000:80'
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
volumes:
  db_data: {}
  wordpress_data: {}

Затем мы можем запустить наш образ докера, выполнив следующую команду:

docker-compose up

Как только он будет запущен, вы должны увидеть следующее в своем клиенте Docker Desktop.

Следующим шагом является посещение нашей установки WordPress и выполнение шагов установки.

Вы можете найти свою установку WordPress на ‌http://localhost:8000/ и должны приветствоваться руководством по установке WordPress.

Чтобы настроить его как Headless CMS, нам нужно установить плагин WP GraphQL.

Следуйте инструкциям по установке плагина. После его установки мы даже получаем этот фантастический редактор GraphQL для проверки наших запросов.

И мы получаем конечную точку GraphQL, доступную по следующему URL-адресу: http://localhost:8000/graphql.

Пока вы находитесь в разделе WordPress, создайте несколько демонстрационных страниц. Теперь пришло время настроить наш проект Astro.

Настройка проекта Astro

Пожалуйста, создайте новую папку и перейдите в нее.

mkdir astro-wordpress && cd astro-wordpress

Затем мы можем установить Astro, выполнив следующую команду:

npm init astro

Вы можете выбрать начальный шаблон для начала работы. Затем запустите npm install, чтобы установить все зависимости, и запустите проект Astro, запустив npm start.

Теперь вы можете посетить свой интерфейс по адресу http://localhost:3000/.

Добавление Tailwind CSS в качестве нашей структуры стилей

Правильно, прежде чем мы перейдем к загрузке наших данных WordPress, давайте установим TailwindCSS, так как это облегчит нам жизнь при стилизации веб-сайта.

Установить Tailwind в проект Astro довольно просто. Давайте посмотрим, что должно произойти шаг за шагом.

  • Установить Попутный ветер:
npm install --D tailwindcss
  • Создайте файл tailwind.config.js
module.exports = {
  mode: 'jit',
  purge: ['./public/**/*.html', './src/**/*.{astro,js,jsx,svelte,ts,tsx,vue}'],
};
  • Включите конфигурацию попутного ветра в файле astro.config.mjs.
export default {
  devOptions: {
    tailwindConfig: './tailwind.config.js',
  }
};

И, наконец, нам нужно создать папку styles в каталоге src. Внутри создается файл global.css и добавляется следующее содержимое:

@tailwind base;
@tailwind components;
@tailwind utilities;

Чтобы использовать этот стиль на наших страницах, нам нужно загрузить его следующим образом:

<link rel="stylesheet" type="text/css" href={Astro.resolve('../styles/global.css')} />

Установка плагина типографики Tailwind

Поскольку наш контент исходит из WordPress, мы можем использовать плагин Tailwind Typography, чтобы не стилизовать вещи вручную.

Выполните следующую команду, чтобы установить плагин:

npm install @tailwindcss/typography

Затем откройте файл tailwind.config.js и добавьте плагин:

module.exports = {
  mode: 'jit',
  purge: ['./public/**/*.html', './src/**/*.{astro,js,jsx,svelte,ts,tsx,vue}'],
  plugins: [require('@tailwindcss/typography')],
};

И это все! Теперь мы можем использовать Tailwind и его фантастический плагин для типографики.

Создание файла .env

Поскольку наша конечная точка может различаться в зависимости от нашей среды, давайте установим пакет dotenv.

npm install --D dotenv

Затем мы можем создать файл .env, который будет содержать нашу конечную точку WordPress graphQL.

WP_URL=http://localhost:8000/graphql

Повтор сеанса с открытым исходным кодом

Отладка веб-приложения в рабочей среде может быть сложной и трудоемкой. OpenReplay — это альтернатива FullStory, LogRocket и Hotjar с открытым исходным кодом. Это позволяет вам отслеживать и воспроизводить все, что делают ваши пользователи, и показывает, как ваше приложение ведет себя при каждой проблеме. Это похоже на то, как если бы инспектор вашего браузера был открыт, когда вы смотрите через плечо вашего пользователя. OpenReplay — единственная доступная в настоящее время альтернатива с открытым исходным кодом.

Удачной отладки, для современных фронтенд-команд — Начните бесплатно отслеживать свое веб-приложение.

Создание вызовов API в Astro

Итак, мы настроили WordPress и запустили базовый веб-сайт Astro. Пришло время объединить этих двоих.

Создайте папку lib в каталоге src и создайте файл с именем api.js.

Этот файл будет содержать вызовы нашего API к конечной точке WordPress GraphQL API.

Первое, что нам нужно сделать в этом файле, это загрузить нашу среду.

import dotenv from 'dotenv';
dotenv.config();
const API_URL = process.env.WP_URL;

Затем нам нужно создать базовый вызов fetchAPI, который будет выполнять наши запросы GraphQL. Этот общий вызов будет обрабатывать URL-адрес и фактическую публикацию.

async function fetchAPI(query, { variables } = {}) {
  const headers = { 'Content-Type': 'application/json' };
  const res = await fetch(API_URL, {
    method: 'POST',
    headers,
    body: JSON.stringify({ query, variables }),
  });
  const json = await res.json();
  if (json.errors) {
    console.log(json.errors);
    throw new Error('Failed to fetch API');
  }
  return json.data;
}

Затем давайте создадим функцию, которая будет извлекать все наши страницы WordPress, на которых есть ярлык.

export async function getAllPagesWithSlugs() {
  const data = await fetchAPI(`
  {
    pages(first: 10000) {
      edges {
        node {
          slug
        }
      }
    }
  }
  `);
  return data?.pages;
}

Как видите, мы передаем запрос GraphQL в нашу функцию fetchAPI и возвращаем все страницы, которые получаем взамен.

Помните, что вы можете опробовать эти запросы GraphQL в средстве просмотра GraphQL подключаемого модуля WordPress.

Приведенный выше запрос даст нам только слаги для каждой страницы. Мы можем пойти дальше и создать подробный вызов, который может получить содержимое страницы на основе ее слага.

export async function getPageBySlug(slug) {
  const data = await fetchAPI(`
  {
    page(id: "${slug}", idType: URI) {
      title
      content
    }
  }
  `);
  return data?.page;
}

Рендеринг страниц WordPress в Astro

Теперь, когда мы настроили эти функции, нам нужно динамически создавать эти страницы в нашем внешнем проекте Astro.

Помните, как Astro выводит статический HTML? Это означает, что нам нужен способ получить их и динамически создавать эти страницы.

К счастью, Astro может сделать это для нас!

Чтобы создать динамическую страницу, мы должны создать файл с именем [slug].astro в нашем каталоге pages.

Поскольку это файл Astro, он состоит из двух частей: кода и HTML. Код завернут во фронтматер (три строки) и выглядит так:

---
Code
---
<html>
    <h1>HTML</h1>
</html>

Давайте сначала импортируем две нужные нам функции из нашего файла API.

---
import { getAllPagesWithSlugs, getPageBySlug } from '../lib/api';
---

Затем Astro поставляется с функцией getStaticPaths, которая позволяет нам создавать динамические страницы.

Внутри этой функции мы можем обернуть все наши страницы следующим образом:

export async function getStaticPaths() {
  const pagesWithSlugs = await getAllPagesWithSlugs();
}

И затем мы можем сопоставить их, чтобы вернуть заблокированную страницу для каждой из наших страниц WordPress.

export async function getStaticPaths() {
  const pagesWithSlugs = await getAllPagesWithSlugs();
  return pagesWithSlugs.edges.map(({ node }) => {
    return {
      params: { slug: node.slug },
    };
  });
}

Вы можете видеть, что имя файла должно совпадать с параметрами, так как у нас есть [slug] в качестве имени файла. Параметры также должны быть slug.

const { slug } = Astro.request.params;
const page = await getPageBySlug(slug);

Тогда последнее, что нам нужно, это получить текущую страницу на основе слага.

Затем мы можем перейти к части HTML для отображения страницы!

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>{page.title}</title>
    <meta name="viewport" content="width=device-width" />
    <link rel="stylesheet" type="text/css" href={Astro.resolve('../styles/global.css')} />
  </head>
  <body>
    <div class="flex flex-col p-10">
      <div class="mb-5 text-4xl font-bold">{page.title}</div>
      <article class="prose lg:prose-xl">
        {page.content}
      </article>
    </div>
  </body>
</html>

Теперь вы сможете посетить любого из ваших слагов. Давайте посмотрим, например, на мою страницу политики конфиденциальности.

Очень здорово, что у нас есть эти страницы, но мы не можем сказать пользователю ввести URL-адреса, которые он хочет посетить.

Итак, давайте создадим основное меню в WordPress и будем использовать его!

Сначала зайдите в панель администратора WordPress и найдите раздел AppearanceMenu.

Добавьте новое меню. Вы можете дать этому любое имя, которое хотите. Однако в качестве места отображения выберите Primary menu.

Затем вы можете продолжить и добавить несколько страниц в это меню.

Следующее, что нам нужно сделать, это запросить это меню в нашем файле lib/api.js в нашем внешнем проекте.

export async function getPrimaryMenu() {
  const data = await fetchAPI(`
  {
    menus(where: {location: PRIMARY}) {
      nodes {
        menuItems {
          edges {
            node {
              path
              label
              connectedNode {
                node {
                  ... on Page {
                    isPostsPage
                    slug
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  `);
  return data?.menus?.nodes[0];
}

Чтобы использовать это, давайте создадим новый компонент, который мы можем использовать повторно. Помните, что это одна из сил, которые дает нам Астро.

Создайте файл Header.astro в каталоге components. Там давайте сначала перейдем к разделу кода.

---
import { getPrimaryMenu } from '../lib/api';
const { menuItems } = await getPrimaryMenu();
---

Это позволит получить все пункты меню в основном меню, которое мы только что определили.

Далее раздел HTML для этого:

<nav class="flex flex-wrap items-center justify-between p-6 bg-blue-500 shadow-lg">
  <a href="/" class="cursor-pointer p-4 ml-2 text-white">AstroPress</a>
  <ul class="flex items-center justify-end flex-grow">
    {menuItems.edges.map((item) => 
        <li key={item.node.path}>
            <a href={item.node.connectedNode.node.slug} class={`cursor-pointer p-4 ml-2 text-white`}>
                {item.node.label}
            </a>
        </li>
    )}
  </ul>
</nav>

Чтобы использовать этот компонент и увидеть его в действии, давайте откроем файл [slug].astro и импортируем его в наш раздел кода.

---
import Header from '../components/Header.astro';
---

Затем мы можем использовать его в нашем разделе HTML, добавив следующий код в наш тег body.

<body>
    <Header />
    <!-- Other code -->
</body>

А если обновить наш проект, то у нас получится супер крутое меню!

Вывод

Сегодня мы узнали, как настроить WordPress как безголовую CMS и как загрузить ее через конечную точку GraphQL на веб-сайте Astro.

Для меня это приносит лучшее из двух миров.

WordPress как устоявшаяся система CMS, которую мы не хотим перестраивать с нуля. И Astro как SSG, который выводит для нас максимально быстрый веб-сайт!

Отсюда варианты бесконечны, так как вы можете получать сообщения, пользовательские элементы и многое другое из WordPress.

Если вам интересно, вы можете найти полный код на GitHub. Или посмотрите пример сайта здесь.

Первоначально опубликовано на https://blog.openreplay.com 8 октября 2021 г.