当前位置: 首页 > news >正文

Tampermonkey 5.1.0 离线安装包:免联网拖拽即用,含完整脚本管理功能

本文还有配套的精品资源,点击获取

简介:解压后打开 Chrome 扩展程序页面,开启开发者模式,直接拖入 manifest. 或整个文件夹就能装好,全程不依赖网络。内置编辑器(editor.html/js)、后台服务(background.html/js)、内容注入逻辑(content.js)、权限控制模块(extension.js)、缓存支持(cache.js)和语法检查(lint.js),支持脚本启停、定时运行、跨域请求、本地存储。配套选项页(options.html)、权限确认页(ask.html)、操作面板(action.html)、脚本详情页(userscript.html)和多尺寸图标(16px–128px),适配 Chrome 90+。通过 computed_hashes. 和 verified_contents. 校验脚本完整性,LICENSE 文件注明开源协议,确保安全可信。
我用 Tampermonkey 已经八年多了,从 Chrome 45 时代就开始折腾用户脚本——最早还得手动改 manifest.json 兼容新版 API,后来干脆自己编译过三个不同分支的离线版。这次整理的Tampermonkey 5.1.0 离线安装包,不是简单打包官网源码,而是基于上游 v5.1.0 tag 源码树,剔除所有网络依赖路径(比如自动更新检查、CDN 加载的 Monaco 编辑器、远程脚本仓库索引)、重写本地资源引用逻辑、补全缺失的构建产物,并通过完整功能回归测试验证。它真正做到了“解压即用”:不连外网、不调远程接口、不发任何 telemetry、不依赖 chrome.webstore 或任何在线服务。你拿到手的是一个完全自洽、可审计、可复现的扩展运行时环境。关键词里提到的“Tampermonkey离线版”“Chrome脚本管理器”“用户脚本插件”,其实背后是一整套浏览器沙箱内脚本生命周期管理机制——而这个包,就是这套机制最干净、最可控的落地形态。它适合三类人:一是企业内网/教育机房等完全断网环境下的技术老师和学生;二是对隐私极度敏感、拒绝一切后台通信的资深用户;三是前端开发者想快速搭建本地脚本调试沙箱,绕过线上审核周期。下面我会像带徒弟一样,把整个包的设计逻辑、每个文件的真实作用、安装时容易踩的坑、以及怎么把它变成你日常开发中最顺手的工具,掰开揉碎讲清楚。

1. 整体设计思路与架构拆解

1.1 为什么必须做“真离线”?——从 Chrome 扩展机制说起

很多人以为“拖进扩展页就能装”就等于离线,其实大错特错。原版 Tampermonkey 在安装后首次启动时,会强制加载https://cdn.jsdelivr.net/npm/monaco-editor@0.34.1/min/vs/loader.js初始化编辑器,还会向https://update.tmdb.org/发起版本检查请求,甚至在打开选项页时尝试拉取https://tampermonkey.net/faq.php的帮助文档。这些行为在断网环境下直接导致:编辑器白屏、选项页卡死、脚本列表加载失败、定时任务无法注册。这不是 Bug,是设计使然——官方默认假设你有网络。

我们做的第一件事,就是把所有https?://开头的硬编码 URL 全部替换为chrome-extension://__MSG_@@extension_id__/协议的本地路径。比如原版editor.js中这行:

require.config({ paths: { 'vs': 'https://cdn.jsdelivr.net/npm/monaco-editor@0.34.1/min/vs' } });

被我们替换成:

const extId = chrome.runtime.id; require.config({ paths: { 'vs': `${location.protocol}//${location.host}/${extId}/monaco/min/vs` } });

然后我们在根目录下新增monaco/文件夹,放入预构建的 Monaco Editor 0.34.1 最小化版本(仅保留 editor、language、worker 三个核心模块,体积从 8.2MB 压到 1.7MB),并确保其loader.js能正确解析相对路径。这不是简单复制粘贴,而是要重写monaco-editor的 AMD 加载器入口,让它识别chrome-extension://协议——因为 Chrome 扩展的资源协议不支持跨域fetch(),但支持XMLHttpRequest同源读取,而 Monaco 默认用fetch,我们必须打补丁让它 fallback 到 XHR。

提示:如果你打开editor.html后看到控制台报Failed to load resource: net::ERR_FAILED且路径是vs/editor/editor.main.nls.js,说明 Monaco 资源路径没对齐。真实原因往往是manifest.json里的"web_accessible_resources"没包含monaco/**,或者editor.js里写的路径多了一层../

1.2 功能模块如何解耦又协同?——一张图看懂五个核心进程

Tampermonkey 不是一个单页应用,它由五个独立 HTML 页面构成,各自运行在 Chrome 的不同上下文中,靠chrome.runtime.sendMessagechrome.storage通信。这个设计决定了它的稳定性和安全性边界:

页面名运行上下文核心职责离线改造重点
background.html后台页(常驻)管理脚本生命周期、触发定时任务、处理跨域请求代理、监听页面导航移除所有fetch('https://...'),将chrome.identity.getAuthToken替换为本地 token 生成器(用于模拟 OAuth 流程)
content.js注入到每个网页的 Content Script执行用户脚本、劫持XMLHttpRequest/fetch实现跨域、注入unsafeWindow重写crossOrigin请求逻辑,改为通过chrome.runtime.sendMessage转发至 background,由 background 用chrome.cookies+chrome.webRequest模拟带凭证的跨域请求
editor.html弹出页(点击图标打开)提供代码编辑、语法高亮、实时校验、保存/运行/调试内置monaco-editor离线版 +eslint规则包(压缩后 412KB),校验逻辑完全在本地执行,不连 eslint.org
options.html选项页(右键图标→选项)配置全局参数、管理脚本元数据、设置黑白名单移除“同步到云”按钮及所有相关 JS 逻辑,将“备份/还原”功能绑定到chrome.storage.local,导出为.tmbackupJSON 文件
action.html操作面板(地址栏右侧图标弹窗)快速启停当前页脚本、查看匹配状态、跳转编辑重写getMatchedScripts()方法,避免调用chrome.tabs.query({active: true})后再发消息给 content script,改为直接读取chrome.storage.session中缓存的匹配结果

这五个页面就像一支特种部队:background 是指挥中心,content 是前线侦察兵,editor 是武器工坊,options 是作战室,action 是单兵通讯器。它们之间不共享内存,只靠消息传递——这既是安全隔离的保障,也是离线化的基础。只要消息通道畅通(chrome.runtimeAPI 完全离线可用),整个系统就能运转。

1.3 安全机制不是摆设:verified_contents.json 和 computed_hashes.json 怎么工作?

很多用户以为“开源协议+离线”就等于安全,其实不然。Tampermonkey 的核心风险在于:它允许执行任意 JavaScript,而脚本来源不可控。verified_contents.jsoncomputed_hashes.json就是两道保险栓。

  • computed_hashes.json是构建时生成的“指纹库”。它记录了所有内置脚本(如@require加载的 jQuery、lodash)和 Tampermonkey 自身核心模块(content.js,background.js)的 SHA256 哈希值。格式如下:
{ "content.js": "a1b2c3d4e5f67890...", "background.js": "f0e1d2c3b4a56789...", "lib/jquery.min.js": "9876543210fedcba..." }
  • verified_contents.json是运行时校验表。当用户首次启用某个脚本时,Tampermonkey 会计算该脚本文件的哈希,然后查表确认是否在computed_hashes.json中登记过。如果没登记,就弹出警告:“此脚本未通过完整性校验,是否仍要运行?”——这就是ask.html的作用。

关键点在于:这两个文件必须在构建阶段一次性生成,且不能被运行时修改。我们在build.sh脚本中加入强制校验:

# 构建后自动计算所有 JS/CSS 文件哈希 find . -name "*.js" -o -name "*.css" | while read f; do hash=$(sha256sum "$f" | cut -d' ' -f1) echo " \"$(basename "$f")\": \"$hash\"," >> computed_hashes.json.tmp done # 合并去重,写入最终文件

注意:如果你手动修改了content.js但忘了重新生成computed_hashes.json,启动时 background 会报错Hash mismatch for content.js并拒绝加载——这是故意设计的熔断机制,宁可停摆也不执行被篡改的代码。

2. 核心文件功能详解与实操要点

2.1 manifest.json:离线化的总开关,每一行都不能错

manifest.json是 Chrome 扩展的宪法,它决定了什么能做、什么不能做、资源怎么加载。这个离线包的manifest.json经过 17 处关键修改,远不止加个"offline_enabled": true。我们逐条拆解:

{ "manifest_version": 3, "name": "Tampermonkey Offline", "version": "5.1.0", "description": "Offline-ready userscript manager for Chrome 90+", "permissions": ["storage", "scripting", "cookies", "webRequest", "webRequestBlocking"], "host_permissions": ["<all_urls>"], "content_scripts": [{ "matches": ["<all_urls>"], "js": ["content.js"], "run_at": "document_start", "all_frames": true, "match_about_blank": true }], "background": { "service_worker": "background.js" }, "web_accessible_resources": [{ "resources": [ "editor.html", "editor.css", "style.css", "monaco/**", "lib/**", "images/**" ], "matches": ["<all_urls>"] }], "icons": { "16": "icon16.png", "32": "icon32.png", "48": "icon48.png", "128": "icon128.png" } }
  • "manifest_version": 3是硬性要求。MV3 强制使用 Service Worker 替代 Background Page,而原版 Tampermonkey 5.1.0 是 MV2。我们做了完整迁移:把background.html改造成background.js,所有chrome.extension.onMessage改为chrome.runtime.onMessagelocalStorage改为chrome.storage.local。这不是语法替换,而是重构——因为 Service Worker 无 DOM、无window对象、有严格的事件驱动生命周期。

  • "permissions"里删掉了"https://*/*"这类宽泛权限,只保留必要最小集。特别注意"scripting"权限:它是 MV3 中替代executeScript的新 API,允许动态注入脚本,但必须显式声明目标 URL。我们在background.js中这样用:

// 注入用户脚本到指定 tab await chrome.scripting.executeScript({ target: { tabId: tab.id }, files: ['content.js'], world: 'MAIN' // 确保注入到页面主世界,而非隔离世界 });
  • "web_accessible_resources"是离线成败的关键。很多用户拖进去后 editor 白屏,90% 是因为这里漏写了monaco/**。Chrome 对web_accessible_resources的路径匹配是精确前缀匹配,"monaco/**"表示允许monaco/下所有子路径被其他页面访问,但"monaco"(不带/**)只允许访问monaco文件本身(不存在)。我们还额外加了"lib/**"(存放 jQuery/lodash 等 require 库)和"images/**"(存放图标资源),确保@require@resource能正常加载本地文件。

  • "icons"字段必须包含 16x16 到 128x128 全尺寸。Chrome 会根据上下文自动选择:地址栏用 16px,任务管理器用 32px,扩展页用 48px,系统设置用 128px。少任何一个,对应场景就会显示默认灰色图标。我们提供的icon16.png是从icon128.png严格等比缩放+双三次插值生成,不是简单压缩,避免模糊。

2.2 content.js:用户脚本的“执行引擎”,跨域和 unsafeWindow 的真相

content.js是整个包里最精妙也最危险的文件。它不是直接执行用户脚本,而是作为一个“沙箱注入器”,负责:

  1. 监听chrome.runtime.onMessage,接收 background 发来的脚本代码和执行参数;
  2. 创建<script>标签注入页面,但关键是要绕过 CSP(内容安全策略)限制;
  3. 实现GM_xmlhttpRequest跨域请求;
  4. 构造unsafeWindow并修补Object.prototype防止污染。

来看一段真实注入逻辑:

// content.js 片段:安全注入用户脚本 function injectScript(code, url) { // 步骤1:创建 script 标签 const script = document.createElement('script'); script.textContent = code; // 步骤2:绕过 CSP —— 关键!不能用 innerHTML,必须用 textContent // 因为 innerHTML 会触发 CSP 的 'unsafe-inline' 检查,而 textContent 不会 script.setAttribute('type', 'text/javascript'); // 步骤3:插入到 head,确保在页面 JS 执行前运行 (document.head || document.documentElement).appendChild(script); // 步骤4:清理,避免内存泄漏 script.remove(); }

跨域请求的实现更复杂。原版用fetch(),但我们改成通过chrome.runtime.sendMessage转发到 background,由 background 调用chrome.webRequestAPI 发起真实请求(它不受 CSP 限制):

// content.js 中的 GM_xmlhttpRequest 代理 chrome.runtime.onMessage.addListener((req, sender, sendResp) => { if (req.action === 'crossOriginRequest') { // 转发给 background 处理 chrome.runtime.sendMessage({ action: 'doCrossOriginRequest', url: req.url, method: req.method, headers: req.headers, data: req.data }, resp => sendResp(resp)); return true; // 保持消息通道开启 } });

实操心得:如果你发现某个脚本的GM_xmlhttpRequest返回 403,先检查manifest.json是否声明了"webRequest""webRequestBlocking"权限;再检查background.js中是否有对应的chrome.webRequest.onBeforeSendHeaders监听器;最后确认请求头里是否包含了Origin字段——有些网站会校验 Origin,而 background 发起的请求 Origin 是chrome-extension://xxx,需要手动覆盖。

2.3 editor.html/js:不只是编辑器,更是脚本 IDE

editor.html看似只是一个 textarea,但它集成了完整的开发体验:

  • 语法高亮与错误提示:基于 Monaco 的javascript语言服务,支持 ES2022 语法、JSDoc 提示、变量跳转;
  • 实时校验(lint.js):集成 ESLint 8.22.0,规则配置在eslint-config-tampermonkey.js中,禁用所有网络相关规则(no-restricted-globals,no-unused-vars保留),添加tampermonkey/gm-api自定义规则(检查GM_setValue是否传入字符串 key);
  • 快捷操作:Ctrl+S 保存到chrome.storage.local,Ctrl+Enter 运行当前脚本,F5 刷新当前页并重载脚本;
  • @require/@resource 智能补全:输入@require后按 Ctrl+Space,自动列出lib/下所有 JS 库(jQuery、lodash、moment 等),选中后自动插入完整路径。

editor.js的核心是 Monaco 的monaco.editor.create()调用,但我们做了三处关键增强:

  1. 离线字体加载:Monaco 默认从 Google Fonts 加载Cascadia Code,我们改为本地fonts/cascadia.woff2,并在 CSS 中用@font-face声明;
  2. 主题适配:内置vs-darkhc-black两种主题,通过chrome.storage.sync.get('theme')读取用户偏好,避免每次打开都重绘;
  3. 大文件优化:当脚本超过 500 行时,自动启用lazyModel模式,只加载可视区域代码,防止卡顿。

注意事项:Monaco 编辑器初始化耗时约 300ms,如果用户在editor.html打开瞬间就狂按 Ctrl+S,可能触发Cannot set property 'value' of null错误。我们的解决方案是在editor.js中加锁:

let isEditorReady = false; monaco.editor.defineTheme('myTheme', { ... }); monaco.editor.create(document.getElementById('container'), { ... }); isEditorReady = true; // 保存函数加锁 function saveScript() { if (!isEditorReady) return; // 执行保存逻辑 }

3. 完整安装与配置流程实录

3.1 从解压到可用:五步走通全流程(附每步截图要点)

我用一台全新安装的 Chrome 118(Win11)全程录屏,以下是真实操作步骤,没有跳步:

步骤 1:解压到纯英文路径
- 下载Tampermonkey-5.1.0-offline.zip,右键→“全部解压缩…”;
-关键:解压路径必须是纯英文、无空格、无中文,例如C:\tm-offline\。如果解压到D:\我的软件\Tampermonkey\,Chrome 会报错Failed to load extension,因为路径中的\u6211\u7684Unicode 字符被转义失败;
- 解压后检查根目录应有 28 个文件,包括manifest.json,background.js,editor.html,icon128.png等,缺一不可。

步骤 2:打开 Chrome 扩展程序页
- 地址栏输入chrome://extensions/回车;
- 右上角开启“开发者模式”开关(蓝色变亮);
- 此时页面左上角会出现“加载已解压的扩展程序”按钮。

步骤 3:拖拽安装(两种方式任选)
-方式 A(推荐):拖拽整个文件夹
直接将C:\tm-offline\文件夹拖到chrome://extensions/页面空白处 → 松开鼠标 → 出现绿色“已加载”提示框 → 点击“确定”。
-方式 B:拖拽 manifest.json
找到C:\tm-offline\manifest.json,拖入页面 → 出现黄色“加载失败”提示 →不要点确定,而是点击提示框右下角的“详细信息”,查看错误日志:Could not load manifest. Permission 'scripting' is unknown.
这是因为你用的是 Chrome 88 以下版本。此时必须升级 Chrome 或改用方式 A。

实测对比:方式 A 成功率 100%,方式 B 在 Chrome 90+ 也偶发失败(Chrome 的 manifest 解析器对拖拽单文件有竞态 bug)。所以永远优先拖文件夹。

步骤 4:验证安装成功
- 地址栏右侧出现 Tampermonkey 图标(橙色猴子头);
- 右键图标→“选项”,打开options.html,能看到“常规”“高级”“关于”三个标签页,且“关于”页显示版本号5.1.0-offline
- 点击图标→弹出action.html,显示“无匹配脚本”或已安装脚本列表;
- 按 Ctrl+Shift+I 打开 DevTools,切换到 Console,输入typeof GM_info,返回"object"即表示content.js注入成功。

步骤 5:首次运行脚本(Hello World 测试)
- 点击图标→“创建新脚本”;
- 编辑器自动打开,顶部显示// ==UserScript==头部;
- 在// @grant none下一行添加alert('Hello from offline Tampermonkey!');
- Ctrl+S 保存;
- 打开任意网页(如https://example.com),脚本自动运行,弹出 alert;
- 如果没弹出,按 F12 打开 DevTools→Console,看是否有Refused to execute inline script报错——有则说明 CSP 阻止了注入,需检查content.js是否正确使用textContent

3.2 高级配置:让离线版真正好用的六个技巧

光能装上还不够,要让它成为生产力工具,还得调教:

技巧 1:启用定时任务(cron)
- 默认background.jscron功能是关闭的,因为需要chrome.alarms权限且耗电;
- 打开options.html→“高级”→勾选“启用定时任务”;
- 在脚本头部添加:
js // @run-at document-idle // @cron 0 */2 * * * // 每两小时执行一次
- 实测:在断网状态下,chrome.alarms.onAlarm依然精准触发,误差 < 100ms。

技巧 2:本地存储加速(cache.js)
-cache.js实现了 LRU 缓存,key 是 URL,value 是响应体;
- 在脚本中这样用:
js GM_xmlhttpRequest({ url: 'https://api.example.com/data.json', cache: true, // 关键!开启缓存 onload: res => console.log(res.responseText) });
- 缓存有效期 24 小时,存储在chrome.storage.local,最大容量 5MB。

技巧 3:跨域请求代理(extension.js)
-extension.js是权限控制中枢,它拦截所有chrome.webRequest请求;
- 在options.html→“高级”→“跨域请求代理”中开启;
- 脚本中GM_xmlhttpRequest会自动走代理,无需改代码。

技巧 4:语法校验开关(lint.js)
-lint.js默认开启,但大型脚本(>1000 行)校验会卡顿;
- 在editor.html右上角齿轮图标→取消勾选“启用 ESLint 校验”;
- 或在脚本头部加// @lint false关闭单个脚本校验。

技巧 5:图标状态自定义
-icon_blocker32.png等图标不是装饰,而是状态指示器;
-icon_blocker32.png表示“当前页所有脚本被禁用”,icon_paused32.png表示“仅禁用定时任务”;
- 修改background.js中的updateIcon()函数,可自定义状态逻辑。

技巧 6:备份与迁移
- 打开options.html→“常规”→“备份/还原”;
- 点击“导出备份”,生成tampermonkey-backup-20240520.tmbackup文件;
- 在另一台电脑上,解压离线包→安装→打开options.html→“导入备份”→选择文件;
- 所有脚本、设置、缓存全部迁移,无需联网。

4. 常见问题与排查技巧实录

4.1 安装阶段高频问题速查表

现象可能原因排查命令/操作解决方案
拖拽后无反应,页面刷新解压路径含中文或空格在文件资源管理器地址栏输入cmd回车,执行cd /d C:\tm-offline && dir,看是否报错重解压到纯英文路径,如C:\tm
加载失败:Permission 'scripting' is unknownChrome 版本 < 90地址栏输入chrome://version/查看版本升级 Chrome 至 90+,或改用拖文件夹方式
图标显示灰色方块manifest.jsonicons字段缺失某尺寸打开chrome://extensions/→点击“详情”→“背景页”→Console,看是否有Failed to load icon检查icon16.png,icon32.png等是否存在,用 PS 重新导出 PNG-24
editor.html白屏web_accessible_resources未包含monaco/**editor.html控制台输入fetch('monaco/min/vs/loader.js').then(r=>r.text()).catch(e=>console.error(e))编辑manifest.json,在web_accessible_resources中添加"monaco/**"
选项页打不开options.html路径未在manifest.json中声明查看manifest.json"options_page"字段是否为"options.html"MV3 不支持options_page,必须用"options_ui",但我们已兼容:"options_ui": {"page": "options.html", "open_in_tab": true}

4.2 运行阶段典型故障与根因分析

故障 1:脚本能保存但不执行,Console 报GM_info is not defined

  • 根因content.js未成功注入到页面。常见于:
  • 网站启用了严格的 CSP,禁止eval()和内联脚本;
  • 用户在options.html中误关了“启用内容脚本”;
  • manifest.jsoncontent_scripts.matches没覆盖当前网址。

  • 排查
    1. 打开options.html→“常规”→确认“启用内容脚本”已勾选;
    2. 在目标网页按 F12→Application→Manifest,确认content_scriptsmatches包含当前 URL;
    3. 在 Console 输入chrome.runtime.sendMessage({action:'ping'}, r=>console.log(r)),如果返回undefined,说明content.js根本没加载。

  • 解决:在background.js中强制注入:
    js chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { if (changeInfo.status === 'complete' && tab.url.startsWith('http')) { chrome.scripting.executeScript({ target: { tabId }, func: () => console.log('content.js injected'), }); } });

故障 2:GM_xmlhttpRequest返回status: 0,无 responseText

  • 根因:跨域请求被chrome.webRequest拦截器阻止,或 background 的onBeforeSendHeaders没正确返回requestHeaders

  • 排查
    1. 在background.jschrome.webRequest.onBeforeSendHeaders监听器中加console.log('headers:', details.requestHeaders)
    2. 在目标网页 Console 输入GM_xmlhttpRequest({url:'https://httpbin.org/get'}),看 background 控制台是否打印;
    3. 如果没打印,说明host_permissions没声明<all_urls>

  • 解决:确保manifest.json"host_permissions": ["<all_urls>"],且background.js中监听器返回details
    js chrome.webRequest.onBeforeSendHeaders.addListener( (details) => { console.log('Sending request to:', details.url); return { requestHeaders: details.requestHeaders }; }, { urls: ["<all_urls>"] }, ["blocking", "requestHeaders"] );

故障 3:编辑器语法高亮失效,全是白色文字

  • 根因:Monaco 的vs/basic-languages语言包未加载,或monaco-editor版本与editor.js不匹配。

  • 排查
    1. 在editor.html控制台输入monaco.languages.getLanguages(),看是否返回空数组;
    2. 查看 Network 面板,过滤monaco,确认vs/basic-languages/javascript/javascript.js是否 200。

  • 解决:检查monaco/目录结构,必须是:
    monaco/ ├── min/ │ ├── vs/ │ │ ├── loader.js │ │ └── basic-languages/ │ │ └── javascript/ │ │ └── javascript.js

4.3 我踩过的三个深坑与独家避坑指南

坑 1:chrome.storage.local在 MV3 Service Worker 中的异步陷阱

  • 现象:在background.jschrome.storage.local.set({key: 'val'})后立即chrome.storage.local.get(['key']),返回undefined
  • 真相:Service Worker 的chrome.storageAPI 是纯异步的,且没有回调地狱保护。setget不是原子操作,中间可能被其他事件打断。
  • 避坑:永远用async/await包裹:
    js async function saveAndLoad() { await chrome.storage.local.set({ key: 'val' }); const res = await chrome.storage.local.get(['key']); console.log(res.key); // 'val' }

坑 2:@require本地库的路径黑洞

  • 现象:脚本中写// @require lib/jquery.min.js,但运行时报jQuery is not defined
  • 真相@require的路径是相对于manifest.json的,不是相对于脚本文件。如果jquery.min.jsC:\tm-offline\lib\,那@require必须写lib/jquery.min.js,不能写./lib/jquery.min.js
  • 避坑:统一用绝对路径风格,在options.html→“高级”→“@require 路径前缀”中填lib/,这样所有脚本只需写// @require jquery.min.js

坑 3:图标状态与脚本启停不同步

  • 现象:在action.html点击“禁用”,图标变成灰色,但脚本仍在运行。
  • 真相action.html只修改了chrome.storage.local中的启用状态,但content.js没监听状态变更事件,还是按旧状态执行。
  • 避坑:在content.js开头加监听:
    js chrome.storage.local.get('disabledScripts', (res) => { const disabled = res.disabledScripts || []; if (disabled.includes(scriptId)) { return; // 跳过执行 } }); chrome.storage.local.onChanged.addListener((changes) => { if (changes.disabledScripts) { location.reload(); // 强制重载,重新注入 } });

这个 Tampermonkey 离线包,我从去年十月开始维护,每周都在真实内网环境(某三甲医院信息科)跑压力测试:同时启用 87 个脚本,每分钟触发 3 个定时任务,持续 72 小时不崩溃。它不是玩具,而是一个经过生产环境淬炼的工具。最后分享一个小技巧:如果你要做二次开发,别碰editor.html的 UI,直接改editor.js里的monaco.editor.create()参数——比如把fontSize: 14改成16,立刻全局生效。真正的掌控感,从来不在表面,而在那些被精心设计的接口深处。

本文还有配套的精品资源,点击获取

简介:解压后打开 Chrome 扩展程序页面,开启开发者模式,直接拖入 manifest. 或整个文件夹就能装好,全程不依赖网络。内置编辑器(editor.html/js)、后台服务(background.html/js)、内容注入逻辑(content.js)、权限控制模块(extension.js)、缓存支持(cache.js)和语法检查(lint.js),支持脚本启停、定时运行、跨域请求、本地存储。配套选项页(options.html)、权限确认页(ask.html)、操作面板(action.html)、脚本详情页(userscript.html)和多尺寸图标(16px–128px),适配 Chrome 90+。通过 computed_hashes. 和 verified_contents. 校验脚本完整性,LICENSE 文件注明开源协议,确保安全可信。


本文还有配套的精品资源,点击获取

http://www.jsqmd.com/news/941666/

相关文章:

  • 前端工程化命题,覆盖性能/架构/交互
  • Windows 10/11 C盘告急?用mklink命令把VSCode扩展文件夹挪到D盘,实测有效
  • 云原生生态解析:主流厂商与核心技术栈
  • 从实验室到街头:拥抱复杂性的研究范式变革与实战指南
  • 避坑指南:在Linux服务器上为个人项目安装CUDA 11.1,如何避免污染系统环境?
  • 搞定Xilinx CPRI IP核的时钟同步:从GT恢复时钟到外部PLL的保姆级配置指南
  • 告别SpeechRecognition!用阿里FunASR搞定会议录音转文字(附离线模型部署避坑指南)
  • Protobuf动态解析避坑指南:从Descriptor文件生成到DynamicMessage实战
  • UE5 SpatialLabs插件实战:如何解决摄像机外物体不显示这个“反常识”的立体成像问题?
  • 爆炸金属复合板厂家推荐:威海化机凭双工艺技术领跑高端防腐材料赛道 - 玖叁鹿
  • 别再凭感觉画线了!用这个在线工具5分钟搞定PCB电源线宽计算(附IPC-2152标准解读)
  • 全网最细java零基础学习就业课程教学之java基础篇3
  • 别再为ImageNet发愁了!3GB的Mini-ImageNet数据集保姆级处理教程(附Python脚本)
  • 钢材的机械性能浅析
  • Zotero插件市场:3步完成插件管理的终极指南
  • Python函数:局部变量与全局变量的作用域
  • 耐火浇注料供应商怎么选?2026年行业深度解析与优质厂家推荐 - 深度智识库
  • 资源等待与系统吞吐—— 从线程、连接到 TCP 带宽利用率
  • 别再堆技术了!高并发高可用下单系统,真正的架构精髓在这里
  • YOLOv8安装踩坑记:手动创建setup.py和requirements.txt的保姆级教程
  • 5个突破性技巧彻底改变你的OneNote笔记管理效率
  • 当AI学会了“理解“医院:医疗企业本体语义模型落地记
  • 揭秘Chromatic:5分钟掌握Chromium/V8应用的终极修改神器
  • Ubuntu 根分区文件系统损坏,系统启动时自动检查失败
  • ACE-Guard限制器:腾讯游戏性能优化终极指南
  • 洛阳市涧西区 清洁收纳上门|维小达 日常保洁、开荒保洁、窗户保洁、收纳整理、暖气清洗、家电清洗等一站式清洁收纳服务 - 维小达科技
  • STM32F103C8T6直接驱动SG90舵机的PWM控制工程(标准库版,含接线图与示例)
  • 除了禁用Domain Reload,Unity项目编译提速还有哪些靠谱选择?实测对比与避坑指南
  • 一张图搞懂 HarmonyOS SnapshotUtil:什么场景用哪个截图方法?
  • 保姆级教程:用CrewAI+Ollama在本地电脑搭建你的第一个多Agent协作项目(附避坑指南)