Разработка расширения для браузера Chrome (Chrome Extension)
Chrome Extensions — это веб-приложения, которые запускаются в контексте браузера и имеют доступ к вкладкам, запросам, хранилищу, закладкам и DOM страниц. Архитектура расширения отличается от обычного сайта: несколько изолированных контекстов исполнения, собственная система сообщений и отдельная песочница.
Манифест V3
Google требует Manifest V3 для всех новых расширений с 2023 года. Ключевые отличия от MV2: Service Worker вместо Background Page, декларативный declarativeNetRequest вместо динамического webRequest.
{
"manifest_version": 3,
"name": "My Extension",
"version": "1.0.0",
"description": "Описание расширения",
"permissions": ["storage", "tabs", "activeTab", "scripting"],
"host_permissions": ["https://*.example.com/*"],
"background": {
"service_worker": "background.js",
"type": "module"
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"content_scripts": [
{
"matches": ["https://*.target-site.com/*"],
"js": ["content.js"],
"css": ["content.css"],
"run_at": "document_idle"
}
],
"options_page": "options.html",
"icons": { "48": "icons/icon48.png", "128": "icons/icon128.png" }
}
Контексты исполнения
| Контекст | Доступ к DOM | Доступ к Chrome API | Срок жизни |
|---|---|---|---|
| Service Worker | Нет | Полный | По событию |
| Popup | Только своё окно | Полный | Пока открыт |
| Content Script | Страницы вкладки | Ограниченный | Пока вкладка жива |
| Options Page | Только своё окно | Полный | Пока открыта |
Обмен сообщениями
Контексты не имеют общей памяти. Общение — через chrome.runtime.sendMessage / chrome.runtime.onMessage:
// Content script -> Background
chrome.runtime.sendMessage(
{ type: 'FETCH_DATA', url: window.location.href },
(response) => console.log('Got:', response)
);
// Background (service worker)
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'FETCH_DATA') {
fetch(message.url)
.then(r => r.json())
.then(data => sendResponse({ data }));
return true; // сигнал, что ответ будет асинхронным
}
});
Для постоянного соединения — chrome.runtime.connect / Port:
// Popup
const port = chrome.runtime.connect({ name: 'popup' });
port.postMessage({ type: 'START_STREAM' });
port.onMessage.addListener(msg => updateUI(msg));
// Background
chrome.runtime.onConnect.addListener(port => {
if (port.name === 'popup') {
port.onMessage.addListener(msg => {
// обработка
});
}
});
Работа с вкладками
// Получить активную вкладку
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
// Выполнить скрипт на вкладке (MV3)
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: () => document.title,
});
// Внедрить CSS
await chrome.scripting.insertCSS({
target: { tabId: tab.id },
css: 'body { background: #fff !important; }',
});
Хранилище
chrome.storage.local — синхронизируется между контекстами расширения, не очищается при перезагрузке:
// Запись
await chrome.storage.local.set({ settings: { theme: 'dark', enabled: true } });
// Чтение
const { settings } = await chrome.storage.local.get('settings');
// Подписка на изменения
chrome.storage.onChanged.addListener((changes, area) => {
if (area === 'local' && changes.settings) {
applySettings(changes.settings.newValue);
}
});
chrome.storage.sync — синхронизируется между устройствами пользователя через Google аккаунт (лимит 100 KB, 512 байт на ключ).
Декларативная блокировка запросов (MV3)
// rules.json
[{
"id": 1,
"priority": 1,
"action": { "type": "block" },
"condition": {
"urlFilter": "||ads.example.com^",
"resourceTypes": ["script", "image"]
}
}]
// manifest.json
"declarative_net_request": {
"rule_resources": [{
"id": "ruleset_1",
"enabled": true,
"path": "rules.json"
}]
}
Сборка с Vite/Webpack
Расширение — это несколько точек входа. Конфигурация Vite:
// vite.config.js
import { defineConfig } from 'vite';
import { crx } from '@crxjs/vite-plugin';
import manifest from './manifest.json';
export default defineConfig({
plugins: [crx({ manifest })],
build: {
rollupOptions: {
input: {
popup: 'popup.html',
options: 'options.html',
},
},
},
});
Плагин @crxjs/vite-plugin автоматически обрабатывает манифест, Content Scripts и Service Worker.
Публикация в Chrome Web Store
- Зарегистрировать аккаунт разработчика ($5 единоразово)
- Собрать ZIP архив папки
dist/ - Загрузить в Chrome Web Store Developer Dashboard
- Заполнить описание, скриншоты (минимум 1280×800), иконку магазина
- Пройти ревью (обычно 1–7 дней для новых расширений)
Сроки
Простое расширение с popup, storage и content script — 3–4 рабочих дня. Расширение с перехватом запросов, боковой панелью, настройками и публикацией в Store — 7–12 дней.







