Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как включить импорт/экспорт внутри chrome.tabs.executeScript?

    mihail430899
    @mihail430899 Автор вопроса
    Вебмастер
    Короче ответ на собственный же вопрос получился приличной портянкой. Текущее решение во второй части ответа, а в первой саммари из обсуждения на stackoverflow.

    В общем вот вопрос на stackoverflow под которым собралось больше всего разных решений https://stackoverflow.com/questions/48104433/how-t...
    Что я понял из этого всего:
    1. Самое лучшее - разобраться с Webpack и собирать код браузерного плагина через него. Возможно другой сборщик тоже прокатит, тот же Parcel.
    2. Можно обойтись без import/export, подключив несколько скриптов сверху вниз и используя в нижнем функции и переменные из верхних. Но мне кажется, что это не так уж и удобно для разработки. Императивный подход подобного мультиподключения для плагинов на mv2 (manifest.json v2) неудобен, т.к. надо один executeScript оборачивать другим. Декларативный чуть удобнее, но тогда надо все это лепить прямо в manifest.json, у этого тоже вижу свои минусы. Если делать плагин на mv3, там дела у императивщины лучше, т.к. вместо file в executeScript указывается массив files.
    3. Хак с промежуточным файлом в executeScript, который вставляет на веб-страницу уже собственно наш скрипт с бизнес-логикой (а еще в manifest.json нужно добавить скрипты в web_accessible_resources). Я попробовал, сработало, но выглядит это решение не очень изящно, а также оно было раскритиковано на stackoverflow. mv2 дает такое сделать, mv3 не пропускает столь грубый метод.
    4. Также возможно неплохая идея перенести расширение на manifest v3. Это и в целом правильно, и там на stackoverflow предложили вроде как неплохое решение для mv3, которое я тоже проверил - оно чуть лучше предыдущего, но все равно не очень, особенно если плагин большой.


    Ну а так для удобной разработки большого плагина только вариант 1 (походу).

    UPD: В итоге, после очередного перепрочтения инфы по указанной ссылке на stackoverflow, я додумался до варианта, который не иначе как мегакостылем не назовешь. Но он позволяет ограничиться одним промежуточным файлом, причем в 1 строчку, и через него подключать любое кол-во файлов, где уже свободно можно юзать импорты. А также этот способ не такой грубый, как вставка тега script напрямую на веб-страницу. В общем, мне даже понравилось.

    Костыль использует 3 решения:
    1. Один executeScript вложенный в другой
    2. Использование globalThis
    3. Использование динамического импорта

    А если конкретнее, то в background.js у меня вот что:
    chrome.tabs.executeScript(tabId, { code: 'globalThis.path = "folder/your_content_script.js"'}, () => {
      chrome.tabs.executeScript(tabId, { file: 'folder/middle.js' })
    })

    middle.js это файл в 1 строчку:
    (async () => await import(chrome.runtime.getURL(globalThis.path)))()

    И всё, это работает! Чтобы в background.js каждый раз не писать вложенный executeScript, я сделал функцию хелпер:
    function executeImportedScript(tabId, path) {
      chrome.tabs.executeScript(tabId, { code: `globalThis.path = '${path}'`}, () => {
        chrome.tabs.executeScript(tabId, { file: 'folder/middle.js' })
      })
    }

    И в нужном месте просто:
    executeImportedScript(tabId, "folder/your_content_script.js")

    Только в manifest.json в ключе web_accessible_resources должны присутствовать пути ко всем контент-скриптам + пути ко всем скриптам, из которых контент-скрипты что-то импортируют. И собственно это пока единственная проблема, которую я вижу у этого способа - разбухание manifest.json и web_accessible_resources в частности (для большого плагина).
    Ответ написан