Tampermonkey油猴JavaScript脚本开发基础规范

作者:小括号

时间:2026-10-30

浏览:254

详细介绍Tampermonkey(油猴)JavaScript脚本开发的基础规范,涵盖元数据块配置、执行上下文与沙箱机制、DOM注入与生命周期管理、以及安全与发布标准。

文章目录

一、元数据块(UserScript Metadata)配置规范

Tampermonkey 脚本以特殊的注释块开头,即 // ==UserScript== 到 // ==/UserScript==。扩展核心解析器依靠该区域决定脚本的运行范围、加载时机、外部依赖与特权 API 权限。元数据声明不规范是导致脚本不生效或过度索权的常见根源。

1. 核心基础字段

  • @name:脚本的完整名称,应具备独立辨识度,避免与常用库名混淆。
  • @namespace:脚本作者标识或专属网址,用于与同名脚本做唯一区分,建议设置为个人 GitHub 主页或项目域名。
  • @version:严格遵循语义化版本格式(SemVer,如 1.0.0),以便扩展更新检测模块准确对比版本差异。
  • @description:简要说明脚本功能,控制在 100 字以内,清晰说明适用场景。
  • @author:脚本开发者署名。

2. 匹配规则(@match vs @include)

在指定脚本生效的网址时,必须优先使用 @match,避免使用宽松的 @include。@match 语法遵循严格的协议、域名和路径结构规范(如 *://*.example.com/*),能够规避正则误匹配带来的安全隐患。禁止使用 @match *://*/* 这种通配全网的宽松规则,除非脚本确实是通用型全局辅助工具。

3. 执行时机(@run-at)配置

@run-at 决定了脚本何时被注入到目标网页。常见选项包括:

  • document-start:页面刚发起请求,DOM 尚未构建,适合需要尽早拦截原生方法或注入预置对象的场景。此时访问 document.body 为 null。
  • document-body:<body> 标签已生成,但子节点可能尚未解析,适合提前注入全局容器或高优先级样式。
  • document-end(默认值):HTML 已解析完毕(相当于 DOMContentLoaded),但图片、样式等外部资源可能仍在下载,适合大部分常规 DOM 修改。
  • document-idle:浏览器空闲时或 window.onload 之后执行,适合低优先级或资源消耗较大的统计与分析操作。
// ==UserScript==
// @name         Sample Enhanced Script
// @namespace    https://github.com/developer-team
// @version      1.0.0
// @description  示范遵循标准规范的 Tampermonkey 用户脚本
// @author       Developer
// @match        https://example.com/*
// @match        https://*.example.com/items/*
// @run-at       document-end
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// ==/UserScript==
Tampermonkey油猴JavaScript脚本开发基础规范
图 1:Tampermonkey 脚本执行生命周期与 @run-at 各时机对应关系

二、执行上下文与沙箱机制规范

Tampermonkey 的执行环境与普通浏览器页面脚本存在根本差异。理解其沙箱边界是编写安全、稳定脚本的前提。

1. @grant 声明与沙箱级别

@grant 决定了脚本的权限上下文与沙箱类型:

  • @grant none:脚本直接运行在页面的主上下文(Page Context)中。此时脚本可以自由访问页面的全局变量和函数,但无法调用任何以 GM_ 开头的特权 API。如果脚本仅执行轻量级的 DOM 改动且无需扩展持久化存储,声明 @grant none 可以降低开销。
  • 声明具体 GM_* API:一旦显式声明了如 @grant GM_setValue,Tampermonkey 将为脚本创建独立的沙箱环境(Sandbox Context)。此时脚本的 window 是一个隔离对象,不会污染宿主页面,也不能直接读取宿主页面的闭包变量。

2. unsafeWindow 的使用规范与安全边界

在沙箱模式下,Tampermonkey 提供了 unsafeWindow 对象用于访问宿主页面的原始 window。由于宿主页面的 JavaScript 代码可能存在漏洞、恶意行为或原型链修改,因此直接使用 unsafeWindow 存在安全风险。

开发规范守则:遵循“只读优先、避免写入、隔绝执行”原则。如需读取宿主页面配置项(如 unsafeWindow.__INITIAL_STATE__),应进行深拷贝或仅读取基础类型;切勿将沙箱内部的特权函数挂载至 unsafeWindow,否则宿主页面脚本将能间接调用高权限的 GM API。

Tampermonkey油猴JavaScript脚本开发基础规范
图 2:Tampermonkey 执行上下文隔离与双向通信架构示意

三、DOM 注入与生命周期管理规范

在现代 Web 开发中,单页应用(SPA)高度普及,页面内容往往在初始 HTML 加载后通过异步数据动态渲染。如果使用固定的 setTimeout 进行延时等待,容易导致在网络较慢时元素获取失败,或在较快时产生不必要的等待感知。

1. 动态元素等待:杜绝固定延时,采用 MutationObserver

规范的做法是使用 MutationObserver 监听目标父级容器(或 document.body)的子节点变动,一旦目标元素出现立即执行回调,并及时断开(disconnect)监听器以释放内存:

/**
 * 安全等待指定选择器的 DOM 元素出现
 * @param {string} selector - CSS 选择器
 * @param {number} timeout - 超时时间(毫秒)
 * @returns {Promise<Element>}
 */
function waitForElement(selector, timeout = 10000) {
  return new Promise((resolve, reject) => {
    const el = document.querySelector(selector);
    if (el) return resolve(el);

    const timer = setTimeout(() => {
      observer.disconnect();
      reject(new Error(`等待元素超时: ${selector}`));
    }, timeout);

    const observer = new MutationObserver(() => {
      const target = document.querySelector(selector);
      if (target) {
        clearTimeout(timer);
        observer.disconnect();
        resolve(target);
      }
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true
    });
  });
}

2. 样式注入与命名空间隔离规范

为避免脚本样式与宿主页面既有样式发生冲突,必须遵守以下两项基本规则:

  • 类名命名空间前缀:所有自定义样式类名、ID 及自定义属性均应加上独特的前缀(如 tm-scriptname-button),严禁直接使用 .btn、.active、.box 等泛用类名。
  • 注入方式选择:如果声明了 @grant GM_addStyle,推荐直接调用 GM_addStyle(cssText),该方法具备更高的执行优先级并能正确处理 CSP 策略限制;在 @grant none 模式下,则通过创建 <style> 标签并追加至 document.head。
Tampermonkey油猴JavaScript脚本开发基础规范
图 3:现代单页应用(SPA)动态元素等待与安全注入流程图

四、数据持久化与跨域网络请求规范

油猴脚本通常需要保存用户配置(如快捷键设置、筛选规则)或请求外部服务接口。正确选择存储方式和网络通信层至关重要。

1. 存储机制对比:localStorage vs GM_setValue

  • localStorage:依附于当前站点的 Origin。如果目标网站包含多个二级域名(如 forum.example.com 与 i.example.com),两者无法直接互通;且宿主页面代码随时可以遍历和清空 localStorage,存在被恶意网页篡改配置的风险。
  • GM_setValue / GM_getValue:Tampermonkey 扩展底层提供的专有存储。数据独立保存在浏览器扩展的沙箱数据库中,具有跨子域共享、不受宿主页面清空影响、支持结构化对象自动序列化等优势。因此,脚本自身配置和跨页面状态应强制使用 GM_setValue 系列 API。

2. 跨域网络请求:GM_xmlhttpRequest 规范

浏览器标准的 fetch 和 XMLHttpRequest 受到同源策略和目标页面 CSP(Content Security Policy)的严格约束。当脚本需要跨域请求数据或发送无源请求时,需声明 @grant GM_xmlhttpRequest,并在元数据中配合 @connect 明确允许的域名白名单:

// ==UserScript==
// @grant        GM_xmlhttpRequest
// @connect      api.github.com
// @connect      raw.githubusercontent.com
// ==/UserScript==

GM_xmlhttpRequest({
  method: "GET",
  url: "https://api.github.com/repos/example/repo/releases/latest",
  headers: {
    "Accept": "application/json"
  },
  timeout: 5000,
  onload: function(response) {
    if (response.status === 200) {
      try {
        const data = JSON.parse(response.responseText);
        console.log("获取成功:", data.tag_name);
      } catch (e) {
        console.error("JSON 解析失败", e);
      }
    }
  },
  ontimeout: function() {
    console.warn("请求超时");
  },
  onerror: function(err) {
    console.error("网络请求异常", err);
  }
});

五、安全防护与发布规范总结

油猴脚本在用户浏览器中拥有较高的操作权限,尤其是使用 GM API 时。开发者必须强化防范意识,确保代码符合安全审计规范:

  1. 严禁随意使用 innerHTML:在将网络接口返回的数据或用户输入插入页面时,必须使用 textContent、createElement 或专用的安全 DOM 净化库,杜绝 DOM-based XSS 漏洞。
  2. 严格控制外部资源引用(@require / @resource):仅从权威、可靠的公共 CDN 引入第三方库;推荐在引入链接后补充 Subresource Integrity (SRI) 校验哈希,防止 CDN 被篡改后导致恶意代码执行。
  3. 代码封装采用 IIFE 或模块化严格模式:将脚本主体逻辑包裹在立即执行函数表达式(IIFE)或块级作用域中,开启 "use strict";,防止无意间声明泄漏到全局环境。
Tampermonkey油猴JavaScript脚本开发基础规范
图 4:Tampermonkey 脚本基础开发规范体系全景图

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章