Это разновидность фоновых (Background) страниц, которые не хранятся в памяти постоянно, а загружаются только когда возникают связанные с ними события. Есть еще фоновые страницы, которые хранятся в памяти постоянно (persistent). Хотя и те и другие “фоновые”, но обычно, если в документации речь идет про фоновые, то имеются ввиду постоянные.
Гугл рекомендует разработчикам переносить свои наработки на event-страницы, что как бы намекает, что в один прекрасный день останутся только они.
Манифест
{
"name": "My extension",
...
"background": {
"scripts": ["eventPage.js"],
"persistent": false
},
По умолчанию свойство persistent = true и фоновая страница является постоянной.
Жизненный цикл
Страница типа event загружается при необходимости и уничтожается когда она не нужна. Строго говоря – не обязательно. Если быть точным, браузер может освободить занимаемые ей ресурсы при необходимости. А может и не освобождать если таковой не возникло. Логика может быть достаточно изощренной, например учитывать как часто возникают события связанные со страницей, но нам она неизвестна. Страница загружается когда:
- Приложение(или расширение) установлено, или обновилось на новую версию. При этом регистрируются обработчики событий
- Возникло событие
- Странице отправлено сообщение контентным скриптом или другим расширением
- Другой элемент расширения, например всплывающее окно вызвало метод runtime.getBackgroundPage.
Будучи загруженной, страница остается в памяти пока она активна. Например, пока ожидает результатов вызовов API или сетевых запросов. Она также остается загруженной, пока активны видимые элементы расширения (всплывающие окна) или каналы сообщений. Заметьте – открытие всплывающего окна не обязательно приводит к загрузке event-страницы, но препятствует ее закрытию. Вы можете наблюдать как страница загружается и когда освобождается в диспетчере задач браузера. Кстати, заглянув туда первый раз вы охренеете, сколько памяти жрут казалось бы простые странички.
Если страница неактивна несколько секунд, возникает событие runtime.onSuspend. После этого у страницы есть еще несколько секунд, если за это время что-то успеет случится, возникает событие runtime.onSuspendCanceled.
Нам эти детали в общем-то не должны быть интересны
Регистрация событий
Когда страница загружается, она регистрирует обработчики событий вызовом addListener. Если она удалит их с помощью removeListener – страница будет выгружена из памяти. При каждой загрузке страницы обработчики событий регистрируются заново
Если нужно выполнить какую-то инициализацию при установке расширения, то для этого необходимо регистрировать обработчик события runtime.onInstalled.
Переход от использования постоянных страниц к event-страницам
- Добавляем свойство “persistent” : false в манифесте
- Если вы используете window.setTimeout() или window.setInterval(), заменяем их на вызовы chrome.alarms API. Не забываем, что использование этого API требует разрешения alarms
- Аналогично, все прочие асинхронные вызовы должны заменяться на вызовы chrome API
- Вызовы extension.getBackgroundPage необходимо заменить на runtime.getBackgroundPage. Разница между ними в том, что второй является асинхронным – страницу ведь надо еще загрузить.
Советы
- Регистрируйте все обработчики которые могут быть интересны вашему расширению. Страница загружается один раз, когда расширение устанавливается. Потом она будет загружена только при возникновении зарегистрированного события.
- Если вам нужно провести какую-то инициализацию после установки расширения, то добавьте обработчик события runtime.onInstalled. Это подходящее место для того чтобы задать правила declarativeWebRequest, или создать контекстное меню.
- Используйте storage API или IndexedDB, если вам нужно что-то хранить
- Фильтруйте события
- Ставьте обработчик на runtime.onSuspend, если хотите что-то почистить перед тем как страница будет выгружена из памяти (на мой взгляд – плохая идея). Но вместо этого гугл советует периодически сохранять данные, иначе, если расширение внезапно накроется медным тазом, не успев получить runtime.onSuspend, то ваши данные могут пропасть. А еще лучше – в принципе не храните важных данных в переменных скрипта.
- Если вы обрабатываете сообщения, не оставляйте открытыми неиспользуемые порты. Это будет препятствовать звкрытию страницы
- Если вы используете контекстное меню, не используйте параметр onclick, а передавайте строковый параметр id и анализируйте его в обработчике contextMenus.onClicked
- Типичные ошибки
- выполнение ненужной работы при каждой загрузке страницы (например контекстное меню можно создать один раз – при установке)
- Повторная установка алармов при каждой загрузке – они сбрасываются и начинают считать с начала.
- Забытые обработчики событий: некоторые события могут быть обработаны двояко – путем создания обработчика или путем передачи callback-функции. Второй способ для event-страницы череват проблемами.
Доброго времени суток. Хочу написать простенькое расширение с двумя кнопками: "копировать" и "вставить". На одной странице с таблицы нужно скопировать данные с определенных ячеек, а на другой странице вставить эти данные в форму. Как я понял, этот скрипт должен быть в "бэкграунде" для того, чтобы хранить данные в переменных. Это я и сделал, только кнопки в попапе не реагируют на клики. Потом решил инжектить сам скрипт и кнопки в код этих страниц. Но в этом случае два скрипта работают независимо друг от друга. Подскажите, пожалуйста, куда копать и как это должно выглядеть.
ОтветитьУдалить