Загрузка фрагмента расширения webpack chrome в контексте content_script

Я разрабатываю расширение для Chrome в формате amd. В качестве сборщика js я использую webpack. Я извлек несколько записей, webpack создал для них несколько фрагментов. Моя цель — добиться загрузки чанка в контексте content_script. По умолчанию функция webpack_require.ensure создаст новый тег script с правильным исходным кодом и внедрит его в dom:

__webpack_require__.e = function requireEnsure(chunkId, callback) {
/******/        // "0" is the signal for "already loaded"
/******/        if(installedChunks[chunkId] === 0)
/******/            return callback.call(null, __webpack_require__);
/******/
/******/        // an array means "currently loading".
/******/        if(installedChunks[chunkId] !== undefined) {
/******/            installedChunks[chunkId].push(callback);
/******/        } else {
/******/            // start chunk loading
/******/            installedChunks[chunkId] = [callback];
/******/            var head = document.getElementsByTagName('head')[0];
/******/            var script = document.createElement('script');
/******/            script.type = 'text/javascript';
/******/            script.charset = 'utf-8';
/******/            script.async = true;
/******/
/******/            script.src = __webpack_require__.p + "" + ({}[chunkId]||chunkId) + ".chunk.js";
/******/            head.appendChild(script); // INJECT INTO DOM
/******/        }
/******/    };

В моем случае я хотел бы загрузить чанк как отдельный запрос (как сейчас), но выполнить его в контексте текущего кода content_script: функция eval.

Чтобы получить что-то вроде этого:

/******/    __webpack_require__.e = function requireEnsure(chunkId, callback) {
/******/        // "0" is the signal for "already loaded"
/******/        if(installedChunks[chunkId] === 0)
/******/            return callback.call(null, __webpack_require__);
/******/
/******/        // an array means "currently loading".
/******/        if(installedChunks[chunkId] !== undefined) {
/******/            installedChunks[chunkId].push(callback);
/******/        } else {
/******/            // start chunk loading
/******/            installedChunks[chunkId] = [callback];
/******/            var head = document.getElementsByTagName('head')[0];
/******/            var src = __webpack_require__.p + "" + ({}[chunkId]||chunkId) + ".chunk.js";
/******/            var url = chrome.extension.getURL(src);
/******/            var xhr = new XMLHttpRequest(),
/******/            evalResponseText = function (xhr) {
/******/                eval(xhr.responseText + '//# sourceURL=' + url); // execute chunk's code in context of content_script
/******/                // context.completeLoad(moduleName);
/******/            };
/******/            xhr.open('GET', url, true);
/******/            xhr.onreadystatechange = function (e) {
/******/                if (xhr.readyState === 4 && xhr.status === 200) {
/******/                    evalResponseText.call(window, xhr);
/******/                }
/******/            };
/******/            xhr.send(null); // get chunk
/******/            
/******/        }

Я уже решил это путем внедрения собственного плагина в процесс компиляции. Вопрос, можно ли добиться этого "законным" (более простым) способом? Или не использовать кастомный плагин и это можно решить кастомным загрузчиком?

Большое спасибо за любые идеи.


person SchmerZ    schedule 10.08.2016    source источник


Ответы (1)


Легальный способ для расширения Chrome внедрить новый сценарий контента — сделать это на фоновой странице через chrome.tabs.executeScript. Внедренные скрипты контента используют среду выполнения других ваших скриптов контента, так называемый изолированный мир.

person wOxxOm    schedule 10.08.2016
comment
Спасибо за ответ! На самом деле первоначальный вопрос относился к веб-пакету и как лучше всего модифицировать/изменить механизм генерации кода загрузки чанков =) Но ваш ответ дает мне ответ, как избежать вызова eval() в моем коде, и это тоже здорово! Я уже пробовал ваше предложение с chrome.executeScript, но получил несколько запутанных сообщений об ошибках. Я пытаюсь использовать глобальную функцию переопределения requirejs.load для вызова sendMessage и executeScript на фоновой странице. Chrome может найти модуль, но по какой-то причине не может его выполнить. - person SchmerZ; 11.08.2016
comment
Что ж, веб-пакет не может обойти ограничения, присущие расширениям Chrome, поэтому любые функции загрузки скриптов, специфичные для расширения, которые он когда-либо мог бы предоставить, будут в основном соответствовать этим направлениям. Возможно, в светлом будущем, когда Chrome реализует ES6-модули для расширений. - person wOxxOm; 11.08.2016
comment
Если вы пытаетесь выполнить объект ответа, это просто остаток того, что было последним оценено, кастрировано внутренней строкой (см. комментарии в моем коде). Поэтому просто обращайтесь к новому модулю напрямую (например, он должен зарегистрироваться в глобальном объекте modules или exports). - person wOxxOm; 11.08.2016
comment
Не уверен, что у меня есть четкое понимание ваших слов о stringify... Я пытаюсь загрузить сценарий содержимого, который является модулем amd, с помощью executeScript, как вы описали выше. - person SchmerZ; 11.08.2016
comment
Итак, идея довольно проста: у меня есть requirejs в расширении chrome в качестве сценария содержимого. Все, что я хочу, это иметь возможность загружать любой запрошенный модуль amd (с помощью require(['./my/file.js'] т.е.) в качестве сценария содержимого. executeSxript подходит очень хорошо, но requirejs не может обработать модуль ответа. идея почему пока.. - person SchmerZ; 11.08.2016
comment
Я имею в виду, что объект ответа не является модулем. Забудь это. Я должен был никогда не упоминать об этом. Просто переделайте свои модули, чтобы они самостоятельно регистрировались в глобальном объекте, таком как exports. - person wOxxOm; 11.08.2016
comment
Другой/лучший метод — автоматически перехватывать внедрение скрипта и оценивать его в контексте скрипта содержимого: scriptTagContext оболочка. - person wOxxOm; 06.09.2016
comment
то, что имя файла должно быть относительно корневой папки (а не относительно папки, в которой размещены скрипты), является очень важной частью информации и избавило меня от головной боли на github.com/qownnotes/web-companion, спасибо! - person Patrizio Bekerle; 08.01.2019