在 content_script 上下文中加载 webpack chrome 扩展块 [英] webpack chrome extension chunk loading in content_script context

查看:40
本文介绍了在 content_script 上下文中加载 webpack chrome 扩展块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在以 amd 的方式开发 chrome 扩展.作为 js 打包器,我使用的是 webpack.我提取了几个条目,webpack 为它们构建了几个块.我的目标是在 content_script 的上下文中实现块加载.默认行为 webpack_require.ensure 函数将创建一个具有正确 src 的新脚本标记并将其注入到 dom 中:

I'm developing chrome extension in amd way. As js bundler I'm using webpack. I have extracted several entries, webpack constructed several chunks for them. My goal is to achieve chunk loading in context of content_script. By default behavior webpack_require.ensure function will create a new script tag with proper src and inject it into the 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 函数.

For my case I would like to load chunk as separate request (like it works now) but execute in context of current content_script code: 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
/******/            
/******/        }

我已经通过自定义插件注入到编译过程中解决了这个问题.问题是否有可能以合法"(更简单)的方式实现?或者不使用自定义插件,可以通过自定义加载器解决?

I already solved it by custom plugin injection into compilation process. The question if it's possible to achieve in 'legal' (simpler) way? Or not to use custom plugin and it could be solved by custom loader?

感谢您的任何想法.

推荐答案

chrome 扩展程序注入新内容脚本的一种合法方式是通过 chrome.tabs.executeScript.注入的内容脚本共享您其他内容脚本的执行环境,即所谓的孤立世界.

A legal way for chrome extension to inject a new content script is to do it in the background page via chrome.tabs.executeScript. Injected content scripts share the execution environment of your other content scripts, the so-called isolated world.

  • 内容脚本:

  • content script:

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
    .............
}

  • 后台脚本:

  • background script:

    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:

  • manifest.json:

    允许 chrome.tabs.executeScript 注入到 https://example.com/(或使用 ):

    Allow chrome.tabs.executeScript to inject into https://example.com/ (or use <all_urls>):

    "permissions": ["tabs", "https://example.com/*"],
    

    或者,最好是,如果您的扩展程序被批准的用户手势激活:

    Alternatively, and preferably, in case your extension is activated by an approved user gesture:

    "permissions": ["activeTab"],
    

    用户手势列表:

    • 执行浏览器操作,即点击工具栏图标
    • 在现代 Chrome 中执行页面操作,即点击工具栏图标
    • 执行扩展程序的上下文菜单项
    • 从命令 API 执行扩展程序的键盘快捷键
    • 从多功能框 API 接受您的扩展程序的建议

    这篇关于在 content_script 上下文中加载 webpack chrome 扩展块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆