Блог

Знецінення блоків Gutenberg: Оновлення без порушення вмісту

Практичний посібник із безпечного оновлення блоків Gutenberg за допомогою знецінення у block.json, з кроками, прикладами та чесними компромісами.

Резюме

Оновлення блока Gutenberg часто ламає існуючі записи, які використовують стару версію. Ця стаття показує, як використовувати властивість deprecated у block.json для підтримки зворотної сумісності. Ви дізнаєтеся точні кроки, щоб захопити поточну розмітку блоку, визначити одну або декілька застарілих версій та правильно відобразити атрибути. Ми розглянемо як статичні, так і динамічні блоки з практичними прикладами. Стаття також ставить під сумнів припущення, що знецінення завжди є найкращим підходом, обговорюючи, коли чистий розрив може бути кращим. Наприкінці ви зможете впевнено оновлювати свої блоки, не ламаючи вміст ваших користувачів.

Сценарій зміни, що порушує

Шість місяців тому ви запустили кастомний блок відгуків. Він виводить простий <div> з цитатою та ім'ям автора. Тепер ваш клієнт хоче новий дизайн: автор повинен з'являтися над цитатою з іншим CSS-класом. Ви оновлюєте функцію save та render_callback блоку. Тестуєте на новому записі — виглядає чудово. Потім переходите до старого запису, який використовує цей блок. Катастрофа: текст цитати зник, автор не на своєму місці, стилі розбігаються. Ви щойно зламали кожну сторінку, яка використовує цей блок.

Це класична проблема "зміни, що порушує" у розробці блоків Gutenberg. Блоки — це по суті структури даних, поєднані з розміткою. Коли ви змінюєте розмітку, редактор не може автоматично відобразити старий вміст у нову структуру. Результатом є або помилка валідації (блок стає недійсним), або — ще гірше — тихе пошкодження, коли блок відображається неправильно.

Що таке знецінення блоку?

Знецінення блоку — це вбудований механізм Gutenberg для обробки змін версії. Визначаючи масив deprecated у block.json вашого блоку, ви кажете редактору: "Якщо ви зустрінете блок, який відповідає одній з цих старіших версій, перетворіть його на поточну версію." Кожен запис deprecated визначає попередні attributes, supports та функцію save (або render_callback). Коли редактор завантажує старий блок, він проходить масив deprecated по порядку і застосовує перше співпадіння.

Ця функція часто недооцінюється, оскільки розробники вважають, що їм ніколи не доведеться змінювати розмітку блоку. Але в реальних проектах вимоги змінюються. Якщо пропустити знецінення, ви або змушуєте користувачів видаляти та вставляти блоки заново (поганий досвід), або підтримуєте дві окремі версії блоку (безладно). Офіційний довідник розробника WordPress висвітлює це в Довіднику редактора блоків, але практичні приклади відсутні.

Крок 1: Захопіть поточний стан

Перш ніж вносити зміни, запишіть точний вивід save (або render_callback для динамічних блоків) та attributes, які ваш блок використовує зараз. Уявіть це як знімок. Для статичних блоків збережіть JSX, який повертає функція save. Для динамічних блоків збережіть PHP-розмітку, згенеровану render_callback.

Створіть новий файл у вашому плагіні під назвою deprecated.js (або подібне) і збережіть там стару функцію save. Або тримайте застарілі версії безпосередньо в головному JavaScript-файлі блоку. Ключове — зберегти цей код точно таким, яким він був при першому розгортанні блоку.

Крок 2: Визначте застарілі версії

У вашому block.json додайте масив deprecated. Кожен запис — це об'єкт, який може містити:

  • attributes (об'єкт): Попередні визначення атрибутів.
  • supports (об'єкт): Будь-які попередні налаштування підтримки, які змінилися.
  • save (функція або рядок): Попередня функція save. Для блоків лише на JavaScript ви імпортуєте стару функцію. Для динамічних блоків, які рендеряться через PHP, ви можете використовувати migrate та render_callback замість цього.
  • migrate (функція): Функція, яка відображає старі атрибути на нові (необов'язково).

Приклад:

"deprecated": [
  {
    "attributes": {
      "quote": { "type": "string", "source": "html", "selector": ".quote" },
      "author": { "type": "string", "source": "html", "selector": ".author" }
    },
    "supports": {},
    "save": "() => <div className=\"testimonial-legacy\"><p className=\"quote\">{attributes.quote}</p><p className=\"author\">{attributes.author}</p></div>"
  }
]

Примітка: Функція save у block.json зазвичай визначається на JavaScript. Якщо ви використовуєте зовнішній скрипт, вам потрібно його підключити та посилатися на ім'я функції. Або ви можете вбудувати функцію як рядок (хоча це не рекомендується для складних блоків).

Крок 3: Відобразіть атрибути

Часто ви змінюєте не лише розмітку, а й назви атрибутів або джерела. Наприклад, ви можете перейти від зберігання автора як простого рядка до поля з багатим текстом. У таких випадках використовуйте властивість migrate для перетворення старих атрибутів у нові.

migrate: (attributes) => {
  return {
    quote: attributes.quote,
    author: { content: attributes.author, level: 2 }
  };
}

Якщо ви не надасте функцію migrate, редактор просто передасть старі атрибути безпосередньо новому блоку. Це може спричинити помилки, якщо назви атрибутів змінилися.

Крок 4: Тестуйте з реальним вмістом

Після визначення застарілої версії ретельно протестуйте. Створіть новий запис, вставте старий блок (ви можете змоделювати це, вставивши серіалізований код блоку з існуючого запису) і переконайтеся, що він перетворюється на нову версію без помилок валідації. Також протестуйте редагування та збереження перетвореного блоку. Повторіть для кількох застарілих версій, якщо вони є.

Для динамічних блоків процес подібний, але з відмінністю: функція save для динамічного блоку зазвичай повертає null (блок рендериться через PHP). У застарілому записі ви можете встановити save на попередню статичну розмітку, яка використовувалася до переходу на динамічний рендеринг, або використовувати render_callback у PHP, який обробляє як старі, так і нові структури атрибутів. Це складніше, але можливо.

Застереження та компроміси

Знецінення потужне, але має недоліки. Кожна застаріла версія додає код до вашого плагіна. З часом ви можете отримати ланцюжок з п'яти чи шести застарілих версій, які рідко використовуються, але їх потрібно підтримувати. Команда ядра WordPress рекомендує зберігати принаймні дві версії назад, але далі можна розглянути чистий розрив, якщо кількість уражених записів мала.

Ще один нюанс: порядок записів deprecated має значення. Редактор проходить масив від індексу 0 вгору і використовує перше співпадіння. Якщо дві застарілі версії схожі, може застосуватися неправильна. Завжди розташовуйте найновішу застарілу версію першою (ту, яка безпосередньо передує поточній версії).

Нарешті, знецінення не обробляє вміст, який було відредаговано за допомогою глобальної зміни стилю (наприклад, через theme.json). Якщо вигляд вашого блоку залежав від глобальних стилів, які з тих пір змінилися, знецінення цього не скоригує. Можливо, вам потрібно додати скрипт міграції, який запускається при збереженні або через хук оновлення плагіна.

Коли знецінення не є відповіддю

Більшість підручників подають знецінення як обов'язкове. Насправді є ситуації, коли чистий розрив кращий. Якщо ваш блок новий і використовується лише в кількох записах, ручне оновлення цих кількох випадків може бути швидшим, ніж написання та тестування коду знецінення. Аналогічно, якщо модель даних блоку принципово інша (наприклад, ви об'єднуєте два блоки в один), знецінення може бути недостатньо гнучким. У такому випадку напишіть одноразовий скрипт міграції, який запускається при оновленні плагіна, перетворюючи старі блоки на новий формат.

Інша контрарна точка: знецінення не слід використовувати як заміну хорошого дизайну. Якщо ви передбачаєте часті зміни, розробляйте блок з урахуванням версіонування з самого початку — наприклад, зберігаючи атрибут version і використовуючи умовний рендеринг. Цей підхід, обговорений у За межами базових блоків, легший за знецінення, але вимагає передбачливості.

Висновок

Знецінення блоку — це важливий інструмент для будь-якого серйозного розробника Gutenberg. Воно дозволяє розвивати ваші блоки, не ламаючи вміст користувачів. Ключові кроки: захопити поточний стан, визначити застарілу версію в block.json, відобразити атрибути, якщо потрібно, і протестувати з реальним вмістом. Але пам'ятайте, що знецінення має витрати на підтримку. Іноді чистий розрив або версіонований дизайн блоку є більш прагматичним. Використовуйте знецінення стратегічно, не автоматично, і ваші блоки залишатимуться надійними протягом багатьох оновлень.

Для ширшої перспективи щодо створення підтримуваних плагінів дивіться Створення надійних плагінів WordPress. А якщо ви новачок у розробці блоків, За межами базових блоків допоможе вам почати.

Sources (5)