2 minute read

Давай разберём разницу между фоновой страницей (Manifest V2) и Service Worker (Manifest V3).

✅ Manifest V2 (Фоновая страница) — Старый подход

📌 Как это работало:

  • Фоновая страница представляла собой постоянный HTML файл с JavaScript, который оставался запущенным постоянно.
  • Он занимал память и процессор, даже когда ничего не происходило.

📂 Структура проекта:

/my-chrome-extension
|-- manifest.json
|-- background.html
|-- background.js

📄 manifest.json:

{
  "manifest_version": 2,
  "name": "My V2 Extension",
  "version": "1.0",
  "background": {
    "page": "background.html"
  },
  "permissions": ["activeTab"]
}

📄 background.html:

<!DOCTYPE html>
<html>
<head>
    <script src="background.js"></script>
</head>
<body>
</body>
</html>

📄 background.js:

chrome.runtime.onInstalled.addListener(() => {
    console.log("Расширение установлено!");
});

🔍 Проблемы Manifest V2:

  1. Постоянно занимает память и процессор.
  2. Работает даже когда не нужно.
  3. Негативно влияет на производительность и автономность ноутбуков.

✅ Manifest V3 (Service Worker) — Новый подход

📌 Как это работает:

  • Вместо фоновой страницы используется Service Worker — специальный JavaScript файл, который запускается только когда нужно, например:
    • При установке расширения.
    • При взаимодействии с браузером (например, клик по иконке).
    • При приёме сообщений.
  • Когда он бездействует — автоматически выгружается из памяти.

📂 Структура проекта:

/my-chrome-extension
|-- manifest.json
|-- background.js

📄 manifest.json:

{
  "manifest_version": 3,
  "name": "My V3 Extension",
  "version": "1.0",
  "background": {
    "service_worker": "background.js"
  },
  "permissions": ["activeTab"]
}

📄 background.js (Service Worker):

chrome.runtime.onInstalled.addListener(() => {
    console.log("Расширение установлено!");
});

🔍 Преимущества Manifest V3:

  1. Автоматическая выгрузка: Когда код не выполняется, Chrome выгружает Service Worker из памяти.
  2. Лучшее управление ресурсами: Скрипт запускается только по событиям, что экономит процессорное время и батарею.
  3. Безопасность: Новый подход ограничивает доступ к некоторым API, улучшая безопасность.

📌 Пример сценария:

  1. В Manifest V2, если ты открываешь страницу chrome://extensions/ и смотришь в Task Manager (Shift + Esc), ты увидишь, что фоновая страница всегда активна.
  2. В Manifest V3, Service Worker будет активен только во время обработки события и автоматически выгружается.

Это не просто внутренняя оптимизация Chrome — изменения влияют и на разработку. Давай разберёмся.

🔍 Что изменилось для разработчика?

  1. Новый способ регистрации фонового скрипта:
    • В Manifest V2 — через "background": { "page": "background.html" }.
    • В Manifest V3 — через "background": { "service_worker": "background.js" }.
    • Теперь нет HTML файла. Только один JS файл, который работает как Service Worker.
  2. Отсутствие глобального контекста:
    • В Manifest V2 фоновая страница была постоянно активна, и все переменные, объекты и функции в background.js оставались в памяти.
    • В Manifest V3 твой Service Worker не хранит состояние между событиями — он загружается при вызове события и выгружается, когда не нужен.
    • Например, вот такой код больше не сработает:

        let counter = 0;  // Это не будет работать как ожидается
        chrome.runtime.onMessage.addListener(() => {
            counter++;
            console.log(counter);  // Будет почти всегда 1, потому что Service Worker выгружается
        });
      
    • Нужно использовать API для хранения данных, например, chrome.storage:

        chrome.runtime.onMessage.addListener(() => {
            chrome.storage.local.get(['counter'], (result) => {
                const count = (result.counter || 0) + 1;
                chrome.storage.local.set({ counter: count });
                console.log(count);
            });
        });
      
  3. 🚀 Асинхронная работа:
    • Service Worker работает через Promise-based API.
    • Примеры старых колбэков можно переписать через async/await.
  4. 🔐 Ограничение API:
    • Некоторые API теперь недоступны напрямую в background.js (например, document или window), так как это не страница, а Service Worker.

📌 Пример Manifest V3 background.js с асинхронным кодом:

chrome.runtime.onInstalled.addListener(() => {
    console.log("Расширение установлено!");
});

chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
    if (message.type === "increment") {
        const result = await chrome.storage.local.get(['counter']);
        const count = (result.counter || 0) + 1;
        await chrome.storage.local.set({ counter: count });
        sendResponse({ counter: count });
    }
    return true; // Это нужно, чтобы указать Chrome, что ответ будет асинхронным.
});

💡 Что остаётся прежним:

  • Событийная модель API — всё ещё используются chrome.runtime.onInstalled, chrome.runtime.onMessage, и так далее.
  • Основная логика (регистрация событий, взаимодействие через сообщения) остаётся похожей.