Clash Verge Rev 扩展脚本(Script)教程:用 JavaScript 修改订阅
Clash 中文网编辑部 · 更新于 2026/10/22 · 对照版本 Clash Verge Rev v2.5.8
扩展脚本是一段 JavaScript,Clash Verge Rev 会调用其中的 main(config, profileName) 函数,把订阅配置作为对象传进来,你修改后 return 回去即可。 它比 Merge 更灵活,可以追加、过滤、按条件批量处理。打开方式:
- 右键订阅卡片 →「扩展脚本」:只对该订阅生效;
- 订阅页顶部「全局扩展脚本」:对所有订阅生效。
脚本结构
新建的脚本默认内容如下:
// Define main function (script entry)
function main(config, profileName) {
return config;
}
| 部分 | 说明 |
|---|---|
main |
入口函数,名字不能改 |
config |
当前配置对象,结构与 YAML 一一对应 |
profileName |
当前订阅的名称 |
return config |
必须返回一个配置对象 |
config 对象长什么样
YAML 配置会被转换成 JavaScript 对象。例如:
proxies:
- name: 香港01
type: ss
proxy-groups:
- name: 节点选择
type: select
proxies: [香港01]
rules:
- MATCH,节点选择
在脚本中对应:
| YAML | JavaScript |
|---|---|
proxies |
config.proxies(数组,每项是对象) |
proxy-groups |
config["proxy-groups"](名字带横线,要用方括号) |
rules |
config.rules(字符串数组) |
dns.nameserver |
config.dns.nameserver |
带横线的字段名(
proxy-groups、rule-providers、proxy-providers)必须用config["proxy-groups"]方括号写法。
执行顺序
订阅原文 → 全局扩展配置 → 全局扩展脚本 → 订阅扩展配置 → 订阅扩展脚本 → 交给内核
订阅扩展脚本是“应用设置回写前的最后一个扩展步骤”,可以修改前面所有步骤的结果。
常用示例
1. 在最前面追加规则
function main(config) {
const myRules = [
"DOMAIN-SUFFIX,openai.com,节点选择",
"DOMAIN-SUFFIX,anthropic.com,节点选择",
"DOMAIN-SUFFIX,corp.example.com,DIRECT",
"PROCESS-NAME,qbittorrent.exe,DIRECT",
];
config.rules = [...myRules, ...(config.rules || [])];
return config;
}
把 节点选择 换成你的订阅中实际存在的代理组名称。用 ... 展开符把自定义规则放在前面,订阅原有规则放在后面。
2. 删除名称含“过期”“剩余”的信息节点
function main(config) {
const bad = /过期|剩余|官网|到期|流量|重置/;
const removed = new Set();
config.proxies = (config.proxies || []).filter((p) => {
if (bad.test(p.name)) {
removed.add(p.name);
return false;
}
return true;
});
// 同时从所有代理组中移除这些节点
for (const g of config["proxy-groups"] || []) {
if (Array.isArray(g.proxies)) {
g.proxies = g.proxies.filter((n) => !removed.has(n));
}
}
return config;
}
注意:删除节点后必须同时从代理组中移除,否则内核会报“找不到节点”的错误。
3. 按地区新建自动选择代理组
function main(config) {
const regions = [
{ name: "香港自动", re: /港|HK|Hong Kong/i },
{ name: "日本自动", re: /日本|JP|Japan/i },
{ name: "美国自动", re: /美国|US|United States/i },
];
const names = (config.proxies || []).map((p) => p.name);
const newGroups = [];
for (const r of regions) {
const list = names.filter((n) => r.re.test(n));
if (list.length) {
newGroups.push({
name: r.name,
type: "url-test",
proxies: list,
url: "https://www.gstatic.com/generate_204",
interval: 300,
tolerance: 50,
});
}
}
config["proxy-groups"].push(...newGroups);
// 把新组加入第一个手动选择组,方便在代理页选择
const selector = config["proxy-groups"].find((g) => g.type === "select");
if (selector) selector.proxies.unshift(...newGroups.map((g) => g.name));
return config;
}
4. 节点重命名(加上国旗)
function main(config) {
const flags = [
[/港|HK/i, "🇭🇰"],
[/日本|JP/i, "🇯🇵"],
[/美国|US/i, "🇺🇸"],
[/新加坡|SG/i, "🇸🇬"],
];
const rename = new Map();
for (const p of config.proxies || []) {
const hit = flags.find(([re]) => re.test(p.name));
if (hit && !p.name.startsWith(hit[1])) {
const newName = `${hit[1]} ${p.name}`;
rename.set(p.name, newName);
p.name = newName;
}
}
// 同步更新代理组中的引用
for (const g of config["proxy-groups"] || []) {
if (Array.isArray(g.proxies)) g.proxies = g.proxies.map((n) => rename.get(n) || n);
}
return config;
}
改名后同样必须更新代理组中的引用。
5. 修改 DNS 与嗅探
function main(config) {
config.dns = {
...config.dns,
enable: true,
"enhanced-mode": "fake-ip",
nameserver: ["https://dns.alidns.com/dns-query", "https://doh.pub/dns-query"],
};
config.sniffer = {
enable: true,
sniff: {
HTTP: { ports: [80, "8080-8880"], "override-destination": true },
TLS: { ports: [443, 8443] },
QUIC: { ports: [443, 8443] },
},
};
return config;
}
6. 只对某个订阅生效(写在全局脚本中)
function main(config, profileName) {
if (profileName !== "我的机场") return config;
// ……只对名为“我的机场”的订阅执行的修改
return config;
}
profileName 就是订阅卡片上显示的名称。
7. 为所有订阅统一添加 AI 专用组和规则
function main(config) {
const groups = config["proxy-groups"] || [];
const selector = groups.find((g) => g.type === "select");
if (!selector) return config;
groups.unshift({
name: "AI 服务",
type: "select",
proxies: [selector.name, ...(config.proxies || []).map((p) => p.name).filter((n) => /美国|US/i.test(n))],
});
config.rules = ["GEOSITE,openai,AI 服务", "GEOSITE,anthropic,AI 服务", ...(config.rules || [])];
return config;
}
把它放进全局扩展脚本,无论切换到哪个订阅都会自动拥有“AI 服务”组。
调试脚本
使用 console.log
function main(config) {
console.log("节点数量:", (config.proxies || []).length);
console.log("代理组:", (config["proxy-groups"] || []).map((g) => g.name));
return config;
}
保存后,在编辑器的「脚本控制台输出」中查看打印的内容和错误信息。
查看最终结果
保存后点击订阅页「查看运行时订阅」,确认修改是否符合预期。
常见错误
| 错误 | 原因 |
|---|---|
Cannot read properties of undefined |
访问了不存在的字段,加 ` |
| 代理组引用了不存在的节点 | 删除或重命名节点后没有同步更新代理组 |
| 脚本没有效果 | 忘记 return config,或 main 函数名写错 |
| 端口等设置没变 | 这些字段由应用设置接管,脚本修改无效 |
脚本写坏了怎么恢复
把内容改回默认模板:
function main(config, profileName) {
return config;
}
保存即可恢复原样。如果开启了「关键变更时自动备份」,也可以从 备份 中恢复全局脚本。
注意事项
- 脚本运行在受限的 JavaScript 环境中,不能访问网络、文件;
- 由应用设置接管的字段(端口、
allow-lan、mode、log-level、ipv6、external-controller、secret、unified-delay)在脚本里修改不会生效; - 脚本每次激活订阅时都会运行,避免写非常耗时的逻辑。
相关教程
常见问题
脚本报错导致订阅加载失败怎么办?
打开扩展脚本编辑器查看「脚本控制台输出」中的错误信息;最简单的恢复办法是把脚本改回只有 return config 的初始模板。
扩展脚本和扩展覆写配置该用哪个?
只是覆盖几个字段用 Merge 更简单;需要追加、过滤、按条件批量处理时用脚本。
脚本里能联网请求吗?
不能。脚本运行在受限的 JavaScript 环境中,只能处理传入的配置对象,不能访问网络或文件。
需要会编程才能用吗?
照抄本文示例并修改其中的名称即可满足大多数需求。理解基本的 JavaScript 数组和对象操作会更得心应手。
还没安装 Clash Verge Rev?
最新版 v2.5.8,直链 GitHub 官方安装包。