Многие люди жалуются на трудности при создании блоков и приложений Гутенберга. Кривая обучения крутая, в основном из-за сложности установки и настройки среды разработки. Кроме того, твердые знания JavaScript, Node.js, React и Redux являются обязательными ингредиентами для этого довольно сложного рецепта.
Официальное руководство редактора блоков WordPress предоставляет разработчикам огромное количество информации, но вы можете потеряться в море деталей.
Стоит упомянуть то, что Матиас Вентура, ведущий архитектор проекта Гутенберга, сообщил в интервью WP Tavern:
Хотя есть люди, которые могут быстро выучить его, это все еще является большим препятствием для людей. Я думаю, в этом есть несколько уровней; документация могла бы быть на порядок лучше как в организации, так и в представлении. Надеюсь, мы сможем там сделать намного больше.
Имея это в виду, мы решили предоставить пошаговое руководство, призванное помочь нашим читателям начать разработку блока Гутенберга.
Звучит интересно? Погрузимся!
Содержание статьи
- 1 Предпосылки разработки блока Гутенберга
- 2 Что такое блок Гутенберга?
- 3 Настройка среды разработки WordPress
- 4 Обзор строительных лесов для стартовых блоков
- 5 The Project: Building Your First Gutenberg Block
- 6
Sign Up For the Newsletter
- 6.1 Want to know how we increased our traffic over 1000%?
- 6.2 Using Built-In Components: The RichText Component
- 6.3 Info
- 6.4 Important
- 6.5 Adding Controls to the Block Toolbar
- 6.5.1 Step 1: Import BlockControls and AlignmentControl Components from @wordpress/block-editor
- 6.5.2 Step 2: Add BlockControls and AlignmentControl Elements
- 6.5.3 Step 3: Define the align Attribute in block.json
- 6.5.4 Step 4: Define the Event Handlers
- 6.5.5 Step 5: Save Data
- 6.5.6 Step 1. Import InspectorControls and PanelColorSettings Components from @wordpress/block-editor
- 6.5.7 Step 2: Include the Corresponding Elements Into Your JSX code
- 6.5.8 Step 3: Define the Necessary Attributes in block.json
- 6.5.9 Step 4: Define the Event Handlers
- 6.5.10 Step 5: Save Data
- 6.6 Adding and Customizing an External Link
- 6.7 Adding Multiple Block Styles
- 6.8 Nesting Gutenberg Blocks With the InnerBlocks Component
- 6.9 Additional Improvements
- 7 Summary
Предпосылки разработки блока Гутенберга
Для этого урока требуются только навыки — хорошее знание разработки плагинов WordPress и, по крайней мере, базовое понимание HTML, CSS, JavaScript и React.
Будет ли это амбициозный проект? Готов поспорить, будет!
Было нелегко найти правильный компромисс между полнотой и простотой или решить, какие темы включить, а какие опустить.
Надеюсь, читатели среднего и продвинутого уровней простят нас за то, что мы не вникаем глубоко в определенные концепции, такие как состояние React, хранилище Redux, компоненты высокого порядка и так далее. Эти темы требуют дополнительного места и внимания и, вероятно, слишком сложны для начала разработки блоков (если вы не разработчик React).
По той же причине мы не будем освещать некоторые более сложные темы, связанные с разработкой блоков Гутенберга, такие как динамические блоки и мета-блоки.
Обладая знаниями, которые вы получите к концу этой статьи, вы сразу сможете начать получать удовольствие и работать продуктивно.
Как только вы начнете строить блоки, вы сможете еще больше улучшить свои навыки и самостоятельно строить еще более сложные блоки Гутенберга.
Что такое блок Гутенберга?
С момента своего первого выпуска в декабре 2018 года редактор блоков был значительно улучшен во всех аспектах: более мощные API-интерфейсы, более продвинутый пользовательский интерфейс, улучшенное удобство использования, множество новых блоков, первые реализации полного редактирования сайта, и многое другое.
Короче говоря, даже если Gutenberg все еще находится в стадии интенсивной разработки, он прошел долгий путь — и сегодня редактор блоков является полноценным кандидатом в качестве надежного функционального конструктора страниц и сайтов.
С точки зрения разработчика, Gutenberg — это одностраничное приложение (SPA) на основе React, которое позволяет пользователям WordPress создавать, редактировать и удалять контент в WordPress. Однако это не должно наводить на мысль об улучшенной версии традиционного редактора контента.
Мы хотим прояснить это:
В Гутенберге контент разделен на блоки, которые представляют собой «кирпичики», которые пользователи могут использовать для создания сообщений и страниц или целых своих веб-сайтов.
Но что технически представляет собой блок?
Нам нравится определение WordPress:
«Блок» — это абстрактный термин, используемый для описания единиц разметки, которые в совокупности образуют контент или макет веб-страницы. Идея сочетает в себе концепции того, чего мы сегодня достигаем в WordPress с помощью шорткодов, настраиваемого HTML и встраивания открытий в единый согласованный API и пользовательский интерфейс.
Названия, абзацы, столбцы, изображения, галереи и все элементы, составляющие интерфейс редактора, от боковых панелей до элементов управления блокировкой панели инструментов, являются компонентами React.
Итак, что такое компоненты React? W3Schools дает следующее определение:
Компоненты — это независимые и многократно используемые биты кода. Они служат той же цели, что и функции JavaScript, но работают изолированно и возвращают HTML через функцию
render ()
.
Хотя возможности редактирования, предоставляемые Гутенбергом, новы по сравнению с классическим редактором WordPress, то, как WordPress хранит фрагменты контента в базе данных, вообще не меняется. Это потому, что Gutenberg — это приложение, которое работает в WordPress, но не меняет принцип работы CMS по своей сути.
Сообщения (включая сообщения, страницы и пользовательские типы сообщений), созданные с помощью Gutenberg, по-прежнему хранятся в таблице wp_posts
как и в классическом редакторе.
Но в сообщении, созданном с помощью Gutenberg, вы найдете дополнительную информацию в таблице, которая представляет фундаментальное различие между сообщениями, созданными с помощью Classic Editor, и Gutenberg.
Эти фрагменты информации выглядят как комментарии HTML, и у них есть особая функция: разделение блоков:
Разделители блоков сообщают WordPress, какой блок должен отображаться на экране. Они также предоставляют значения для свойств блока в объекте JSON. Эти свойства определяют способ отображения блока на экране:
Настройка среды разработки WordPress
Для создания современной среды разработки JavaScript требуется глубокое знание передовых технологий, таких как Webpack, React и JSX, Babel, ESLint и т. Д.
Запугать? Не надо! Сообщество WordPress уже пришло на помощь, предоставив мощные инструменты, которые позволят вам избежать запутанного процесса ручной настройки.
Чтобы не усложнять задачу, мы не будем рассматривать транспиляцию в этой статье (с которой мы тем не менее рекомендуем ознакомиться после того, как вы изучите основы разработки блоков). Вместо этого мы представим два альтернативных инструмента, которые вы можете использовать, чтобы быстро и легко настроить современную среду разработки JavaScript за несколько минут. Вам решать, какой из них наиболее удобен для вашего проекта.
Настройка среды разработки JavaScript для построения блоков Гутенберга состоит из трех этапов:
- Установите Node.js и npm
- Настройка среды разработки
- Настройте плагин блокировки
Приступим.
1. Установите Node.js и npm
Перед установкой среды разработки и регистрацией первого блока вам необходимо установить Node.js и диспетчер пакетов Node (npm).
Вы можете установить Node.js и npm несколькими способами. Но сначала вы можете проверить, установлено ли уже программное обеспечение на вашем компьютере.
Для этого запустите терминал и выполните следующую команду:
узел -v
Если результат команда не найдена
значит Node.js не установлен на вашем компьютере, и вы можете продолжить установку.
В этой статье мы выбрали самый простой вариант установки — Node Installer. Все, что вам нужно сделать, это загрузить версию, соответствующую вашей операционной системе, и запустить мастер установки:
После установки Node.js снова введите в терминале команду node -v
. Вы также можете запустить команду npm -v
чтобы убедиться, что у вас есть доступный пакет npm.
Теперь у вас есть следующие инструменты:
- Средство выполнения пакетов
npx
Node.js (см. Документацию). Это позволяет запускать командуnpm
без ее предварительной установки. - Диспетчер пакетов
npm
Node.js (см. Документацию). Это используется для установки зависимостей и запуска скриптов.
Следующим шагом является установка среды разработки.
2. Настройте среду разработки
Если на вашем локальном компьютере установлены последние версии Node.js и npm, вам понадобится среда разработки для WordPress.
Вы можете использовать локальную среду разработки, например DevKinsta, или официальный инструмент WordPress. Давайте взглянем на оба варианта.
Вариант 1. Среда локальной разработки (DevKinsta)
Всего несколькими щелчками мыши вы можете установить WordPress локально с помощью DevKinsta, нашего современного локального инструмента разработки WordPress. Или вы можете выбрать другой локальный инструмент разработки, такой как MAMP или XAMPP:
Вариант 2: wp-env
Вы также можете выбрать официальный инструмент wp-env
который предоставляет локальную среду разработки WordPress, которую вы можете запустить непосредственно из командной строки. Ной Ален дает следующее определение:
Локальные среды WordPress теперь так же просты, как выполнение одной команды.
wp-env
— это инструмент с нулевой конфигурацией для безболезненных локальных сред WordPress. Он предоставляет решения по вариантам, чтобы пользователи могли быстро развернуть WordPress, не теряя времени. Действительно, цель состоит в том, чтобы сделать эти среды легкодоступными для всех — будь то разработчик, дизайнер, менеджер или кто-либо еще.
Если вы решите попробовать, установка wp-env
потребует минимальных усилий. Просто выполните следующие действия:
Шаг 1. Подтвердите установку Docker и Node.js
Для соответствия техническим требованиям вам сначала необходимо установить на вашем компьютере и Docker, и Node.js. Это потому, что wp-env
создает экземпляр Docker, на котором запущен веб-сайт WordPress. Любые изменения, внесенные в код, немедленно отражаются в экземпляре WordPress.
Шаг 2. Установите @ wordpress / env
из командной строки
Если на вашем компьютере запущены Docker и Node.js, вы можете продолжить и установить среду разработки WordPress.
Вы можете установить wp-env
как глобально, так и локально. Чтобы сделать это глобально, вам нужно будет запустить следующую команду из каталога плагинов (подробнее об этом в поле «Важное» ниже):
npm install -g @ wordpress / env
Давайте разберемся:
Чтобы подтвердить, что wp-env
был успешно установлен, выполните следующую команду:
wp-env --version
Вы должны увидеть текущую версию wp-env
что означает, что теперь вы можете запустить среду, используя следующую команду из папки вашего плагина:
wp-env start
Вы можете получить доступ к панели управления WordPress, используя следующий адрес:
- http: // localhost: 8888 / wp-admin /
Учетные данные по умолчанию следующие:
- Имя пользователя:
admin
- Пароль:
пароль
Настройка подключаемого модуля блока
Теперь вам нужен плагин для начального блока. Но вместо того, чтобы вручную создавать подключаемый модуль блока разработки со всеми необходимыми файлами и папками, вы можете просто запустить инструмент разработки, содержащий все файлы и конфигурации, необходимые для начала разработки блока.
Опять же, у вас есть несколько вариантов на выбор. Давайте посмотрим на каждый.
Вариант 1. Настройка подключаемого модуля блока с помощью @ wordpress / create-block
@ wordpress / create-block — официальный инструмент нулевой конфигурации для создания блоков Гутенберга:
Create Block — это официально поддерживаемый способ создания блоков для регистрации блока для плагина WordPress. Он предлагает современную настройку сборки без какой-либо конфигурации. Он генерирует код PHP, JS, CSS и все остальное, что вам нужно для запуска проекта.
Он во многом вдохновлен приложением create-react-app. Слава @gaearon, всей команде Facebook и сообществу React.
После того, как ваша локальная среда будет запущена, вы можете настроить стартовый блок, просто выполнив команду npx @ wordpress / create-block
и она предоставит все файлы и папки, которые вам нужны создать каркас плагина и зарегистрировать новый блок.
Давайте проверим, как это работает.
В инструменте командной строки перейдите в каталог / wp-content / plugins / и выполните следующую команду:
npx @ wordpress / create-block my-first-block
При запросе подтверждения введите y
чтобы продолжить:
Процесс занимает несколько минут. По завершении вы должны получить следующий ответ:
Вот и все!
Теперь запустите среду разработки WordPress и перейдите на экран Плагины на панели управления WordPress. Новый плагин под названием «My First Block» должен был быть добавлен в ваш список плагинов:
При необходимости активируйте подключаемый модуль, создайте новую запись в блоге, прокрутите страницу вставки блоков до раздела Виджеты и выберите новый блок:
Теперь вернитесь в терминал и измените текущий каталог на my-first-block :
cd my-first-block
Затем выполните следующую команду:
npm start
Это позволяет запускать плагин в режиме разработки. Чтобы создать производственный код, вы должны использовать следующую команду:
npm run build
Вариант 2. Настройка подключаемого модуля блока с помощью create-guten-block
create-guten-block
— это сторонний инструмент разработки для создания блоков Гутенберга:
create-guten-block
— это набор инструментов с нулевой конфигурацией (# 0CJS) для разработки блоков WordPress Gutenberg за считанные минуты без настройки React, webpack, ES6 / 7 / 8 / Далее, ESLint, Babel и т. Д.
Как и официальный инструмент create-block
create-guten-block
основан на приложении create-react-app и может помочь вам без проблем сгенерировать ваш первый подключаемый модуль блока.
Набор инструментов предоставляет все необходимое для создания современного плагина WordPress, включая следующее:
- Поддержка синтаксиса React, JSX и ES6.
- Разработка / производственная сборка webpack за кулисами.
- Дополнительные языковые возможности помимо ES6, такие как оператор распространения объекта.
- Автоматические префиксы CSS, поэтому вам не нужны -webkit или другие префиксы.
- Скрипт сборки для объединения JS, CSS и изображений для производства с исходными картами.
- Беспроблемные обновления для вышеуказанных инструментов с помощью единственной зависимости cgb-скриптов.
Обратите внимание на следующее предостережение:
Компромисс заключается в том, что эти инструменты предварительно настроены для работы определенным образом. Если ваш проект требует дополнительной настройки, вы можете «извлечь» и настроить его, но тогда вам нужно будет сохранить эту конфигурацию.
Когда у вас будет локальный веб-сайт WordPress, запустите инструмент командной строки, перейдите в папку / wp-content / plugins вашей установки и выполните следующую команду:
npx create-guten-block my-first-block
Вам придется подождать минуту или две, пока структура проекта будет создана и зависимости загружены:
По завершении процесса вы должны увидеть следующий экран:
На следующем изображении показана структура проекта с терминалом, работающим в Visual Studio. Код:
Теперь вернитесь в свою панель управления WordPress. На экране "Плагины" должен появиться новый элемент — это плагин my-first-block :
Активируйте плагин и вернитесь в терминал. Измените текущий каталог на my-first-block затем запустите npm start
:
cd my-first-block
npm start
Вы должны получить следующий ответ:
Опять же, это позволяет запускать плагин в режиме разработки. Чтобы создать производственный код, вы должны использовать:
npm run build
Активируйте плагин и создайте новую запись или страницу, затем просмотрите свои блоки и выберите свой новый блок Гутенберга:
Для более подробного обзора или в случае ошибок обратитесь к документации, предоставленной Ахмадом Авайсом.
Обзор строительных лесов для стартовых блоков
Какой из двух инструментов разработки — create-block
или create-guten-block
— вы выберете, теперь у вас есть блочные леса, которые вы можете использовать в качестве отправной точки. для создания плагина блока.
Но что такое блочные леса?
Структура блоков — это сокращенный термин, который описывает вспомогательную структуру каталогов, необходимую WordPress для распознавания блока. Обычно в этот каталог входят такие файлы, как index.php index.js style.css и другие, которые, в свою очередь, содержат такие вызовы, как
register_block_type
.
Мы выбрали официальный инструмент разработчика Create Block который используется в Руководстве редактора блоков. Но даже если вы решите использовать сторонний инструмент, например create-guten-block
ваш опыт не сильно изменится.
С учетом сказанного, давайте углубимся в инструмент create-block
.
Подробнее об инструменте Create Block Dev-Tool
Как мы упоминали выше, Create Block — это официальный инструмент командной строки для создания блоков Gutenberg. Запуск @ wordpress / create-block
в вашем терминале генерирует файлы PHP, JS и SCSS и код, необходимый для регистрации нового типа блока:
npx @ wordpress / create-block [options] [slug]
-
[slug]
(необязательно) — используется для назначения заголовка блока и установки плагина -
[options]
(необязательно) — доступные варианты
По умолчанию назначается шаблон ESNext. Это означает, что вы получите следующую версию JavaScript с добавлением синтаксиса JSX.
Если вы опустите имя блока, команда будет запущена в интерактивном режиме, что позволит вам настроить несколько параметров перед созданием файлов:
npx @ wordpress / create-block
На изображении ниже показана файловая структура плагина блока, созданного с помощью официального инструмента Create Block:
С учетом сказанного, давайте пройдемся по основным файлам и папкам нашего нового подключаемого модуля блокировки.
Файл подключаемого модуля
С помощью основного файла плагина вы регистрируете блок на сервере:
/ **
* Имя плагина: My First Block
* Описание: Пример блока, написанного со стандартом ESNext и поддержкой JSX - требуется этап сборки.
* Требуется минимум: 5.8
* Требуется PHP: 7.0
* Версия: 0.1.0
* Автор: Авторы WordPress.
* Лицензия: GPL-2.0 или выше.
* URI лицензии: https://www.gnu.org/licenses/gpl-2.0.html
* Текстовый домен: мой первый блок
*
* @package create-block
* /
/ **
* Регистрирует блок, используя метаданные, загруженные из файла `block.json`.
* За кулисами он также регистрирует все активы, чтобы их можно было поставить в очередь
* через редактор блоков в соответствующем контексте.
*
* @ см. https://developer.wordpress.org/block-editor/tutorials/block-tutorial/writing-your-first-block-type/
* /
function create_block_my_first_block_block_init () {
register_block_type (__DIR__);
}
add_action ('init', 'create_block_my_first_block_block_init');
Функция register_block_type
регистрирует тип блока на сервере, используя метаданные, хранящиеся в файле block.json .
Функция принимает два параметра:
- Имя типа блока, включая пространство имен, или путь к папке, где находится файл block.json или полный объект
WP_Block_Type
- Массив аргументов блочного типа
В приведенном выше коде аргумент типа блока предоставляется магической константой __ DIR __
. Это означает, что файл block.json находится в той же папке, что и файл плагина.
Файл package.json
Файл package.json определяет свойства и сценарии JavaScript для вашего проекта. Здесь вы можете установить зависимости вашего проекта.
Чтобы лучше понять, для чего предназначен этот файл, откройте его в своем любимом редакторе кода:
{
"имя": "мой-первый-блок",
"версия": "0.1.0",
"description": "Пример блока, написанного со стандартом ESNext и поддержкой JSX - требуется этап сборки.",
"author": "Авторы WordPress",
"лицензия": "GPL-2.0 или новее",
"main": "build / index.js",
"scripts": {
"build": "wp-scripts build",
"формат": "формат wp-скриптов",
"lint: css": "wp-scripts lint-style",
"lint: js": "wp-scripts lint-js",
"start": "запуск wp-скриптов",
"пакеты-обновление": "wp-скрипты пакеты-обновление"
},
"dependencies": {
"@ wordpress / block-editor": "^ 7.0.1",
"@ wordpress / blocks": "^ 11.0.1",
"@ wordpress / i18n": "^ 4.2.1"
},
"devDependencies": {
"@ wordpress / scripts": "^ 18.0.0"
}
}
Свойство scripts
— это словарь, содержащий команды, которые запускаются в разное время в жизненном цикле пакета с использованием npm run [cmd]
.
.
В этой статье мы будем использовать следующие команды:
-
npm run build
— создать (сжатую) производственную сборку -
npm run start
— создать (несжатую) сборку разработки
зависимости
и devDependencies
— это два объекта, отображающие имя пакета на версию. зависимости
требуются в производственной среде, а devDependences
необходимы только для локальной разработки (подробнее).
Единственная зависимость разработчика по умолчанию — это пакет @ wordpress / scripts
который определяется как «набор повторно используемых скриптов, адаптированных для разработки WordPress».
Файл block.json
Начиная с WordPress 5.8, файл метаданных block.json является каноническим способом регистрации типов блоков.
Наличие файла block.json дает несколько преимуществ, включая улучшенную производительность и лучшую видимость в каталоге плагинов WordPress:
С точки зрения производительности, когда темы поддерживают отложенную загрузку ресурсов, блоки, зарегистрированные с помощью block.json будут иметь оптимизированную постановку своих ресурсов в очередь из коробки. Внешние ресурсы CSS и JavaScript, перечисленные в свойствах стиля
или
скрипта
будут помещены в очередь только тогда, когда блок присутствует на странице, что приведет к уменьшению размеров страницы.
При выполнении команды @ wordpress / create-block
создается следующий файл block.json :
{
"apiVersion": 2,
"имя": "создать-блок / мой-первый-блок",
"версия": "0.1.0",
"title": "Мой первый блок",
"категория": "виджеты",
"icon": "смайлик",
"description": "Пример блока, написанного со стандартом ESNext и поддержкой JSX - требуется этап сборки.",
"поддерживает": {
"HTML": ложь
},
"textdomain": "мой-первый-блок",
"editorScript": "файл: ./ build / index.js",
"editorStyle": "файл: ./ build / index.css",
"стиль": "файл: ./ build / style-index.css"
}
Вот полный список свойств по умолчанию:
-
apiVersion
— версия API, используемая блоком (текущая версия — 2) -
имя
— уникальный идентификатор блока, включая пространство имен -
версия
— текущая версия блока -
title
— отображаемый заголовок для блока -
категория
— категория блока -
значок
— ярлык Dashicon или пользовательский значок SVG -
описание
— краткое описание, отображаемое в инспекторе блоков -
поддерживает
— набор параметров для управления функциями, используемыми в редакторе -
textdomain
— текстовый домен плагина -
editorScript
— определение скрипта редактора -
editorStyle
— определение стиля редактора style
— provides alternative styles for a block
In addition to the properties listed above, you can (and probably will) define an attributes
object providing information about data stored by your block. In your block.json you can set any number of attributes in key/value pairs, where the key is the attribute name and the value is is the attribute definition.
Take a look at the following example of attribute definitions:
"attributes": {
"content": {
"type": "array",
"source": "children",
"selector": "p"
},
"align": {
"type": "string",
"default": "none"
},
"link": {
"type": "string",
"default": "https://kinsta.com"
}
},
We’ll dive deeper into the block.json file later in the article, but you may also want to check the Block Editor Handbook for more detailed information about block.json metadata and attributes.
The src Folder
The src
folder is where the development happens. In that folder, you’ll find the following files:
- index.js
- edit.js
- save.js
- editor.scss
- style.scss
index.js
The index.js file is your starting point. Here you will import dependencies and register the block type on the server:
import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import save from './save';
registerBlockType('create-block/my-first-block', {
edit: Edit,
save,
});
The first statement imports the registerBlockType
function from the @wordpress/blocks
package. The following import statements import the stylesheet along with the Edit
and save
functions.
The registerBlockType
function registers the component on the client. The function takes two parameters: a block name namespace/block-name
(the same as registered on the server) and a block configuration object.
The Edit
function provides the block interface as rendered in the block editor, while the save
function provides the structure that will be serialized and saved into the database (read more).
edit.js
edit.js is where you’ll build the block admin interface:
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit() {
return (
{__('My First Block – hello from the editor!', 'my-first-block')}
);
}
First, it imports the __
function from the @wordpress/i18n
package (this package contains a JavaScript version of the translation functions), the useBlockProps
React hook, and the editor.scss
file.
Following that, it exports the React component (read more about import and export statements).
save.js
The save.js file is where we build the block structure to be saved into the database:
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
export default function save() {
return (
{__(
'My First Block – hello from the saved content!',
'my-first-block'
)}
);
}
editor.scss and style.scss
Apart from the scripts, two SASS files reside in the src folders. The editor.scss file contains the styles applied to the block in the editor’s context, while the style.scss file contains the styles of the block for display in the frontend. We’ll dive deeper into these files in the second part of this guide.
The node_modules and build Folders
The node_modules
folder contains node modules and their dependencies. We won’t dive deeper into node packages as it is beyond the scope of this article, but you can read more in this article on where npm installs the packages.
The build
folder contains the JS and CSS files resulting from the build process. You can dive deeper into the build process in ESNext syntax and JavaScript Build Setup guides.
The Project: Building Your First Gutenberg Block
It’s time to get our hands dirty. This section will teach you how to create a plugin providing a CTA block named Affiliate Block.
The block will consist of two columns, with an image on the left and a text paragraph on the right. A button with a customizable link will be placed below the text:
This is just a simple example, but it allows us to cover the basics of Gutenberg block development. Once you get a clear understanding of the basics, you can go ahead and create more and more complex Gutenberg blocks with the help of the Block Editor Handbook and any other of the vast resources available out there.
Assuming that you have the latest version of WordPress running on your local development environment, here’s what you’re going to learn from here on:
Ready… set… go!
How to Set Up the Starter Block Plugin
Launch your command-line tool and navigate to the /wp-content/plugins folder:
Now, run the following command:
npx @wordpress/create-block
This command generates the PHP, SCSS, and JS files for registering a block in interactive mode, allowing you to add the necessary data for your block easily. For our example we’ll use the following details:
- Block slug: my-affiliate-block
- Internal namespace: my-affiliate-plugin
- Block display title: Affiliate block
- Short block description: An example block for Kinsta readers
- Dashicon: money
- Category name: design
- Plugin author: your name
- License: –
- Link to the license text: –
- Current plugin version: 0.1.0
Installing the plugin and all dependencies takes a couple of minutes. When the process is complete, you’ll see the following response:
Now, run the following command from the /wp-content/plugins folder:
cd my-affiliate-block
Finally, from within your plugin’s folder (my-affiliate-block in our example), you can start development with:
npm start
Now open the Plugins screen to find and activate the Affiliate Block plugin:
Create a new post, open the block inserter, and scroll down to the Design category. Click to add the Affiliate Block:
block.json at Work
As we mentioned earlier, the server-side block registration takes place in the main .php file. However, we won’t define settings in the .php file. Instead, we’ll be using the block.json file.
So, open block.json again and take a closer look at the default settings:
{
"apiVersion": 2,
"name": "my-affiliate-plugin/my-affiliate-block",
"version": "0.1.0",
"title": "Affiliate Block",
"category": "design",
"icon": "money",
"description": "An example block for Kinsta readers",
"supports": {
"html": false
},
"textdomain": "my-affiliate-block",
"editorScript": "file:./build/index.js",
"editorStyle": "file:./build/index.css",
"style": "file:./build/style-index.css"
}
Scripts and Styles
editorScript
editorStyle
and style
properties provide the relative paths to frontend and backend scripts and styles.
You don’t have to manually register the scripts and styles defined here because these are automatically registered and enqueued by WordPress. To prove that, launch the browser inspector and open the Network tab:
As you can see from the image above, our index.js script residing in the build folder has been regularly enqueued without having to add any PHP code.
UI Labels
The title
and description
properties provide the labels needed to identify the block in the editor:
Keywords
As we mentioned earlier, you can accurately configure your block settings using properties and attributes. For example, you can add one or more keywords
to help users search blocks:
{ "keywords": [ "kinsta", "affiliate", "money" ] }
If you now input “kinsta”, “affiliate” or “money” in the quick inserter, the editor will suggest you the Affiliate block:
Localization
If you are wondering how the localization of the strings in the JSON file happens, here is the answer:
In JavaScript, you can use now
registerBlockTypeFromMetadata
method from@wordpress/blocks
package to register a block type using the metadata loaded from block.json file. All localized properties get automatically wrapped in_x
(from@wordpress/i18n
package) function calls similar to how it works in PHP withregister_block_type_from_metadata
. The only requirement is to set thetextdomain
property in the block.json file.
Here we are using the registerBlockType
function instead of registerBlockTypeFromMetadata
as the latter has been deprecated since Gutenberg 10.7, but the mechanism is the same.
Using Built-In Components: The RichText Component
The elements that make up a Gutenberg block are React components, and you can access these components via the wp
global variable. For example, try to type wp.editor
into your browser’s console. This will give you the full list of the components included in the wp.editor
module.
Scroll through the list and guess what components are meant for by their names.
Similarly, you can check the list of components included in the wp.components
module:
Now go back to the edit.js file and take a closer look at the script:
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit() {
return (
{__('My First Block – hello from the editor!', 'my-first-block')}
);
}
This code generates a static block with simple, non-editable text. But we can change things easily:
To make the text editable you’ll have to replace the current
tag with a component that makes the input content editable. For that, Gutenberg provides the built-in RichText component.
Adding a built-in component to your block is a 5 step process:
- Import the required components from a WordPress package
- Include the corresponding elements into your JSX code
- Define the necessary attributes in the block.json file
- Define event handlers
- Save data
Step 1: Import the Required Components from a WordPress Package
Now open the edit.js file and change the following import
statement:
import { useBlockProps } from '@wordpress/block-editor';
…to:
import { useBlockProps, RichText } from '@wordpress/block-editor';
This way, you’re importing the useBlockProps
function and RichText
component from the @wordpress/block-editor
package.
useBlockProps
The useBlockProps
React hook marks the block’s wrapper element:
When using API version 2, you must use the new
useBlockProps
hook in the block’sedit
function to mark the block’s wrapper element. The hook will insert attributes and event handlers needed to enable block behavior. Any attributes you wish to pass to the block element must be passed throughuseBlockProps
and the returned value be spread onto the element.
To put things simply, useBlockProps
automatically assign attributes and classes to the wrapper element (the p
element in our example):
If you remove useBlockProps
from the wrapper element, you’d have a simple text string with no access to block functionality and style:
As we’ll explain later, you can also pass to useBlockProps
an object of properties to customize the output.
RichText
The RichText component provides a contenteditable input, allowing users to edit and format the content.
You’ll find the component documented on GitHub at gutenberg/packages/block-editor/src/components/rich-text/README.md.
Step 2: Include the Corresponding Elements Into Your JSX Code
...
const blockProps = useBlockProps();
return (
);
Let’s comment on the code line by line:
tagName
— the tag name of the editable HTML elementonChange
— function called when the element’s content changesallowedFormats
— an array of allowed formats. By default, all formats are allowedvalue
— the HTML string to make editableplaceholder
— placeholder text to show when the element is empty
Step 3: Define the Necessary Attributes in the block.json File
Attributes provide information about the data stored by a block, such as rich content, background color, URLs, etc.
You can set an arbitrary number of attributes within an attributes
object in key/value pairs, where the key is the attribute name and the value is the attribute definition.
Now open the block.json file and add the following attributes
prop:
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "p"
}
},
The content
attribute allows to store the text typed by the user in the editable field:
type
indicates the type of data stored by the attribute. The type is required unless you define anenum
property.source
defines how the attribute value is extracted from the post content. In our example, it’s the HTML content. Note that if you don’t provide a source property, data are stored in the block delimiter (read more).selector
is an HTML tag or any other selector, such as a class name or an id attribute.
We will pass the Edit
function an object of properties. So, go back to the edit.js file and make the following change:
export default function Edit( { attributes, setAttributes } ) { ... }
Step 4: Define Event Handlers
The RichText
element has an onChange
attribute, providing a function to call when the element’s content changes.
Let’s define that function and see the whole edit.js script:
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
return (
);
}
Now save the file and run npm run start
in your terminal window. Then, go back to your WordPress dashboard, create a new post or page and add your Affiliate block:
Add some text and switch to Code view. Here is what your code should look like:
This is my first editable Gutenberg block 🤓
If you now save the page and check the frontend result, you may be a bit disappointed because your changes do not affect the site. That’s because you have to modify the save.js file to store user input in the database when the post is saved.
Step 5: Save Data
Now open the save.js file and change the script as follows:
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
);
}
That’s what we are doing here:
- Import the
RichText
component from theblock-editor
package. - Pass several properties through an object argument to the
save
function (in this example, we are only passing theattributes
property) - Return the content of the
RichText
component
You can read more about the RichText
component in the Block Editor Handbook and find the full list of props on Github.
Now let’s take it a step further. In the next section, you’ll learn how to add controls to the block toolbar.
Adding Controls to the Block Toolbar
The block toolbar contains a set of controls allowing users to manipulate portions of block content. For each toolbar control, you’ll find a component:
For example, you could add a text alignment control for your block. All you need to do is import two components from the @wordpress/block-editor
package.
We’ll go through the same steps as the previous example:
- Import Required Components From WordPress Packages
- Include the Corresponding Elements Into Your JSX Code
- Define the Necessary Attributes in the block.json File
- Define Event Handlers
- Save Data
Step 1: Import BlockControls and AlignmentControl Components from @wordpress/block-editor
To add an alignment control to the block toolbar, you need two components:
BlockControls
renders a dynamic toolbar of controls (undocumented).AlignmentControl
renders a dropdown menu that displays alignment options for the selected block (read more)
Open the edit.js file and edit the import
statement as shown below:
import {
useBlockProps,
RichText,
AlignmentControl,
BlockControls
} from '@wordpress/block-editor';
Step 2: Add BlockControls and AlignmentControl Elements
Go to the Edit
function and insert the
element at the same level as
. Then add and
within
:
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
return (
<>
>
);
}
In the code above, <>
and >
are the short syntax for declaring React fragments, which are how we return multiple elements in React.
In this example, AlignmentControl
has two attributes:
value
provides the current value for the elementonChange
provides an event handler to run when the value changes
We have also defined additional attributes for the RichText
element (check the full list of attributes with examples)
Step 3: Define the align Attribute in block.json
Now go to the block.json file and add the align
attribute:
"align": {
"type": "string",
"default": "none"
}
Go back to the terminal, stop the current process with ^C
and start the script again with npm run start
. Then go back to the block editor, refresh the page and select the block. You should see the block toolbar with an alignment control:
Now, if you try to format the block content using the new alignment controls, you’ll see that nothing happens. That’s because we haven’t defined the event handler yet.
Step 4: Define the Event Handlers
Now define onChangeAlign
:
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
If newAlign
is undefined
then we set newAlign
to none
. Otherwise, we use newAlign
.
Our edit.js script should be complete (for now):
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
return (
<>
>
);
}
Now you can go back to the editor and align the block content.
We need to modify the save function to store block content and attributes in the database.
Step 5: Save Data
Open save.js and change the save
function as follows:
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
);
}
Finally, to make the code more readable, you can extract the individual properties from the attribute
object using the destructuring assignment syntax:
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
const { content, align } = attributes;
return (
);
}
Save the file, restart the process and return to the editor in Code editor mode. The code should look something like this:
This is my first editable Gutenberg block 🤓
Ant that’s it! You have just added an alignment control to the block toolbar 🤓
You can read more about block toolbar controls in the Block Editor Handbook.
You can also add controls to the block Settings Sidebar (or even create a new sidebar for your application).
The API provides an InspectorControls
component for that.
The Block Editor Handbook explains how to use the Settings Sidebar:
The Settings Sidebar is used to display less-often-used settings or settings that require more screen space. The Settings Sidebar should be used for block-level settings only.
If you have settings that affect only selected content inside a block (example: the “bold” setting for selected text inside a paragraph): do not place it inside the Settings Sidebar. The Settings Sidebar is displayed even when editing a block in HTML mode, so it should only contain block-level settings.
Again:
- Import Required Components From WordPress Packages
- Include the Corresponding Elements Into Your JSX Code
- Define the Necessary Attributes in the block.json File
- Define Event Handlers
- Save Data
Step 1. Import InspectorControls and PanelColorSettings Components from @wordpress/block-editor
You can add several controls to allow users to customize specific aspects of the block. For example, you can provide a color control panel. To do so, you will need to import the InspectorControls
and PanelColorSettings
components from the block-editor
module:
import {
useBlockProps,
RichText,
AlignmentControl,
BlockControls,
InspectorControls,
PanelColorSettings
} from '@wordpress/block-editor';
Step 2: Include the Corresponding Elements Into Your JSX code
Now you can add the corresponding elements to the JSX returned by the Edit
function:
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
return (
<>
>
);
}
Note that we have also updated the style
attribute of the RichText
element:
Step 3: Define the Necessary Attributes in block.json
Now define the backgroundColor
and textColor
attributes in the block.json file:
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "p"
},
"align": {
"type": "string",
"default": "none"
},
"backgroundColor": {
"type": "string"
},
"textColor": {
"type": "string"
}
},
Step 4: Define the Event Handlers
Now you need to define two functions to update backgroundColor
and textColor
on user input:
const onChangeBackgroundColor = ( newBackgroundColor ) => {
setAttributes( { backgroundColor: newBackgroundColor } )
}
const onChangeTextColor = ( newTextColor ) => {
setAttributes( { textColor: newTextColor } )
}
Step 5: Save Data
One last step: Open the save.js file and change the script as follows:
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
const { content, align, backgroundColor, textColor } = attributes;
return (
);
}
Now stop the process (^C) and run npm run start
again. Refresh the page, delete any instance of your block and add it again to your post:
Make your changes, save the post, and view it in the frontend. The changes you made in the block editor should be reflected on the front site.
Adding and Customizing an External Link
In this section, you’ll add new components to your block type:
- An
ExternalLink
component allowing users to add a customizable link to the Affiliate block - Several sidebar controls allowing users to customize link settings
Step 1. Import Components from @wordpress/components
Now you need to import several components from @wordpress/components
. Open your edit.js file and add the following import
statement:
import {
TextControl,
PanelBody,
PanelRow,
ToggleControl,
ExternalLink
} from '@wordpress/components';
PanelBody
adds a collapsible container to the Settings Sidebar.PaneRow
produces a generic container for sidebar controls.TextControl
provides a text input control.ToggleControl
provides a toggle enabling users to enable/disable a specific optionExternalLink
is a simple component to add an external link.
Step 2. Include the Corresponding Elements Into Your JSX Code
You will first add the ExternalLink
element at the same level of RichText
in a div
container:
{ linkLabel }
The ExternalLink
component is not documented, so we referred to the component itself to get the list of available attributes. Here we’re using href
className
and rel
attributes.
By default, the rel
attribute value is set to noopener noreferrer
. Our code will add the nofollow
keyword to the rel
attribute of the resulting a
tag when the toggle control is on.
Now you can add link settings to the block sidebar.
First, you’ll add a PanelBody
element inside InspectorControls
at the same level as PanelColorSettings
:
...
Here’s what we’re doing with this:
- The
title
attribute provides the panel title. initialOpen
sets whether or not the panel is initially open.
Next, we’ll add two PanelRow
elements inside PanelBody
and a TextControl
element inside each PanelRow
:
The code above should now look pretty straightforward. The two text controls allow users to set link label and URL.
We’ll also add an additional PanelRow
with a ToggleControl
to switch on/off a specific option, such as whether to include an attribute or not:
Step 3: Define the Necessary Attributes in block.json
Now define the affiliateLink
linkLabel
and hasLinkNofollow
attributes in the block.json file:
"affiliateLink": {
"type": "string",
"default": ""
},
"linkLabel": {
"type": "string",
"default": "Check it out!"
},
"hasLinkNofollow": {
"type": "boolean",
"default": false
}
Nothing more to add here! Let’s move on to defining the event handling functions.
Step 4: Define the Event Handlers
Get back to the edit.js file and add the following functions:
const onChangeAffiliateLink = ( newAffiliateLink ) => {
setAttributes( { affiliateLink: newAffiliateLink === undefined ? '' : newAffiliateLink } )
}
const onChangeLinkLabel = ( newLinkLabel ) => {
setAttributes( { linkLabel: newLinkLabel === undefined ? '' : newLinkLabel } )
}
const toggleNofollow = () => {
setAttributes( { hasLinkNofollow: ! hasLinkNofollow } )
}
These functions update the corresponding attribute values on user input.
Step 5: Save Data
Last, we have to update the save
function in save.js:
export default function save( { attributes } ) {
const { align, content, backgroundColor, textColor, affiliateLink, linkLabel, hasLinkNofollow } = attributes;
const blockProps = useBlockProps.save();
return (
);
}
Note that here we have used a regular a
element instead of ExternalLink
:
Now save data and restart your environment.
Adding Multiple Block Styles
In a previous section, you learned how to add a block toolbar control allowing users to align the user input. We can add more style controls to the block toolbar, but we can also provide a set of predefined block styles the user can choose from with a single click.
For this purpose, we’re going to use a useful feature of the Block API: Block Styles.
All you need to do is define the block.json styles
property and declare the corresponding styles in your stylesheets.
For example, you can add the following array of styles:
"styles": [
{
"name": "default",
"label": "Default",
"isDefault": true
},
{
"name": "border",
"label": "Border"
}
],
With this, you’ve just added a default style and an additional style called border
. Now go back to the block editor:
The styles will be available to the user by clicking on the block switcher and then looking for the Styles panel in the Block Settings Sidebar.
Select a style and check the classes applied to the p
element. Right-click on the block and Inspect. A new class has been added with a name structured as follows:
is-style-{style-name}
If you checked the “Border” style, then an is-style-border
class will be added to the p
element. If you checked the “Default” style, then an is-style-default
class will be added instead.
Now you only have to declare the CSS properties. Open the editor.scss file and replace the current styles with the following:
.wp-block-my-affiliate-plugin-my-affiliate-block {
padding: 2px;
&.is-style-default{
border: 0;
}
&.is-style-border{
border: 1px solid #000;
}
}
Now you can do the same with style.scss:
.wp-block-my-affiliate-plugin-my-affiliate-block {
&.is-style-default{
border: 0;
}
&.is-style-border{
border: 1px solid #000;
}
}
Stop the process (^C) and run npm run start
again.
And that’s it! Refresh the page, and have fun with your new block styles:
Nesting Gutenberg Blocks With the InnerBlocks Component
Although fully functional, our Affiliate Block is still not very appealing. To make it more engaging for the audience, we could add an image.
This may add a layer of complexity to our block, but fortunately, you don’t need to reinvent the wheel because Gutenberg provides a specific component you can use to create a structure of nested blocks.
The InnerBlocks
component is defined as follows:
InnerBlocks
exports a pair of components which can be used in block implementations to enable nested block content.
First, you’ll need to create a new .js file in the src folder. In our example, we’ll call this file container.js.
Now you’ll need to import the new resource into the index.js file:
import './container';
Go back to container.js and import the necessary components:
import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import {
useBlockProps,
InnerBlocks
} from "@wordpress/block-editor";
The next step is defining a template providing the structure inside which the blocks will be placed. In the following example, we define a template consisting of two columns containing a core Image block and our custom Affiliate block:
const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
[ 'core/column', { templateLock: 'all' }, [
[ 'core/image' ],
] ],
[ 'core/column', { templateLock: 'all' }, [
[ 'my-affiliate-plugin/my-affiliate-block', { placeholder: 'Enter side content...' } ],
] ],
] ] ];
The template is structured as an array of blockTypes (block name and optional attributes).
In the code above, we used several attributes to configure the Columns and Column blocks. Specifically, the templateLock: 'all'
attribute locks Column blocks so that the user won’t add, reorder or delete existing blocks. templateLock
can take one of the following values:
all
—InnerBlocks
is locked, and no blocks can be added, reordered, or removed.insert
— Blocks can only be reordered or removed.false
— The template is not locked.
The template is then assigned to the InnerBlocks
element:
To prevent any compatibility issue, we also added a templateLock
attribute to the InnerBlocks
component (see also issue #17262 and pull #26128).
Here is our final container.js file:
import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
[ 'core/column', { templateLock: 'all' }, [
[ 'core/image' ],
] ],
[ 'core/column', { templateLock: 'all' }, [
[ 'my-affiliate-plugin/my-affiliate-block', { placeholder: 'Enter side content...' } ],
] ],
] ] ];
registerBlockType('my-affiliate-plugin/my-affiliate-container-block', {
title: __( 'Container', 'my-affiliate-block' ),
category: 'design',
edit( { className } ) {
return(
)
},
save() {
const blockProps = useBlockProps.save();
return(
)
},
});
Additional Improvements
Our block is fully functional, but we could improve it a bit with some small changes.
We assigned the backgroundColor
attribute to the paragraph generated by the RichText
component. However, we may prefer to assign the background color to the container div
:
So, change the edit.js file and save.js div
s as follows:
...
This will allow the user to change the background of the entire block.
On the other hand, a more relevant change involves the useBlockProps
method. In the original code, we defined the constant blockProps
as follows:
const blockProps = useBlockProps();
But we can use the useBlockProps
more effectively passing a set of properties. For example, we can import classnames
from the classnames
module and set the wrapper class name accordingly.
In the following example, we assign a class name based on the value of the align
attribute (edit.js):
import classnames from 'classnames';
...
export default function Edit( { attributes, setAttributes } ) {
...
const blockProps = useBlockProps( {
className: classnames( {
[ `has-text-align-${ align }` ]: align,
} )
} );
...
}
We’ll do the same change in the save.js file:
import classnames from 'classnames';
...
export default function save( { attributes } ) {
...
const blockProps = useBlockProps.save({
className: classnames( {
[ `has-text-align-${ align }` ]: align,
} )
});
...
}
And that’s a wrap! You can now run the build for production.
Summary
And here we are, at the end of this incredible journey! We started with the configuration of the development environment and ended up creating a complete block type.
As we mentioned in the introduction, a solid knowledge of Node.js, Webpack, Babel, and React is essential for creating advanced Gutenberg blocks and positioning yourself in the market as a professional Gutenberg developer.
But you don’t need to have established React experience to start having fun with block development, though. Block development could give you motivation and goals to gain increasingly broad skills in the technologies behind Gutenberg blocks.
This guide, therefore, is far from being complete. It’s merely an introduction to a wide variety of topics that will help you get started building your very first Gutenberg blocks.
For this reason, we recommend you deepen your knowledge by carefully reading online documentation and guides. Among the many resources available out there, we recommend the following:
If you’re just starting with WordPress development, you may want to understand the basic concepts of frontend development. Here is a quick list of resources that may help you get started:
And remember that the complete code of the examples of this guide is available on Gist.
Now it’s your turn: Have you developed any Gutenberg blocks? What are the main difficulties you have experienced so far? Let us know about your experience in the comments!
Save time, costs and maximize site performance with:
- Instant help from WordPress hosting experts, 24/7.
- Cloudflare Enterprise integration.
- Global audience reach with 28 data centers worldwide.
- Optimization with our built-in Application Performance Monitoring.
All of that and much more, in one plan with no long-term contracts, assisted migrations, and a 30-day-money-back-guarantee. Check out our plans or talk to sales to find the plan that’s right for you.