Контекстное меню в браузерном расширении: типичные проблемы и решения
При самостоятельной разработке контекстного меню часто возникают дубликаты: каждый раз при активации 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 рабочих дней.







