IHOR.DEVБАЗА_ЗНАНЬ
МЕНЮ

~/blog / Розширення / chrome-extension-message-passing-without-fragile-code.md

// посібник · 3 хв читання

Обмін повідомленнями в розширеннях Chrome без крихкого коду

Проєктуйте вузькі повідомлення Manifest V3 з runtime-перевіркою, асинхронними відповідями, авторизацією відправника й відновленням після навігації.

Коротка відповідь

Використовуйте разові повідомлення для запиту й відповіді, порти — для потоку пов’язаних оновлень. Передавайте прості JSON-сумісні записи з конкретним type, перевіряйте їх у отримувача й повертайте сталу форму успіху чи відмови. Сам TypeScript-інтерфейс не перевіряє дані іншого контексту.

runtime.sendMessage звертається до контекстів розширення; tabs.sendMessage — до контентних скриптів вкладки. Жоден виклик не гарантує існування отримувача після навігації чи завершення завдання лише через надсилання. Відокремте транспортні та прикладні відмови.

Практичні кроки реалізації

  1. Називайте запити дозволеною поведінкою: settings/read або report/save. Уникайте диспетчера довільних методів, ключів сховища чи URL від контентних скриптів.
  2. Перевіряйте типи, розміри, переліки й повноваження відправника. За потреби використовуйте sender.tab, frameId, джерело та ідентичність документа; заявлений у payload ідентифікатор вкладки не є авторизацією.
  3. Реєструйте слухача під час обчислення модуля воркера. Для широкої сумісності використовуйте неасинхронний слухач із буквальним true, якщо sendResponse буде викликано пізніше. Документація описує підтримку промісів із Chrome 148 із поступовим впровадженням; перевірте мінімальну версію перед застосуванням.
  4. Призначте одного слухача власником типу запиту. Кілька можуть виконуватися, але виграє одна відповідь. Сторонній async-слухач може випадково відповісти undefined.
  5. Обробляйте відхилені надсилання після навігації чи за відсутності скрипту. Дайте видимий повторний шлях замість мовчазного повторного впровадження змін. Для потоків обробляйте відключення порту та прив’язуйте оновлення до документа чи запуску.

Зміна сторінки й перегляд звіту LocaleStress ілюструють окремі обов’язки. Запит звіту має ідентифікувати запуск і повертати дані, а не випадково повторювати зміну тексту на довільній сторінці.

Приклад реалізації

Цей воркер повертає лише нешкідливий параметр і потребує storage. Авторизація має стати суворішою для майбутніх приватних записів чи привілейованих дій.

chrome.runtime.onMessage.addListener((message, _sender, respond) => {
  if (typeof message !== "object" || message === null
      || message.type !== "settings/read") return;
  chrome.storage.local.get({ highlights: true }).then(
    ({ highlights }) => respond({ ok: true, highlights: highlights === true }),
    () => respond({ ok: false, error: "storage-unavailable" }),
  );
  return true;
});

async function readHighlights() {
  const result = await chrome.runtime.sendMessage({ type: "settings/read" });
  if (!result || result.ok !== true || typeof result.highlights !== "boolean") {
    throw new Error("Settings unavailable");
  }
  return result.highlights;
}

Викликач має обробити відхилення readHighlights(). Перевірка охоплює неправильну відповідь і явну прикладну відмову; транспортна відмова використовує той самий шлях відновлення. Не повертайте DOM-вузли, функції чи екземпляри класів, очікуючи збереження ідентичності та методів після JSON-серіалізації Chrome.

Компроміси та альтернативи

Порти зменшують повторне підключення для прогресу, але додають відключення й багатофреймову обробку. Разовий запит простіший для параметра. Великі звіти краще один раз зберігати й отримувати за ідентифікатором замість копіювання в кожному оновленні.

Поширені помилки

  • Повертати truthy-об’єкт замість буквального true для відкладеної callback-відповіді.
  • Вважати TypeScript-приведення перевіркою отримувача.
  • Дозволяти даним сторінки вибирати привілейовані URL чи API.
  • Повторювати руйнівну дію без ідентифікатора операції.

Контрольний список випуску

  • Кожен запит має власника й обмежену перевірку.
  • Для привілейованих дій перевіряються повноваження відправника.
  • Обробляються відповіді й транспортні відмови.
  • Навігація та відключення порту відновлювані.
  • Повторення розрізняє читання й побічні ефекти.

Поширені запитання

Чи return true зберігає воркер назавжди?

Ні. Воно залишає канал асинхронної відповіді відкритим і не є загальною стратегією життєвого циклу.

Чи повідомлення створюють спільну пам’ять?

Вони передають значення між контекстами. Визначте власника й джерело істини замість удаваного спільного змінного об’єкта.

Який наступний крок?

Перевірте один запит із правильною відповіддю, неправильним введенням, недоступним сховищем і зниклим отримувачем. Це створить придатний контракт перед розширенням типів.

Первинні джерела

Пов’язані посібники та приклади

Ігор Харчишин

Незалежний full-stack інженер продуктів, який пише посібники з реалізації розширень браузера та сучасних вебпродуктів на основі першоджерел.

Потрібно реалізувати це у вашому продукті?

Перегляньте відповідні приклади продуктів або поділіться контекстом розробки вебзастосунку, розширення Chrome, API чи SaaS.