Cover Image for Как создать первый блок Gutenberg с @wordpress/scripts: пошаговая инструкция

Как создать первый блок Gutenberg с @wordpress/scripts: пошаговая инструкция

24 апреля 2026

Разработка блоков для Gutenberg традиционно считается сложной задачей, особенно для тех, кто только начинает работать с WordPress. Официальная документация обширна, и легко потеряться в ней ещё до того, как напишешь первую строку кода. Многие разработчики тратят целый день на настройку Webpack, а затем просто сдаются.

Но есть хорошая новость: в 2026 году всё стало намного проще. Вам больше не нужно самостоятельно настраивать Webpack или разбираться в сложных конфигурациях сборки. Пакет @wordpress/scripts берёт на себя всю работу с инструментами сборки, а block.json упрощает регистрацию блоков до предела.

Это руководство покажет вам современный подход к разработке блоков Gutenberg — подход, который действительно прост и понятен. Вы научитесь создавать свой первый блок с нуля, поймёте структуру файлов, освоите работу с атрибутами и стилями, и узнаете, как избежать типичных ошибок, которые допускают начинающие разработчики.

Необходимые условия

Перед началом работы подготовьте:

  • Node.js версии 18 или выше и пакетный менеджер npm
  • Локальную среду разработки WordPress (Local by Flywheel, WP-CLI или WordPress Playground)

Docker, Vagrant и ручная настройка Webpack не нужны — @wordpress/scripts берёт это на себя.

Запуск проекта через @wordpress/create-block

Официальный генератор блоков создаст готовую структуру плагина. Откройте терминал и выполните:

cd wp-content/plugins
npx @wordpress/create-block my-first-block --namespace myfirstblock

После генерации вы получите:

my-first-block/
├── my-first-block.php      # Заголовок плагина + регистрация блока
├── package.json            # Зависимости и скрипты сборки
├── src/
│   ├── block.json          # Метаданные блока
│   ├── edit.js             # Компонент редактора
│   ├── save.js             # Фронтенд-разметка
│   ├── index.js            # Точка входа JavaScript
│   └── style.scss          # Стили для фронтенда
└── build/                  # Скомпилированные файлы (автогенерация)

Активируйте плагин в админке WordPress и запустите режим разработки:

cd my-first-block
npm start

Файлы из папки src/ будут компилироваться автоматически при сохранении. Блок появится в редакторе в категории «Виджеты».

Конфигурация block.json

Файл block.json содержит метаданные блока: имя, атрибуты, настройки боковой панели, пути к скриптам и стилям. WordPress читает его напрямую — отдельная регистрация в PHP не требуется.

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "myfirstblock/notice",
  "version": "1.0.0",
  "title": "Notice",
  "category": "text",
  "icon": "info",
  "description": "A simple notice block with a message and colour option.",
  "attributes": {
    "message": {
      "type": "string",
      "source": "html",
      "selector": "p"
    },
    "backgroundColor": {
      "type": "string",
      "default": "#f0f4ff"
    }
  },
  "supports": {
    "html": false,
    "align": true,
    "color": {
      "background": true,
      "text": true
    },
    "typography": {
      "fontSize": true
    }
  },
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css"
}

На что обратить внимание:

  • name — уникальный идентификатор в формате пространство-имён/название-блока, только нижний регистр
  • attributes — структура данных блока и способ их сериализации в HTML
  • supports — доступные параметры в интерфейсе редактора (выравнивание, цвет, типографика)

Разница между edit.js и save.js

edit.js — интерфейс редактора

Компонент отвечает за отображение блока внутри админки. Это React-компонент, но подключать React отдельно не нужно — библиотека доступна глобально.

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

export default function Edit( { attributes, setAttributes } ) {
  const { message, backgroundColor } = attributes;
  const blockProps = useBlockProps( {
    style: { backgroundColor },
  } );

  return (
    <>
      <InspectorControls>
        <PanelBody title="Background colour" initialOpen={ true }>
          <ColorPicker
            color={ backgroundColor }
            onChangeComplete={ ( value ) => setAttributes( { backgroundColor: value.hex } ) }
          />
        </PanelBody>
      </InspectorControls>
      <div { ...blockProps }>
        <RichText
          tagName="p"
          value={ message }
          onChange={ ( value ) => setAttributes( { message: value } ) }
          placeholder="Write your notice here..."
        />
      </div>
    </>
  );
}

save.js — фронтенд-разметка

Этот файл генерирует статический HTML, который сохраняется в базу данных при публикации поста. Рендеринг происходит один раз — при сохранении, а не при каждой загрузке страницы.

import { useBlockProps, RichText } from '@wordpress/block-editor';

export default function Save( { attributes } ) {
  const { message, backgroundColor } = attributes;
  const blockProps = useBlockProps.save( {
    style: { backgroundColor },
  } );

  return (
    <div { ...blockProps }>
      <RichText.Content tagName="p" value={ message } />
    </div>
  );
}

Регистрация в PHP

Файл плагина остаётся минималистичным. Функция register_block_type считывает block.json из папки build/ и регистрирует блок автоматически.

<?php
/**
 * Plugin Name: My First Block
 * Plugin URI:  https://kamalhosen.com
 * Description: A simple custom Gutenberg block.
 * Version:     1.0.0
 * License:     GPL-2.0-or-later
 */

if ( ! defined( 'ABSPATH' ) ) {
  exit;
}

add_action( 'init', function() {
  register_block_type( __DIR__ . '/build' );
} );

Статические и динамические блоки

Статические блоки хранят готовый HTML в базе данных. Подходят для контента, который не меняется после публикации.

Динамические блоки рендерятся через PHP при каждом запросе страницы. Используйте, если вывод зависит от актуальных данных (последние посты, виджеты, форма обратной связи).

Для создания динамического блока:

  • В save.js верните null
  • Добавьте параметр render_callback при регистрации в PHP
add_action( 'init', function() {
  register_block_type( __DIR__ . '/build', [
    'render_callback' => 'myfirstblock_render_notice',
  ] );
} );

function myfirstblock_render_notice( array $attributes, string $content ): string {
  $message    = wp_kses_post( $attributes['message'] ?? '' );
  $bg_color   = sanitize_hex_color( $attributes['backgroundColor'] ?? '#f0f4ff' );

  return sprintf(
    '<div style="background-color: %s;">%s</div>',
    esc_attr( $bg_color ),
    $message
  );
}

Основные пакеты @wordpress

  • @wordpress/block-editor — хуки и компоненты редактора: useBlockProps, RichText, InspectorControls, инструменты работы с цветом и выравниванием
  • @wordpress/components — UI-элементы: PanelBody, TextControl, ToggleControl, Button, ColorPicker
  • @wordpress/data — доступ к хранилищу данных редактора (текущий пост, настройки, выделенный блок)
  • @wordpress/i18n — локализация: функция __( 'строка', 'текстовое-домен' ) для переводов интерфейса
  • @wordpress/api-fetch — запросы к REST API WordPress с встроенной аутентификацией и обработкой ошибок
  • @wordpress/hooks — система хуков для JavaScript: addFilter, addAction, doAction

Типичные проблемы и решения

Ошибки валидации блока

При изменении save.js WordPress покажет ошибку валидации для постов, где блок уже использовался. Варианты решения:

  1. Использовать динамический блок с render_callback — структура генерируется на лету, валидация не требуется
  2. Добавить deprecated-версии в block.json — для обратной совместимости старой разметки
  3. Изменить имя блока в block.json — подходит на этапе разработки, старые блоки останутся как есть

Категории блоков

В поле category укажите одно из стандартных значений: text, media, design, widgets, theme, embed.

Для собственной категории добавьте фильтр в PHP:

add_filter( 'block_categories_all', function( array $categories ): array {
  return array_merge( $categories, [
    [
      'slug'  => 'my-plugin',
      'title' => 'My Plugin',
      'icon'  => null,
    ],
  ] );
} );

Проверка на фронтенде

После добавления блока в пост опубликуйте материал и откройте страницу в режиме инкогнито. Фронтенд загружает скомпилированный style-index.css и результат работы render_callback (если блок динамический) — не файлы редактора.

Если в админке блок отображается корректно, а на сайте — нет, проверьте:

  • Совпадают ли классы и структура в save.js и PHP-рендерере
  • Подключаются ли стили из папки build/
  • Нет ли кэша браузера или плагина кэширования