Категории

React в Guttenberg (Wordpress)

1. Установка окружения

Чтобы делать кастомные блоки, лучше использовать @wordpress/scripts — это готовый билд-инструмент с webpack + Babel.

npm init @wordpress/block my-block
cd my-block
npm start

Это создаст структуру с уже готовым базовым блоком.


2. Основная структура блока

Обычно блок состоит из двух частей:

  • edit – то, что видит редактор (React-компонент)
  • save – то, что сохраняется в HTML

Пример простого блока:

import { registerBlockType } from "@wordpress/blocks";
import { RichText } from "@wordpress/block-editor";

registerBlockType("myplugin/custom-block", {
  title: "Мой блок",
  icon: "smiley",
  category: "widgets",

  attributes: {
    content: { type: "string" },
  },

  edit: ({ attributes, setAttributes }) => {
    return (
      <RichText
        tagName="p"
        value={attributes.content}
        onChange={(newContent) => setAttributes({ content: newContent })}
        placeholder="Введите текст..."
      />
    );
  },

  save: ({ attributes }) => {
    return <RichText.Content tagName="p" value={attributes.content} />;
  },
});

3. Использование React-компонентов

Ты можешь подключать свои кастомные React-компоненты внутрь блока:

const CustomButton = ({ label, onClick }) => {
  return <button onClick={onClick}>{label}</button>;
};

registerBlockType("myplugin/button-block", {
  title: "Кнопка",
  icon: "button",
  category: "widgets",

  edit: ({ attributes, setAttributes }) => {
    return (
      <CustomButton
        label="Нажми меня"
        onClick={() => alert("Hello Gutenberg!")}
      />
    );
  },

  save: () => {
    return <button>Нажми меня</button>;
  },
});

4. Хуки и UI из @wordpress/components

WordPress предоставляет готовые UI-компоненты: Button, PanelBody, ColorPalette, TextControl, и т.д.
Они стилизованы в духе WP-админки и очень экономят время.

Пример:

import { InspectorControls } from '@wordpress/block-editor';
import { PanelBody, ColorPalette } from '@wordpress/components';

edit: ({ attributes, setAttributes }) => {
  return (
    <>
      <InspectorControls>
        <PanelBody title="Настройки блока">
          <ColorPalette
            value={attributes.color}
            onChange={(color) => setAttributes({ color })}
          />
        </PanelBody>
      </InspectorControls>

      <p style={{ color: attributes.color }}>Текст с цветом</p>
    </>
  );
},

5. Где жить коду?

  • Если блоков мало — можно писать прямо в плагине.
  • Если делаешь что-то большое и модульное — выноси каждый блок в отдельную папку.

6. Рекомендации

  • React хуки работают (useState, useEffect и т.д.) – Gutenberg использует React под капотом.
  • Можно писать блоки TS/JSX@wordpress/scripts всё подтянет.
  • Если блоки нужно шарить — упаковывай в npm-пакеты.

Отлично, давай разберёмся глубже 🚀

🔧 Как билдить Gutenberg-блоки

WordPress сам по себе не даёт hot reload как в чистом CRA/Next.js, но есть инструменты, которые делают процесс максимально похожим на React-разработку.


1. Используем @wordpress/scripts

Это официальный пакет от WP, который уже включает в себя:

  • Webpack (с live reload)
  • Babel (JSX/ESNext)
  • PostCSS (стили)
  • ESLint/Prettier-конфиги

Установка:

npm init @wordpress/block my-block
cd my-block
npm start

👉 npm start — это аналог npm run dev в React: он билдит в build/ и отслеживает изменения файлов.
Когда ты сохраняешь файл — билд обновляется, и при перезагрузке страницы в WordPress изменения видны.


2. Запуск локального WordPress для разработки

Тебе нужен рабочий WordPress-сайт (локально или через Docker).

Есть два варианта:

  1. LocalWP (GUI-программа) — просто, быстро, всё на кнопках.

  2. wp-env (от WordPress) — CLI-окружение на Docker, ставится через npm:

    npm install -g @wordpress/env
    wp-env start

    После этого у тебя локально крутится WP по адресу http://localhost:8888.


3. Подключение блока к WordPress

В plugin.php (в папке плагина) подключаем билд:

<?php
/**
 * Plugin Name: My Custom Block
 */
function my_custom_block_register() {
    register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'my_custom_block_register' );

👉 build — это папка, куда складывает Webpack (@wordpress/scripts).


4. Live reload (как в React)

Прямо “горячей замены модулей” (HMR) как в CRA нет.
Но:

  • npm start пересобирает всё за секунду
  • при обновлении страницы в WP редакторе ты сразу видишь изменения

⚡ Есть костыли для HMR через webpack-dev-server, но большинство разрабов WP используют именно стандартный @wordpress/scripts.


📦 Пример продвинутого блока с React-компонентами

Вот блок, где мы используем useState, InspectorControls и кастомный UI:

import { registerBlockType } from "@wordpress/blocks";
import { InspectorControls, RichText } from "@wordpress/block-editor";
import { PanelBody, TextControl, Button } from "@wordpress/components";
import { useState } from "@wordpress/element";

registerBlockType("myplugin/advanced-block", {
  title: "Продвинутый блок",
  icon: "admin-site",
  category: "widgets",

  attributes: {
    title: { type: "string", default: "Заголовок" },
    buttonText: { type: "string", default: "Кнопка" },
  },

  edit: ({ attributes, setAttributes }) => {
    const [count, setCount] = useState(0);

    return (
      <>
        <InspectorControls>
          <PanelBody title="Настройки блока">
            <TextControl
              label="Текст кнопки"
              value={attributes.buttonText}
              onChange={(val) => setAttributes({ buttonText: val })}
            />
          </PanelBody>
        </InspectorControls>

        <div className="my-block">
          <RichText
            tagName="h3"
            value={attributes.title}
            onChange={(val) => setAttributes({ title: val })}
            placeholder="Введите заголовок..."
          />

          <Button variant="primary" onClick={() => setCount(count + 1)}>
            {attributes.buttonText} ({count})
          </Button>
        </div>
      </>
    );
  },

  save: ({ attributes }) => {
    return (
      <div className="my-block">
        <RichText.Content tagName="h3" value={attributes.title} />
        <button>{attributes.buttonText}</button>
      </div>
    );
  },
});

👉 Тут:

  • InspectorControls = боковая панель с настройками блока
  • useState = локальное состояние (счётчик)
  • RichText = редактируемый текст

🔥 О, вот это правильный вопрос! На нём часто ломаются джуны, которые впервые сталкиваются с Gutenberg.


📦 Где должен жить твой блок?

1. Как плагин (самый правильный способ)

  • Ты создаёшь папку my-block-plugin/
  • Внутри — plugin.php, src/, build/
  • Подключаешь блок через register_block_type()

✅ Плюсы:

  • Можно использовать блок в любой теме
  • Код легко переносится, версионируется, заливается в npm
  • Это best practice (WP рекомендует именно плагины)

2. Внутри темы

  • Ты можешь положить свой код в theme-name/blocks/
  • Подключать так же через functions.php

✅ Плюсы:

  • Удобно для кастомных проектов (например, сайт клиента на одной теме)
  • Всё в одном месте

❌ Минусы:

  • Если сменишь тему → блоки пропадут
  • Повторное использование блоков на других проектах усложняется

👉 Поэтому:

  • Если ты делаешь кастомный сайт клиенту → блоки можно положить прямо в тему.
  • Если хочешь переиспользуемые компоненты (библиотека блоков, набор UI) → лучше всегда плагин.

⚡ Про webpack-dev-server и HMR (чтобы реально было как CRA/Next.js)

По умолчанию @wordpress/scripts даёт только watch + пересборку. Но мы можем включить полноценный dev-server:

1. Ставим зависимости:

npm install --save-dev webpack-dev-server

2. В package.json добавляем скрипт:

"scripts": {
  "start": "wp-scripts start",
  "dev": "webpack serve --config webpack.config.js"
}

3. Настраиваем webpack.config.js:

const defaultConfig = require("@wordpress/scripts/config/webpack.config");

module.exports = {
  ...defaultConfig,
  devServer: {
    hot: true,
    port: 3000,
    proxy: {
      "/": "http://localhost:8888", // твой локальный WP
    },
  },
};

4. Запуск:

npm run dev

Теперь:

  • webpack-dev-server поднимается на http://localhost:3000
  • Все запросы проксируются в WP (http://localhost:8888)
  • React-компоненты реально обновляются без перезагрузки страницы 🎉

Окей 🚀 Давай сделаем чек-лист, как написать свой первый Gutenberg-блок на React. Я дам тебе пошаговый путь, без тонны документации, чтобы можно было реально взять и попробовать.


🔹 Шаг 1. Подготовка окружения

  1. Перейди в папку с WordPress (обычно wp-content/plugins/).
  2. Создай папку для плагина, например my-custom-block.
  3. Внутри — файл my-custom-block.php с минимальным кодом:
<?php
/**
 * Plugin Name: My Custom Block
 */

function my_custom_block_register() {
    wp_register_script(
        'my-custom-block-editor',
        plugins_url( 'build/index.js', __FILE__ ),
        array( 'wp-blocks', 'wp-element', 'wp-editor' ),
        true
    );

    register_block_type( 'my/custom-block', array(
        'editor_script' => 'my-custom-block-editor',
    ) );
}
add_action( 'init', 'my_custom_block_register' );

👉 Это зарегистрирует твой блок и подключит скрипт, собранный на React.


🔹 Шаг 2. Инициализация проекта с @wordpress/scripts

  1. В папке плагина делай:
npm init -y
npm install @wordpress/scripts --save-dev
  1. В package.json добавь скрипты:
"scripts": {
  "start": "wp-scripts start",
  "build": "wp-scripts build"
}

🔹 Шаг 3. Создай React-файл для блока

  1. В папке сделай src/index.js
  2. Простейший блок:
import { registerBlockType } from "@wordpress/blocks";
import { useBlockProps } from "@wordpress/block-editor";

registerBlockType("my/custom-block", {
  title: "My Custom Block",
  icon: "smiley",
  category: "widgets",

  edit() {
    const blockProps = useBlockProps();
    return <div {...blockProps}>Привет, я React-блок!</div>;
  },

  save() {
    const blockProps = useBlockProps.save();
    return <div {...blockProps}>Привет с фронта!</div>;
  },
});

🔹 Шаг 4. Сборка

  1. Запусти:
npm run build

(или npm start для разработки)
2. Появится папка build/ с index.js, который подключается в твоём PHP.


🔹 Шаг 5. Проверка

  • Активируй плагин в админке.
  • В редакторе Gutenberg появится блок My Custom Block.
  • Добавь его в пост или страницу — он отрендерится через React.

🔥 Дальше ты можешь усложнять:

  • Использовать InspectorControls (панель справа).
  • Подключать RichText, MediaUpload и т.п.
  • Делать динамические блоки (PHP + React).

О, тема — это уже более фундаментально, чем блок 🚀
Если блоки — это “кирпичики” для редактора, то тема в WordPress задаёт весь внешний вид сайта (шаблоны страниц, стили, блоки, навигацию).


🔹 Что нужно знать перед стартом

  1. Современные темы в WordPress = Gutenberg-блоки + React.

    • Старый подход: PHP-шаблоны (page.php, single.php и т.п.).
    • Новый подход: Block Themes — вся тема собирается из блоков (React + JSON-конфиг).
  2. У тебя два пути:

    • 🟢 Classic Theme — верстка через PHP-шаблоны (гибко, но устаревающе).
    • 🔵 Block Theme (Full Site Editing) — всё строится из блоков, можно писать React-компоненты.

Если хочешь «играть в будущее» → бери Block Theme.


🔹 Минимальный скелет темы

  1. Создай папку в wp-content/themes/my-theme.
  2. Внутри — style.css:
/*
Theme Name: My Theme
Author: Ты
Version: 1.0
*/
  1. Файл index.php (если классическая тема):
<?php get_header(); ?>
<h1>Привет из моей темы</h1>
<?php get_footer(); ?>

👉 Уже можно активировать тему в админке.


🔹 Если делать Block Theme

  1. Вместо index.php создаёшь theme.json:
{
  "version": 2,
  "settings": {
    "color": {
      "palette": [{ "slug": "primary", "color": "#0073aa", "name": "Primary" }]
    },
    "typography": {
      "fontSizes": [
        { "slug": "small", "size": "12px", "name": "Small" },
        { "slug": "large", "size": "36px", "name": "Large" }
      ]
    }
  }
}
  1. Дальше создаёшь шаблоны (например, templates/index.html):
<!-- wp:paragraph -->
<p>Привет, я блок-тема!</p>
<!-- /wp:paragraph -->
  1. Всё это работает на Gutenberg-блоках → можно писать React-блоки и вставлять их как часть темы.

🔹 Где тут React?

  • В кастомных блоках → твой React-код идёт туда.
  • В админке → интерфейсы, панели, виджеты.
  • Можно даже сделать SPA внутри темы (например, страницу портфолио или каталог товаров на React).

🔹 Для практики

  • Если хочешь быстро «подружить» React и WP → начни с Classic Theme (PHP + твой React-компонент, встроенный через wp_enqueue_script).
  • Если хочешь современно и по фану → делай Block Theme с theme.json и своими блоками.

Отлично, это самый продуктивный вариант ⚡
Берёшь свой макет → переносишь его в WordPress-тему → получаешь и практику, и готовую работу в портфолио.


🔹 Алгоритм: как переделать верстку в WordPress-тему

1. Подготовь базовую тему

  • Создай папку в wp-content/themes/my-landing.
  • Добавь style.css с метаданными:
/*
Theme Name: My Landing
Author: Adam Lean
Version: 1.0
*/
  • Сделай index.php с минимальным кодом:
<?php get_header(); ?>
<h1>Привет, это мой первый WP-лендинг</h1>
<?php get_footer(); ?>

👉 Теперь тема уже появится в админке.


2. Подключи свои CSS и JS

  • Создай functions.php:
<?php
function my_landing_enqueue() {
    wp_enqueue_style( 'my-landing-style', get_stylesheet_uri() );
    wp_enqueue_script( 'my-landing-js', get_template_directory_uri() . '/assets/js/main.js', array(), null, true );
}
add_action( 'wp_enqueue_scripts', 'my_landing_enqueue' );
  • Положи свои стили и скрипты в /assets/.

3. Разбей верстку на части

  • header.php → шапка (логотип, меню).
  • footer.php → подвал.
  • index.php → твоя основная страница (из макета).
  • Если будут отдельные страницы → page.php или single.php.

👉 WP сам будет подключать header.php и footer.php через get_header() и get_footer().


4. Динамика через WordPress

  • Тексты, заголовки, изображения → выводи через админку.
  • Простейший пример:
<?php the_title(); ?>
<?php the_content(); ?>

👉 Теперь клиент сможет менять текст прямо в редакторе, а не в коде.


5. Добавь «гибкости»

  • Используй Custom Fields (через ACF или Gutenberg).
  • Например: в блоке «Отзывы» сделай повторяющиеся поля → и клиент добавляет отзывы прямо из админки.