訂閱在用戶端裡的身分是「遠端資料的一份本機快取」。每次更新,用戶端重新拉一遍遠端內容,按它重新產生設定檔。你手寫在那個檔案裡的東西不參與這個過程,自然也留不下來。踩過一次就懂了,剩下的問題只是怎麼繞開。

改動應該掛在訂閱之上,而不是寫進去

Clash Verge Rev 的辦法是把「訂閱說了什麼」和「你改了什麼」拆成兩層。訂閱那份保持唯讀,你的修改單獨存成擴充設定;用戶端每次產生最終設定,都是先取訂閱原文,再把你這層疊上去。訂閱怎麼變都行,你那層始終在。別的用戶端也有同樣的東西,名字可能叫覆寫、Mixin 或者前置處理,形狀是一樣的。

合作推薦訂閱連結從哪來?本站合作機場註冊即送 1GB 香港高速體驗流量,可直接一鍵匯入。取得高速節點

兩種擴充:一段 YAML,一段 JS

  • Merge:一段 YAML 片段,和產生出來的設定做合併。適合寫死的內容——幾條規則、一段 dns、改個連接埠。
  • Script:一段 JavaScript,進入點函式拿到完整的 config 物件,你改完 return 回去。適合有條件判斷的活;純靜態的內容用它是殺雞用牛刀。
  • 順序是固定的:訂閱原文 → Merge → Script → 最終生效的設定。Script 看到的是 Merge 之後的結果,兩個都掛著的時候,Script 說了算。

Merge 最容易踩的一腳:清單是取代,不是追加

同名的鍵後者覆蓋前者,這符合直覺。清單不符合。你在 Merge 片段裡寫一個 rules,預設行為是用你這幾行把訂閱那幾百行整個換掉,於是除了你寫的以外全沒了。表現出來就是絕大多數網站突然全部直連,或者突然全部走代理。要往清單裡加內容得用專門的鍵:prepend-rules 往前插,append-rules 往後接,proxy-groupsproxies 也有對應的 prepend / append 形式。規則講順序,自訂規則基本都該用 prepend。

prepend-rules:
  - DOMAIN-SUFFIX,internal.example.com,DIRECT
  - PROCESS-NAME,Telegram.exe,PROXY
append-rules:
  - DST-PORT,25,REJECT
dns:
  enable: true
  nameserver:
    - 223.5.5.5

Script 能做 Merge 做不到的事

腳本進入點是一個函式,參數是解析好的設定物件,回傳值就是新設定。這表示你可以按條件處理,而不是把結果寫死:篩掉那些名字裡寫著到期時間和剩餘流量的假節點,給所有節點名加統一前綴,或者把符合某個模式的節點整批塞進一個群組。這些 Merge 表達不出來,因為你事先根本不知道訂閱裡會有什麼。

function main(config) {
  config.proxies = config.proxies.filter(function (p) {
    return p.name.indexOf('剩餘流量') === -1;
  });
  config.rules.unshift('DOMAIN-SUFFIX,example.com,DIRECT');
  return config;
}

別靠猜,去看合成出來的東西

擴充設定寫錯了,症狀很不體貼:要麼設定直接載入失敗,要麼載入成功但某一整段悄悄消失——節點清單少一半,或者規則表裡只剩你自己寫的那兩條。用戶端一般提供查看最終生效設定的入口,在設定項目的右鍵選單或者詳情裡,有的寫作「檢視設定」,有的是匯出。改完就去看一眼:你加的在不在,原來的還在不在。比從現象往回推快得多。

擴充設定裡只放增量:規則、DNS、幾個自己加的策略群組。別去重寫整段 proxies——節點是訂閱的職責,你把它接管過來,就等於放棄了自動更新的全部意義,服務商哪天換個伺服器位址,你得手動跟一次。至於規則本身怎麼寫、擺在第幾行才有效,那是另一篇的事;這篇只管讓它別被沖掉。