Представьте: вы написали расширение для Chrome — оно работает безупречно. Потом портируете на Firefox — и половина API ведёт себя иначе. На одном из проектов для финансового агрегатора browser.storage.local в Firefox возвращал undefined без ошибки, из-за чего слетали все пользовательские настройки. Пришлось переписать 40% кода. Каждый браузер — это два дня дополнительной отладки. Мы выработали системный подход: одна кодовая база, WebExtension API, полифилы и условная сборка. Единая кодовая база позволяет сократить бюджет на 40–60% по сравнению с раздельной разработкой для каждого браузера. Экономия времени в 3-4 раза — это сокращение бюджета на 30–50%. Стоимость разработки варьируется от $1.5k–3.5k в зависимости от функциональности. Получите консультацию по вашему проекту — мы поможем выбрать оптимальный стек и оценить стоимость.
Как мы решаем проблему совместимости API?
Полифил webextension-polyfill
Mozilla разработала webextension-polyfill — он преобразует chrome.* (Callback) в browser.* (Promise) и сглаживает различия между браузерами. Согласно спецификации WebExtensions, установка одной командой:
npm install webextension-polyfill import browser from 'webextension-polyfill';
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
await browser.storage.local.set({ data: 'value' });
const result = await browser.storage.local.get('data');
Полифил сокращает время на адаптацию в 3-4 раза по сравнению с ручной обёрткой — это подтверждено на практике в проектах финансового и e-commerce секторов.
Совместимость API по браузерам
| API | Chrome | Firefox | Edge | Opera | Safari |
|---|---|---|---|---|---|
storage.local |
MV2/3 | MV2/3 | MV2/3 | MV2/3 | 14+ |
storage.sync |
✓ | ✓ | ✓ | ✓ | 15+ |
tabs |
✓ | ✓ | ✓ | ✓ | 14+ |
scripting (MV3) |
✓ | 101+ | ✓ | 92+ | 15.4+ |
declarativeNetRequest |
✓ | 113+ | ✓ | 92+ | 15.4+ |
sidePanel |
114+ | — | — | — | — |
webRequest |
MV2 only | ✓ | MV2 only | MV2 only | — |
Различия есть — например, sidePanel доступен только в Chrome 114+. Для таких случаев мы применяем условные пути и fallback-реализации. Общий принцип: полифил покрывает 90% типовых операций, остальное — ручная адаптация, которая надёжнее, чем множащиеся обёртки.
Почему мы используем раздельные манифесты?
Chrome с MV3 требует service_worker, Firefox с MV2 — background.scripts. Поддерживать оба манифеста параллельно — стандартная практика для максимального охвата. Мы собираем итоговый манифест скриптом из manifest.base.json + целевые настройки под каждый браузер:
// scripts/build.js
const fs = require('fs');
const target = process.env.TARGET_BROWSER;
const manifests = {
chrome: {
manifest_version: 3,
background: {
service_worker: 'background.js'
},
action: {
default_popup: 'popup.html'
},
},
firefox: {
manifest_version: 2,
background: {
scripts: ['background.js'],
persistent: false
},
browser_action: {
default_popup: 'popup.html'
},
browser_specific_settings: {
gecko: {
id: '[email protected]',
strict_min_version: '109.0'
},
},
},
safari: {
manifest_version: 3,
background: {
service_worker: 'background.js'
},
action: {
default_popup: 'popup.html'
},
browser_specific_settings: {
safari: {
strict_min_version: '15.4'
},
},
},
};
const base = JSON.parse(fs.readFileSync('./manifest.base.json', 'utf8'));
const merged = {
...base,
...manifests[target]
};
fs.writeFileSync('./dist/manifest.json', JSON.stringify(merged, null, 2)); Сравнение манифестов MV2 и MV3
| Аспект | MV2 | MV3 |
|---|---|---|
| Background | background.scripts + Browser Action | Service Worker + Action |
API webRequest | Полная поддержка | Только declarativeNetRequest |
API tabs | Полная | С ограничениями (не в service worker) |
| Безопасность | Выполнение произвольного кода | Запрещено eval(), ограничены remote scripts |
| Установка | Ручная или автоматическая | Требуется подпись и обновления via store |
Выбор MV2 или MV3 зависит от целевых браузеров и функциональности. Например, для расширения, активно использующего webRequest, в Chrome всё ещё приходится тянуть MV2, хотя Firefox уже работает с MV3 через declarativeNetRequest. Мы помогаем определить оптимальную стратегию.
Как избежать ошибок при работе с сообщениями?
Строгая типизация сообщений между контекстами — залог отсутствия silent-багов. Мы используем дискриминированный union на TypeScript:
// shared/messages.ts
export type Message =
| { type: 'GET_PAGE_DATA'; url: string }
| { type: 'SET_BADGE'; count: number; color?: string }
| { type: 'OPEN_OPTIONS' }
| { type: 'EXTRACT_TEXT'; selector: string };
export type MessageResponse<T extends Message> =
T extends { type: 'GET_PAGE_DATA' }
? { title: string; meta: Record<string, string> }
: T extends { type: 'EXTRACT_TEXT' }
? { text: string }
: void;
export async function sendMessage<T extends Message>(
message: T
): Promise<MessageResponse<T>> {
return browser.runtime.sendMessage(message) as Promise<MessageResponse<T>>;
}
export function onMessage<T extends Message['type']>(
type: T,
handler: (
msg: Extract<Message, { type: T }>,
sender: browser.runtime.MessageSender
) => Promise<MessageResponse<Extract<Message, { type: T }>>>
) {
browser.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.type === type) {
handler(msg, sender).then(sendResponse);
return true;
}
});
}
Такой подход гарантирует, что обработчик получит именно тот тип сообщения, который ожидает. Компилятор не пропустит несоответствие. Типизированные сообщения — стандарт для всех наших проектов, включая финансовые и e-commerce расширения с сотнями тысяч пользователей.
Что входит в работу
Мы предоставляем готовое решение под ключ:
- Архитектура и проектирование — выбор стека, типизация, структура файлов.
- Реализация и тестирование — написание кода, unit-тесты, E2E-тесты с Playwright.
- Сборка и CI/CD — настройка Vite, скрипты сборки, GitHub Actions для публикации.
- Документация — README, описание API, инструкция по сборке.
- Публикация — загрузка в Chrome Web Store, Firefox AMO, Edge Add-ons, Opera Addons (Safari — по запросу).
- Поддержка — гарантийный период 30 дней после сдачи, исправление багов, адаптация к новым версиям браузеров.
Мы имеем опыт разработки расширений для финансового сектора, e-commerce и SaaS — более 5 лет и 30+ успешных проектов. Свяжитесь с нами для оценки вашего проекта — мы поможем выбрать оптимальную архитектуру.
Сроки
Кроссбраузерное расширение (Chrome + Firefox + Edge) с единой кодовой базой, типизацией, автосборкой и публикацией в три магазина — 10–16 рабочих дней в зависимости от функциональности. Добавление Safari (Xcode-обёртка + App Store) прибавляет 5–8 дней. Сроки ревью магазинов — отдельно и параллельно.
Закажите разработку кроссбраузерного расширения — мы оценим вашу задачу за один рабочий день. Получите консультацию по телефону или в чате, чтобы обсудить функциональность и сроки.







