我以amd方式开发chrome扩展。作为js bundler,我使用webpack。我已经提取了几个条目,webpack为它们构建了几个块。我的目标是在content_script的上下文中实现块加载。默认行为 webpack_require 。确保函数将创建一个带有正确src的新脚本标记并将其注入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
/******/ }
/******/ };
对于我的情况,我想将chunk作为单独的请求加载(就像它现在一样)但是在当前content_script代码的上下文中执行: eval function。
得到那样的东西:
/******/ __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
/******/
/******/ }
我已经通过自定义插件注入编译过程解决了这个问题。这个问题是否有可能实现“合法”的合法性。 (更简单)的方式?或者不使用自定义插件,它可以通过自定义加载器解决?
对任何想法都很感兴趣。答案 0 :(得分:1)
Chrome扩展程序注入新内容脚本的合法方式是通过chrome.tabs.executeScript在后台页面中执行此操作。注入的内容脚本共享其他内容脚本的执行环境,即所谓的isolated world。
内容脚本:
function loadScript(fileName, callback) {
// fileName: file name relative to the extension root folder: 'js/blah.js'
// callback: receives an array,
// in our case there'll be only one element as we inject in one frame,
// each element is an injected script's last evaluated expression
// that underwent internal JSON.stringify + JSON.parse
// thus losing anything except simple stringifiable data
chrome.runtime.sendMessage({
action: 'loadContentScript',
fileName: fileName,
}, callback);
}
用法:
loadScript('js/lib/something.js', function(r) {
console.log('something was dropped:', r);
// call something in something
.............
}
后台脚本:
chrome.runtime.onMessage(function(msg, sender, sendResponse)) {
if (msg.action == 'loadContentScript') {
chrome.tabs.executeScript(sender.tab.id, {
file: msg.fileName,
frameId: sender.frameId,
runAt: 'document_start', // just in case, force an immediate execution
}, sendResponse);
}
return true; // keeps the message channel open while async executeScript runs
});
的manifest.json:
允许chrome.tabs.executeScript注入https://example.com/
(或使用<all_urls>
):
"permissions": ["tabs", "https://example.com/*"],
或者,最好是在您的扩展程序由批准的用户手势激活时:
"permissions": ["activeTab"],
user gestures的列表: