Clash Verge Rev 扩展脚本不能跑怎么办?按入口、报错和配置覆盖排查
简答:导入脚本后没反应、运行报错或策略组变空时,先确认你使用的是 Clash Verge Rev 的“扩展脚本”入口,而不是 YAML“扩展配置”。粘贴最小的 main(config) 测试代码,先在扩展脚本编辑器或开发者控制台确认是否执行,再按报错、字段结构和应用设置覆盖逐层排查。本文只适用于 Clash Verge Rev,不适用于其他客户端的脚本机制。
定义:Clash Verge Rev 扩展脚本是运行在客户端内置 JavaScript 执行环境中的配置处理代码,通过 main(config) 接收并返回配置对象;它不同于 YAML 扩展配置,也不等同于内核脚本或其他客户端的模块脚本。
先试这一步:用最小脚本确认有没有执行
如果你遇到“脚本导入成功但没有变化”“策略组突然为空”或保存时直接报错,不要先改 DNS、TUN 或节点。先在 Clash Verge Rev 的配置卡片上右键,找到“编辑扩展/脚本”;不同版本的界面文案可能略有差异,以当前界面为准。官方文档说明,扩展脚本需要通过 main 函数接收配置对象,并返回修改后的配置。可先查看Clash Verge Rev 自定义脚本说明。
先把原脚本备份,再临时替换为下面的最小代码:
function main(config) { console.log("script-test"); return config; }
- 保存扩展脚本。
- 重新加载、更新或重新激活对应配置,让客户端重新生成配置。
- 优先查看扩展脚本编辑区域、脚本运行结果或开发者控制台,搜索
script-test。 - 如果扩展脚本区域没有输出,再查看该扩展卡片的错误提示或日志;不要只在内核日志中搜索,因为
console输出位置可能随版本和调试入口不同而变化。 - 最小脚本能执行后,再逐段恢复原脚本,每次只增加一个修改目标。
官方文档列出了脚本环境支持 console,项目讨论中也有在全局扩展脚本区域查看 console.log 输出的说明。由于不同版本的界面可能不同,最稳妥的判断方式是同时观察脚本编辑区域、开发者控制台和扩展卡片提示,而不是把内核日志作为唯一依据。可参考项目讨论中的扩展脚本调试说明。
| 现象 | 优先检查 | 第一步处理 |
|---|---|---|
| 脚本无法保存或导入 | 入口、脚本类型、基础语法 | 确认编辑的是“扩展脚本”,先粘贴最小 main(config)。 |
| 导入成功但完全无变化 | 是否启用、是否重新生成配置 | 保存后重新加载或激活配置,再查看脚本区域的输出。 |
| 脚本执行时报错 | 入口函数、沙箱 API、字段路径 | 记录完整报错关键词,暂时删除外部模块、文件读写和网络请求。 |
| 脚本执行后策略组或节点为空 | 过滤条件、数组判空、节点名称引用 | 先保护数组,再确认过滤结果和策略组引用的节点确实存在。 |
| 脚本修改后又恢复 | 应用设置和扩展执行顺序 | 检查设置页是否接管了模式、端口、TUN 或部分 DNS 字段。 |
先分清脚本类型:JavaScript 扩展脚本不是 YAML 配置
“模块脚本不能跑”经常不是代码本身的问题,而是脚本被放进了错误的入口。Clash Verge Rev 官方文档将扩展分为“配置”和“脚本”:配置使用 YAML 做覆写或合并,脚本使用 JavaScript 处理配置对象。两者的编辑入口、语法和报错方式不同,不能把 JavaScript 代码粘贴到 YAML 扩展配置中。可查看Clash Verge Rev 扩展配置与脚本说明。
| 机制 | 主要格式 | 是否需要 main(config) | 常见用途 |
|---|---|---|---|
| 扩展配置 | YAML | 不需要 | 覆写 dns、rules、tun 等配置字段。 |
| 扩展脚本 | JavaScript | 需要 | 按条件修改规则、策略组、DNS 或订阅生成的配置对象。 |
| 内核配置 | YAML | 不需要 | 供 Mihomo 内核实际读取的完整配置,不等于客户端脚本。 |
| 其他客户端脚本 | 因客户端而异 | 不一定 | 其他桌面端或移动端可能使用 Actions、覆写、插件或不同的脚本 API。 |
本文只讲 Clash Verge Rev 的扩展脚本。Clash for Windows 的 Actions 或 parsers、移动端客户端的模块与插件机制,以及其他客户端的脚本参数,不应直接套用本文代码。即使文件后缀都是 .js,入口函数、可用 API、执行时机和返回值要求也可能不同。
按报错关键词排查:入口、语法和脚本沙箱
1. 先确认入口函数和返回值
Clash Verge Rev 官方文档说明,脚本入口是 main 函数,接收一个配置对象,并返回修改后的配置对象。最稳妥的基础结构如下:
function main(config) { return config; }
如果脚本没有定义 main,或者最后返回了字符串、布尔值、数组等非配置对象,可能出现入口未找到、返回对象无效或配置无法生成等问题。具体报错文案可能因内置 JavaScript 引擎和版本而不同,不要只按某一条固定英文报错判断。
2. 使用 Node.js 做语法检查,但不要把它当成兼容性测试
如果你把脚本复制到本地文件,可以在 PowerShell 或终端中运行:
node --check script.js
它只能检查括号、引号、关键字等基础 JavaScript 语法,不能验证 Clash Verge Rev 的内置执行环境、传入参数、配置字段结构或应用设置优先级。即使语法检查通过,仍需在客户端内实际运行最小脚本。
3. 遇到 require、import、文件或网络相关错误
官方文档说明,Clash Verge Rev 扩展脚本使用 boa_engine 执行,并且不支持网络 IO 和文件 IO。遇到 require is not defined、文件读取失败、请求接口失败,或使用 ES 模块语法后出现 SyntaxError 等情况,应删除 Node.js 模块、动态加载、文件读写和网络请求代码,改为只处理传入的 config 对象。
支持的 API 中包含 console、JSON、数组、正则表达式和常见错误对象,但这不代表可以直接使用 Node.js 的内置模块。报错关键词可能因执行引擎而异,建议保留完整错误文本和出错行号,再逐段缩小代码范围。
4. 需要区分订阅时,再使用第二个参数
官方文档说明,较新的版本增加了字符串类型的 profileName 参数。可以这样写:
function main(config, profileName) { if (profileName === "订阅A") { config["log-level"] = "debug"; } return config; }
如果脚本来自其他客户端,不要默认它也会传入同名参数。先用只有一个参数的 main(config) 验证执行,再加入第二个参数和条件逻辑。
脚本执行了但策略组或节点为空:加判空保护再查引用
如果最小脚本能够输出,但原脚本执行后节点、代理组或规则消失,重点检查过滤条件和字段结构。常见风险是直接把 proxies 过滤成空数组,或者策略组中引用了订阅里并不存在的节点名称。不要先假设是线路故障,先在脚本中加入判空和数量检查。
下面的示例只在代理组存在且原本有节点时进行过滤,并保留过滤前后的数量信息:
function main(config) { const groups = Array.isArray(config["proxy-groups"]) ? config["proxy-groups"] : []; groups.forEach(group => { if (group && group.name === "示例策略组" && Array.isArray(group.proxies)) { const before = group.proxies.length; const filtered = group.proxies.filter(name => typeof name === "string" && !name.includes("测试")); if (filtered.length > 0) { group.proxies = filtered; } console.log("group", group.name, "before", before, "after", group.proxies.length); } }); return config; }
- 把
示例策略组换成配置中真实存在的策略组名称。 - 先确认
config["proxy-groups"]是数组,再访问其中的proxies。 - 过滤后如果数量为零,先不要覆盖原数组,避免整个策略组失去节点。
- 如果策略组仍为空,检查订阅生成的节点名称是否和脚本中的字符串完全一致。
- 脚本恢复正常后,再逐步加入规则、DNS 或其他字段修改。
Clash Verge Rev 官方示例也使用数组和配置对象进行规则、策略组等字段处理,因此脚本修改前应先确认字段存在、类型正确,并保留返回的 config 对象。可参考官方自定义脚本示例。
| 报错或现象 | 可能原因 | 修复动作 |
|---|---|---|
main 未定义或入口错误 | 函数名称不对,或代码没有定义入口 | 改为 function main(config) { return config; } 测试。 |
SyntaxError | 括号、引号、关键字或模块语法不适配 | 先运行 node --check,再删除 import 等不必要语法。 |
ReferenceError | 使用了不存在的变量、Node.js 全局对象或外部模块 | 检查变量是否定义,删除 require、文件和网络依赖。 |
TypeError | 对不存在的对象或非数组字段调用方法 | 使用 Array.isArray、空值判断和条件初始化。 |
| 执行后节点或策略组为空 | 过滤结果为空,或引用名称不存在 | 打印过滤前后数量,保留非空结果并核对名称。 |
| 修改 DNS、TUN 或端口后恢复 | 应用设置在扩展流程末尾覆盖字段 | 检查设置页接管项和扩展卡片提示。 |
执行顺序导致配置被覆盖:检查应用设置和扩展合并规则
脚本能够执行,不代表脚本写入的每个字段都会成为最终配置。Clash Verge Rev 官方文档给出的扩展链路是:订阅原文、应用设置、全局扩展配置、全局扩展脚本、订阅扩展配置、订阅扩展脚本,最后再进行应用设置回写。设置页中的选项优先级高于订阅原文、扩展配置和扩展脚本,部分字段会被应用接管。
因此,如果脚本修改了 mode、端口、tun.enable、TUN 细项或部分 DNS 字段,界面设置可能在最终生成配置时重新写回。官方文档明确列出了应用接管的字段,并说明被覆盖时会在扩展卡片日志中记录。详细执行顺序和优先级可查看扩展配置与脚本官方说明。
- 脚本修改 DNS 后恢复:检查 DNS 覆写是否开启,以及设置页是否接管了相关字段。
- 脚本修改 TUN 后恢复:检查 TUN 设置中的启用状态、路由、DNS 劫持、MTU 等项目。
- 脚本修改模式或端口后恢复:检查客户端设置中的运行模式、混合端口、 SOCKS 端口或其他端口选项。
- 全局脚本和订阅脚本结果不同:确认脚本放置范围,并注意订阅扩展脚本在执行链路中更靠后。
- DNS 规则被替换:扩展配置中的部分 DNS 字段按整体替换处理,不一定是逐项合并;需要保留多项内容时,应在脚本中读取原对象后再追加。
排查时应查看最终生成的配置,而不是只看脚本源码。可以先关闭一个可能接管目标字段的应用设置,重新生成配置,再比较修改前后的结果;确认原因后,再决定由脚本还是由设置页统一管理该字段。
安全与回滚:先备份订阅和脚本,再缩小复现范围
扩展脚本会参与订阅配置生成,修改前先备份当前脚本和配置。订阅链接、访问令牌、API 密钥、控制器密钥以及包含个人信息的日志,不要粘贴到公开脚本、截图或问题帖中。
- 复制当前扩展脚本,保存一份可以恢复的原始版本。
- 暂时只保留
main(config) { return config; }或最小测试代码。 - 确认最小脚本可以执行后,只增加一个目标,例如先测试规则,再测试策略组,最后测试 DNS 或 TUN。
- 每次修改后重新生成配置,并在扩展脚本区域或开发者控制台观察输出。
- 发现远程脚本包含网络请求、文件读写、动态加载或难以解释的混淆代码时,不要直接启用。
- 如果最小脚本正常而原脚本失败,优先检查 API、字段结构、过滤逻辑和应用设置优先级,而不是立即更换节点。
如果仍无法判断问题来自脚本、订阅配置还是网络连接,可以停止使用原脚本,用不含敏感信息的最小配置复现,再分别恢复配置和脚本。本站是第三方使用指南站,不是 Clash Verge Rev 官方站;版本界面和脚本行为如有差异,应以当前客户端文档和实际提示为准。
常见问题
Clash Verge Rev 扩展脚本不能跑,最先应该检查什么?
先确认脚本放在配置卡片的“扩展脚本”入口,而不是 YAML“扩展配置”入口。然后用 function main(config) { console.log("script-test"); return config; } 测试,并在扩展脚本编辑区域、运行结果或开发者控制台查看输出。
为什么 console.log 输出不在客户端内核日志里?
Clash Verge Rev 官方文档只说明脚本环境支持 console,项目讨论显示扩展脚本输出可以在全局扩展脚本区域查看。不同版本的调试入口可能不同,因此应优先查看脚本编辑区域或开发者控制台,不要只搜索内核日志。
node --check 通过后,为什么 Clash Verge Rev 仍然报错?
node --check 只能检查基础 JavaScript 语法,不能验证 Clash Verge Rev 的内置 JavaScript 执行环境、main 参数、配置字段结构或应用设置优先级。语法通过后仍需在客户端内运行最小脚本。
Clash Verge Rev 扩展脚本支持 require、import 或网络请求吗?
官方文档说明扩展脚本使用 boa_engine 执行,不支持网络 IO 和文件 IO。遇到 require、文件读取或网络请求相关错误时,应改为只处理传入的 config 对象;import 写法出错时,报错关键词可能因执行引擎而异。
为什么脚本执行后策略组或节点为空?
常见原因是脚本把 proxies 过滤成了空数组,或策略组引用了订阅中不存在的节点名称。先用 Array.isArray 检查字段,记录过滤前后的数量,过滤结果为空时不要覆盖原数组,再核对策略组和节点名称。
为什么脚本修改了 DNS 或 TUN,重新加载后又恢复?
Clash Verge Rev 的应用设置优先级高于扩展配置和扩展脚本,部分 DNS、TUN、模式和端口字段会在扩展流程后被应用设置回写。应检查设置页的接管项,并查看最终生成配置和扩展卡片提示。
其他客户端的 Clash 模块脚本可以直接放进 Clash Verge Rev 吗?
不建议直接套用。其他桌面端和移动端可能使用 Actions、覆写、插件或不同的入口函数和参数。本文只适用于 Clash Verge Rev 扩展脚本,跨客户端使用前应先核对对应客户端的脚本文档。
相关阅读
参考资料
- Clash Verge Rev Docs:自定义脚本(clashverge.dev)
- Clash Verge Rev Docs:扩展配置与脚本(clashverge.dev)
- Clash Verge Rev GitHub Discussion:如何调试全局扩展脚本