Фоновые страницы: manifest V2 vs service worker (manifest v3)
Давай разберём разницу между фоновой страницей (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:
- Постоянно занимает память и процессор.
- Работает даже когда не нужно.
- Негативно влияет на производительность и автономность ноутбуков.
✅ 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:
- Автоматическая выгрузка: Когда код не выполняется, Chrome выгружает Service Worker из памяти.
- Лучшее управление ресурсами: Скрипт запускается только по событиям, что экономит процессорное время и батарею.
- Безопасность: Новый подход ограничивает доступ к некоторым API, улучшая безопасность.
📌 Пример сценария:
- В Manifest V2, если ты открываешь страницу
chrome://extensions/
и смотришь в Task Manager (Shift + Esc), ты увидишь, что фоновая страница всегда активна. - В Manifest V3, Service Worker будет активен только во время обработки события и автоматически выгружается.
Это не просто внутренняя оптимизация Chrome — изменения влияют и на разработку. Давай разберёмся.
🔍 Что изменилось для разработчика?
- ✅ Новый способ регистрации фонового скрипта:
- В Manifest V2 — через
"background": { "page": "background.html" }
. - В Manifest V3 — через
"background": { "service_worker": "background.js" }
. - Теперь нет HTML файла. Только один JS файл, который работает как Service Worker.
- В Manifest V2 — через
- ❌ Отсутствие глобального контекста:
- В 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); }); });
- В Manifest V2 фоновая страница была постоянно активна, и все переменные, объекты и функции в
- 🚀 Асинхронная работа:
- Service Worker работает через Promise-based API.
- Примеры старых колбэков можно переписать через
async/await
.
- 🔐 Ограничение API:
- Некоторые API теперь недоступны напрямую в
background.js
(например,document
илиwindow
), так как это не страница, а Service Worker.
- Некоторые API теперь недоступны напрямую в
📌 Пример 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
, и так далее. - Основная логика (регистрация событий, взаимодействие через сообщения) остаётся похожей.