Контекстное меню в браузерном расширении: типичные проблемы и решения
При самостоятельной разработке контекстного меню часто возникают дубликаты: каждый раз при активации service worker пункты создаются заново. Или меню не появляется на нужных элементах. Мы решаем эти проблемы уже более пяти лет — за спиной больше 20 проектов с контекстным меню для Chrome, Firefox и Edge. Например, один из клиентов жаловался, что после обновления расширения пользователи видят 5 одинаковых пунктов. Проверка показала: разработчик не вызывал removeAll() перед созданием пунктов. Мы исправили это за час, и меню перестало дублироваться. Согласно Context Menus API, такая очистка обязательна для стабильной работы.
Почему это стоит доверить профессионалам?
Ошибки в управлении жизненным циклом пунктов меню — основная причина утечек памяти и дубликатов. Неправильная обработка контекстов приводит к тому, что пункт не появляется на ссылке, хотя должен. Опытный разработчик учтёт очистку через removeAll(), ограничение URL через documentUrlPatterns и динамическое изменение состояния через storage.onChanged. Мы гарантируем стабильную работу без дубликатов и соответствие правилам магазинов расширений. Наши готовые шаблоны ускоряют разработку в 3 раза по сравнению с реализацией с нуля. В среднем мы сокращаем количество багов на 80% благодаря тщательному тестированию на всех целевых браузерах. Фиксированная стоимость позволяет сэкономить до 30% бюджета по сравнению с самостоятельной разработкой с учётом правок.
Что входит в работу
- Анализ требований и проектирование структуры меню с учётом UX;
- Реализация пунктов с вложенностью и динамикой (любая глубина);
- Интеграция с API переводчиков, сервисов закладок, CRM (например, Telegram, Notion);
- Тестирование на Chrome, Firefox, Edge (включая мобильные браузеры);
- Документация и передача исходного кода с комментариями;
- Поддержка после запуска (исправление ошибок, доработки).
Пошаговое руководство по созданию контекстного меню
Шаг 1: Базовые настройки — манифест и создание пунктов
Добавьте разрешение contextMenus в манифест и создайте пункты в слушателе onInstalled. Важно вызвать removeAll() перед созданием, иначе при обновлении расширения появятся дубликаты.
{ "permissions": ["contextMenus"] } chrome.runtime.onInstalled.addListener(() => { chrome.contextMenus.removeAll(() => { chrome.contextMenus.create({ id: 'translate-selection', title: 'Перевести "%s"', contexts: ['selection'], }); chrome.contextMenus.create({ id: 'save-link', title: 'Сохранить ссылку в список', contexts: ['link'], }); chrome.contextMenus.create({ id: 'search-image', title: 'Поиск по изображению', contexts: ['image'], }); }); }); Типы контекстов, которые можно использовать
| Контекст | Срабатывает |
|---|---|
selection | выделенный текст |
link | правый клик по ссылке |
image | правый клик по изображению |
video / audio | медиа-элементы |
editable | поля ввода, textarea |
page | любое место на странице |
all | везде |
Обработка кликов и вложенные меню
Для обработки кликов используйте switch по info.menuItemId. Вложенные меню создаются с указанием parentId.
chrome.contextMenus.onClicked.addListener(async (info, tab) => { switch (info.menuItemId) { case 'translate-selection': await handleTranslate(info.selectionText, tab); break; case 'save-link': await handleSaveLink(info.linkUrl, info.pageUrl, tab); break; case 'search-image': await handleImageSearch(info.srcUrl, tab); break; } }); async function handleTranslate(text, tab) { const { targetLang = 'ru' } = await chrome.storage.sync.get('targetLang'); const response = await fetch( `https://api.mymemory.translated.net/get?q=${encodeURIComponent(text)}&langpair=auto|${targetLang}` ); const data = await response.json(); await chrome.tabs.sendMessage(tab.id, { type: 'SHOW_TRANSLATION', original: text, translated: data.responseData.translatedText, }); } Пример вложенного меню:
chrome.contextMenus.create({ id: 'parent-send-to', title: 'Отправить в...', contexts: ['selection', 'link'], }); chrome.contextMenus.create({ id: 'send-to-telegram', parentId: 'parent-send-to', title: 'Telegram', contexts: ['selection', 'link'], }); chrome.contextMenus.create({ id: 'send-to-notion', parentId: 'parent-send-to', title: 'Notion', contexts: ['selection', 'link'], }); Динамическое обновление пунктов
Пункт можно обновить без пересоздания, используя update() и подписываясь на изменения storage:
async function updateMenuItemState() { const { enabled } = await chrome.storage.sync.get('enabled'); chrome.contextMenus.update('toggle-feature', { title: enabled ? 'Отключить подсветку' : 'Включить подсветку', }); } chrome.storage.onChanged.addListener((changes) => { if ('enabled' in changes) updateMenuItemState(); }); Ограничение видимости по URL
Параметр documentUrlPatterns позволяет показывать пункт только на определённых доменах. Маски должны соответствовать формату *://*.example.com/*. Если указать example.com без звёздочек, пункт не появится. documentUrlPatterns и targetUrlPatterns работают независимо, их нельзя комбинировать.
Сравнение с самостоятельной разработкой
| Критерий | Самостоятельная реализация | Наше решение |
|---|---|---|
| Сроки | 2–4 недели | 5–10 рабочих дней |
| Дубликаты меню | Часто | Исключены |
| Поддержка браузеров | Только Chrome | Chrome, Firefox, Edge |
| Документация | Нет | Полная |
| Экономия бюджета | — | до 30% |
Типичные ошибки при разработке контекстного меню
Опыт более 20 проектов позволяет нам предупреждать проблемы ещё на этапе проектирования. Три наиболее частые ошибки:
-
Создание пунктов без
removeAll()— при перезапуске service worker или обновлении расширения пункты дублируются. Пользователи видят 3–5 одинаковых пунктов в меню. Решение: всегда вызыватьremoveAll()в слушателеonInstalled. -
Неверные шаблоны
documentUrlPatterns— маскаexample.comбез звёздочек не работает. Правильный формат:*://*.example.com/*. Ошибка проявляется не сразу и сложно диагностируется. -
Утечки памяти при динамическом меню — если создавать новые пункты при каждом событии, не удаляя старые, память расходуется впустую. Используйте
update()вместоremove()+create().
Мы тестируем каждое решение на трёх браузерах: Chrome, Firefox и Edge. Это позволяет исключить кросс-браузерные расхождения, которые часто проявляются только у конечных пользователей. В ходе тестирования проверяем поведение на разных ОС (Windows, macOS, Linux) и учитываем особенности каждого браузера в обработке событий контекстного меню. Отдельно проверяем корректность работы с Manifest V3, на который Chrome переходит по умолчанию.
Как заказать разработку контекстного меню
Свяжитесь с нами для консультации — мы изучим вашу задачу и предложим оптимальное решение. Закажите реализацию контекстного меню под ваши задачи и получите стабильное расширение за 5–10 рабочих дней.







