能否在Greasemonkey沙箱DOM中以@require方式加载ES6模块?
如何在Greasemonkey沙箱中以类似@require的方式加载ES6模块
针对Site B的CSP限制,以下是三种可行的ES6模块加载方案,均能在Greasemonkey沙箱中正常运行并访问本地数据库:
方案1:通过GM.xmlHttpRequest获取模块代码转Blob加载
利用GM的网络请求API获取模块内容,转为Blob URL后创建type="module"的脚本标签插入沙箱DOM,绕开CSP对外部资源的限制:
// ==UserScript== // @name Load ES6 Modules via GM.xmlHttpRequest // @match https://site-b.example.com/* // @grant GM.xmlHttpRequest // ==/UserScript== GM.xmlHttpRequest({ method: "GET", url: "http://localhost/your-main-module.js", // 你的模块路径 onload: (response) => { const moduleBlob = new Blob([response.responseText], { type: "text/javascript" }); const moduleUrl = URL.createObjectURL(moduleBlob); const script = document.createElement("script"); script.type = "module"; script.src = moduleUrl; document.head.appendChild(script); // 模块加载完成后释放Blob资源 script.onload = () => URL.revokeObjectURL(moduleUrl); } });
如果模块有依赖,可在主模块内用import引入其他子模块(子模块需同样通过该方式加载,或打包为单文件)。
方案2:内联ES6模块代码
对于小型模块,直接将模块代码以字符串形式内联到脚本中,创建模块脚本插入沙箱:
// ==UserScript== // @name Inline ES6 Module in GM // @match https://site-b.example.com/* // ==/UserScript== // 你的ES6模块代码 const moduleCode = ` export async function fetchDBData() { return await fetch("http://localhost/db-api") .then(res => res.json()); } `; const script = document.createElement("script"); script.type = "module"; script.textContent = moduleCode; document.head.appendChild(script); // 调用模块导出的方法 script.onload = async () => { const module = await import(script.src); module.fetchDBData().then(data => console.log("数据库数据:", data)); };
方案3:用@resource声明模块资源
如果模块是本地文件,可通过@resource将其嵌入脚本,再用GM.getResourceText获取内容转为Blob加载:
// ==UserScript== // @name Load ES6 Module via @resource // @match https://site-b.example.com/* // @resource myModule http://localhost/your-module.js // @grant GM.getResourceText // ==/UserScript== const moduleText = GM.getResourceText("myModule"); const moduleBlob = new Blob([moduleText], { type: "text/javascript" }); const moduleUrl = URL.createObjectURL(moduleBlob); const script = document.createElement("script"); script.type = "module"; script.src = moduleUrl; document.head.appendChild(script); script.onload = () => URL.revokeObjectURL(moduleUrl);
注意事项
- 确保脚本声明了所需的
@grant权限,比如GM.xmlHttpRequest或GM.getResourceText - 模块代码可直接调用Greasemonkey API,无需额外处理作用域
- 多模块依赖场景建议打包为单文件,减少加载复杂度
内容的提问来源于stack exchange,提问作者FlamingKitties
相关产品推荐
相关产品推荐

