如何在Tampermonkey的站点脚本中引用已安装的工具脚本?
问题场景与需求
我需要让代码在一个页面以隔离模式运行,在另一个页面的主页面环境运行。为避免本地工具文件误删或移动导致不可用,我把工具代码放在Tampermonkey中,目前已安装三个用户脚本:utility、site A、site B。
utility脚本代码:
// ==UserScript== // @name utility // @namespace http://sjngm/ // @grant none // ==/UserScript== // 大概是这样的结构 const Utility = { func: () => { ... } };
现在要在site A脚本中加载utility的功能,我尝试了以下代码但无法正常工作:
// ==UserScript== // @name site A // @namespace http://sjngm/ // @match http*://site-a.com/* // @grant GM_xmlhttpRequest // ==/UserScript== (function() { 'use strict'; // 尝试用这种方式加载,但不行 GM_xmlhttpRequest({ method: "GET", url: "utility", // 这里是核心问题,找不到脚本 onload: (e) => { console.log(e.responseText); } }); })();
问题在于这段代码会基于当前页面URL去加载"utility",而我需要直接引用Tampermonkey内部的utility脚本,请问这是否可行?该如何实现?
可行的实现方案
方法1:利用Tampermonkey的@require指令(推荐)
这是最直接的方式,把utility脚本的核心代码单独保存,再在业务脚本中通过@require引入:
- 把
utility的核心逻辑保存为独立文件,比如utility.js:
const Utility = { func: () => { // 你的工具函数逻辑 } };
- 修改
site A脚本的元信息,添加@require指向该文件的本地路径或远程地址:
// ==UserScript== // @name site A // @namespace http://sjngm/ // @match http*://site-a.com/* // @require file:///C:/Users/你的用户名/Desktop/utility.js // Windows本地路径示例 // @grant none // ==/UserScript== (function() { 'use strict'; // 直接调用Utility对象的方法 console.log(Utility.func()); })();
- 本地路径格式:Windows用
file:///开头,Linux/macOS用file://开头(如file:///home/xxx/utility.js)。 - 若担心本地文件丢失,可把
utility.js上传到静态托管服务,用远程URL作为@require地址。
方法2:通过Tampermonkey存储共享代码
不想用外部文件的话,可把utility代码存入Tampermonkey的GM存储,其他脚本读取后执行:
- 修改
utility脚本,添加存储权限并写入代码:
// ==UserScript== // @name utility // @namespace http://sjngm/ // @grant GM_setValue // ==/UserScript== const utilityCode = ` const Utility = { func: () => { // 工具函数逻辑 } }; `; // 将代码存入GM存储 GM_setValue("utilityCode", utilityCode);
- 在
site A脚本中读取并执行代码:
// ==UserScript== // @name site A // @namespace http://sjngm/ // @match http*://site-a.com/* // @grant GM_getValue // ==/UserScript== (function() { 'use strict'; const utilityCode = GM_getValue("utilityCode"); if (utilityCode) { eval(utilityCode); // 执行工具函数 console.log(Utility.func()); } })();
- 注意:
eval存在安全风险,确保只有你能修改存储的代码内容。
方法3:脚本间消息通信调用功能
通过Tampermonkey的消息API,让utility脚本响应其他脚本的功能调用请求:
- 修改
utility脚本,添加消息监听逻辑:
// ==UserScript== // @name utility // @namespace http://sjngm/ // @grant GM_addValueChangeListener // @grant GM_setValue // ==/UserScript== const Utility = { func: () => { return "工具函数执行结果"; } }; // 监听调用请求 GM_addValueChangeListener("utilityCall", (key, oldVal, newVal, remote) => { if (remote && newVal) { const { funcName, callbackKey } = newVal; const result = Utility[funcName](); // 通过回调键返回结果 GM_setValue(callbackKey, result); } });
- 在
site A脚本中发送请求并接收结果:
// ==UserScript== // @name site A // @namespace http://sjngm/ // @match http*://site-a.com/* // @grant GM_setValue // @grant GM_addValueChangeListener // ==/UserScript== (function() { 'use strict'; // 生成唯一回调标识 const callbackKey = `utilityCallback_${Date.now()}`; // 监听结果返回 GM_addValueChangeListener(callbackKey, (key, oldVal, newVal) => { if (newVal) { console.log("工具函数返回结果:", newVal); // 清理监听与存储 GM_removeValueChangeListener(callbackKey); GM_deleteValue(callbackKey); } }); // 发送调用请求 GM_setValue("utilityCall", { funcName: "func", callbackKey: callbackKey }); })();
- 这种方式完全在Tampermonkey内部实现,无需外部文件,但逻辑相对复杂。
内容的提问来源于stack exchange,提问作者sjngm
相关产品推荐
相关产品推荐

