Google chrome 在内容\脚本上下文中加载webpack chrome扩展块
我正在以amd的方式开发chrome扩展。作为js bundler,我正在使用webpack。我提取了几个条目,webpack为它们构建了几个块。我的目标是在content_脚本的上下文中实现块加载。默认情况下,行为webpack\u require确保函数将使用正确的src创建一个新的脚本标记,并将其注入dom:Google chrome 在内容\脚本上下文中加载webpack chrome扩展块,google-chrome,google-chrome-extension,webpack,content-script,Google Chrome,Google Chrome Extension,Webpack,Content Script,我正在以amd的方式开发chrome扩展。作为js bundler,我正在使用webpack。我提取了几个条目,webpack为它们构建了几个块。我的目标是在content_脚本的上下文中实现块加载。默认情况下,行为webpack\u require确保函数将使用正确的src创建一个新的脚本标记,并将其注入dom: __webpack_require__.e = function requireEnsure(chunkId, callback) { /******/ // "0"
__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
/******/ }
/******/ };
在我的例子中,我希望将块作为单独的请求加载(就像现在一样),但在当前内容的上下文中执行脚本代码:eval函数
要获得这样的smth:
/******/ __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
/******/
/******/ }
我已经通过在编译过程中注入自定义插件解决了这个问题。问题是是否有可能以“合法”(更简单)的方式实现?或者不使用自定义插件,它可以通过自定义加载程序解决
任何想法都有很多建议。chrome扩展注入新内容脚本的合法方式是通过在后台页面中进行。注入的内容脚本共享其他内容脚本的执行环境,即所谓的
- 内容脚本:
用法: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/
:
- 执行浏览器操作,即工具栏图标单击
- 执行页面操作,即在现代Chrome中单击工具栏图标
- 执行扩展的上下文菜单项
- 从commands API执行扩展的键盘快捷键
- 接受来自omnibox API的扩展的建议
- 内容脚本:
用法: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/
:
- 执行浏览器操作,即工具栏图标单击
- 执行页面操作,即在现代Chrome中单击工具栏图标
- 执行扩展的上下文菜单项
- 从commands API执行扩展的键盘快捷键
- 接受来自omnibox API的扩展的建议
- chrome extension注入新内容脚本的合法方式是通过在后台页面中进行。注入的内容脚本共享其他内容脚本的执行环境,即所谓的
modules
或exports
对象中注册自身)。不确定我是否清楚地理解了你关于stringify的话……我正在尝试加载内容脚本,其中amd模块由executeScript加载,如你所述。因此,想法非常简单:我在chrome扩展中有requirejs作为内容脚本。我只想能够加载任何请求的amd模块(按要求(['./my/file.js']I.e.)作为内容脚本。ExecuteSXcript非常适合,但requirejs无法处理响应模块..现在不知道为什么..谢谢回答!实际上最初的问题是指webpack,以及修改/更改块加载代码生成机制的最佳方式=)但您的回答告诉我如何避免eval()调用我的代码,这也很棒!我已经尝试了你对chrome.executeScript的建议,但得到了一些令人困惑的错误消息。我试图做的是使用override requirejs.load全局函数在后台页面上调用sendMessage和executeScript。chrome能够找到模块,但由于某些原因无法执行。嗯,webpack无法绕过chrome扩展的固有限制,因此它所能提供的任何特定于扩展的脚本加载功能基本上都是这样。也许在光明的未来,当chrome为扩展实现ES6模块时。如果你试图执行响应对象,它只不过是上一代的遗留物通过内部字符串化(参见我代码中的注释)对其进行评估。因此只需直接访问新模块(例如,它应该在全局modules
或exports
对象中注册自身)。不确定我是否清楚地理解了你关于stringify的话……我正在尝试加载内容脚本,其中amd模块由executeScript加载,如你所述。因此,想法非常简单:我在chrome扩展中有requirejs作为内容脚本。我只想能够加载任何请求的amd模块(按要求(['./my/file.js']I.e.)同样也是内容脚本。ExecutesXcript非常适合,但requirejs无法处理响应模块。目前不知道原因。。