Использование importScripts() в сервисном работнике в Firefox под Manifest V3

Вопрос или проблема

Я работаю над расширением для браузера. В Chrome я могу сделать это:

manifest.json:

"background": {
        "service_worker": "scripts/vh_service_worker.js",
},

и в моем сервис-воркере я могу использовать importScript("somefile.js") без проблем.

В Firefox background.service_worker не реализован для манифеста v3.

Попытка #1:
Я загружаю сервис-воркер как фоновый скрипт:

manifest.json:

"background": {
        "scripts": ["scripts/vh_service_worker.js"]
    },

Это в целом работает хорошо, но, к сожалению, кажется, что он не выполняется в WorkerGlobalScope, поэтому функция importScripts() недоступна.

Попытка #2:
Я попытался использовать фоновый скрипт для регистрации сервис-воркера вручную:

manifest.json:

"background": {
        "scripts": ["scripts/vh_service_worker_loader.js"]
    },

vh_service_worker_loader.js:

if ("serviceWorker" in navigator) {
    navigator.serviceWorker
        .register("scripts/vh_service_worker.js")
        .then((registration) => {
            console.log("Сервис-воркер зарегистрирован с областью:", registration.scope);
        })
        .catch((error) => {
            console.error("Ошибка регистрации сервис-воркера:", error);
        });
}

Но, к сожалению, нет доступной записи navigator.serviceWorker, поэтому условие if всегда возвращает false.

Так что мой вопрос:
Как я могу использовать importScripts() в Firefox для расширения, использующего манифест V3?

Ответ или решение

К сожалению, использование importScripts() в фоне (background script) веб-расширений на основе манифеста версии 3 (Manifest V3) в Firefox действительно ограничено, так как функция importScripts() доступна только в контексте веб-воркеров. В этой связи существуют несколько обходных путей, чтобы решить эту проблему.

Решение 1: Использование import вместо importScripts()

С 2023 года современный JavaScript поддерживает модули ES. Если вы можете переработать ваши скрипты, попробуйте имплементировать динамическую загрузку модулей с использованием import. Для этого вам нужно будет адаптировать ваши JS-файлы в соответствии с требованиями ES6.

Ваш файл vh_service_worker.js может выглядеть следующим образом:

// vh_service_worker.js
import { someFunction } from './somefile.js';

// Используйте someFunction и другие экспортированные элементы

Таким образом, ваша структура manifest.json будет несколько похожа на следующую:

"background": {
    "service_worker": "scripts/vh_service_worker.js"
},

Решение 2: Использование self.importScripts()

Если вы все же хотите использовать importScripts() и ваш сценарий должен оставаться в стиле совместимости с CommonJS, вам нужно убедиться, что у вас действительно загружен сервис-воркер. В background сценариях для Manifest V3 вы не можете регистрировать Service Workers через navigator.serviceWorker, как это относится к контексту веб-страницы, но вы можете использовать фреймворки или библиотеки для повышения совместимости.

Решение 3: Использование промисов

Если ваши скрипты требуют асинхронной загрузки, рассмотрите возможность создания специальной функции, которая будет загружать зависимости с использованием fetch и eval. Хотя это менее предпочтительно, оно все же позволяет параллельно загружать необходимые модули.

Пример функции:

async function loadScript(url) {
    const response = await fetch(url);
    const text = await response.text();
    eval(text);
}

// Пример использования
loadScript('scripts/somefile.js').then(() => {
    // Теперь вы можете использовать функции из somefile.js
});

Заключение

К сожалению, importScripts() не доступен в background скриптах при использовании Manifest V3 в Firefox. Рекомендую вам использовать ES6 модули и переосмыслить архитектуру ваших скриптов, чтобы они использовали стандартные возможности JavaScript, такие как import и export. Это позволит вам улучшить совместимость и упростить работу с модульной системой.

Оцените материал
Добавить комментарий

Капча загружается...