跳至主要内容
💬 回報這一頁

跟上新版

導入是一天的事,跟上是每個月的事。 這一頁回答導入之後的三個問題: 怎麼知道上游動了、怎麼判斷要不要跟、決定要跟之後每一層各怎麼跟。 (導入本身見導入三階段;版號的定義見版本策略。)

訊號從哪來​

上游進版時會發出的訊號,依層整理如下——挑一條訂閱,不要靠想起來:

通道涵蓋怎麼訂
GitHub Release(vX.Y.Z)規範版:元件與 token 有取用端可感知的變更;notes 末尾列出這一版動到的 registry itemrepo 頁 Watch → Custom → Releases,有新版就收到通知
CHANGELOG每次進版一則,含「我需要做什麼」判斷時讀;不適合當提醒機制
npm outdated @dooping/tokenstoken 層放進宿主 CI 例行跑
dooping-check元件層:你抄過的 item(含相依)上游動了沒、本地改了沒下面的「例行檢查」,放進宿主 CI
/r/index.json機器可讀正本:規範 version、配對的 tokensVersion、每個 item 的指紋 meta.closureHash自己寫檢查時讀

四個刻意設計要知道:

  • 純文件進版不打 tag、不發 Release。 版號沒動=取用端不需要任何動作, 所以你不會收到通知——安靜本身就是訊號。
  • 規範版與 token 版是配對的:每版規範恰好宣告一個 tokens 版, 正本在 /r/index.json 的 tokensVersion(見版本策略的配對模型)。
  • Release 的 item 清單分四類:內容有變、只因相依變了而受影響、新增、移除。 最容易漏的是「只因相依受影響」——修正落在 utils 時,抄了 data-table 的人一樣要重抄。
  • 訊號只來自核准版(main)。 上游每一版先進 /staging/ 做套用驗收,核准後才進正式站、才發 Release。 想提前試下一版,可以在自己的分支從 /staging/r/ 裝來回報問題;正式導入與例行檢查一律對 /r/ (流程見版本策略「三段式發布」)。

例行檢查:dooping-check​

提醒用,不擋建置——升級是決定,不是 CI 事件。一次性準備:

npx shadcn@latest add https://kielchang.github.io/dooping-design-book/r/dooping-check.json # 裝進 scripts/dooping-check.mjs
node scripts/dooping-check.mjs init data-table page-header # 列出你「主動」裝過的 item,相依會自動算進去

之後每週在宿主 CI 跑一次:

node scripts/dooping-check.mjs

每個 item 回報三種狀態之一:

狀態意思下一步
已是最新上游的指紋與 lock 相同,本地檔案也沒改不必動
上游有更新這個 item 或它的相依在上游變了照輸出的指令先 --dry-run --diff 看差異;決定跟進就重抄,再 update <item>
本地改過本地檔案的內容與 lock 記的不同刻意偏離就記進符合性台帳;不是刻意的,重抄即可

dooping-check 本身也是 registry item:它有更新時,檢查會把它列成「上游有更新」。 想讓提醒擋 PR 就加 --strict(不建議當預設)。

指紋怎麼算​

/r/index.json 每個 item 的 meta 有兩個指紋,dooping-check 與 Release 的異動清單都靠它們:

  • hash:取用端抄走的東西。依序串接下列各行(以換行分隔),取 SHA-256 的前 16 個十六進位字元: name <名稱>、type <型別>、deps <npm 相依,排序後以空白串接>、registryDeps <registry 相依的 item 名稱,排序後以空白串接>, 然後每個檔依 target 排序各一段 file <target> <type> <內容長度> 接內容。排序照字元碼位。 不含版號、標題、說明與 URL——預覽站與正式站的同一份內容必須同一個指紋,只改說明文字也不該叫你重抄。
  • closureHash:自己加上所有遞移 registry 相依的名稱,排序後每行 <名稱>:<hash>,再取 SHA-256 前 16 字元。 任何一個相依變了它就變:utils 修了,data-table 的 closureHash 跟著變、hash 不變。這就是「只因相依受影響」那一類的來源。

這套串接規則是對外契約:改了等於讓所有取用端的 lock 一次失效。實作在 scripts/lib/fingerprint.mjs, tests/registry-fingerprint.test.ts 用獨立寫的第二份實作逐 item 對過;dooping-check 內另有第三份,tests/dooping-check.test.ts 確認一致。

裝不了腳本的專案,退而求其次比對規範版號——粒度只到「規範動了」,看不出動到哪些 item:

UPSTREAM=$(curl -s https://kielchang.github.io/dooping-design-book/r/index.json | jq -r .version)
RECORDED="0.10.0" # 你的台帳記錄的上游版本,跟著台帳一起改
if [ "$UPSTREAM" != "$RECORDED" ]; then
echo "::warning::上游規範已到 v${UPSTREAM}(台帳記 v${RECORDED})——讀該版 CHANGELOG 決定要不要跟。"
fi

判斷要不要跟​

收到訊號之後的流程只有一條,而它的每一步都在縮小要評估的範圍:

流程圖載入中…
  1. 讀該版 CHANGELOG 的「我需要做什麼」。 每一則都會明說,不需要就寫不需要—— 寫不需要就結束,這是最常見的出口。
  2. 對照符合性台帳。 只有標「遵循」的列需要評估; 「自製」不受影響,「刻意偏離」只需重讀一次原因(上游這版說不定正好解掉了偏離的理由)。
  3. 衡量差距與影響再決定。 版號差距是線索:大版差=有會壞的變更、中版差=有新能力、 小版差=修正微調。但差距只回答「上游改了多大」,不回答「你要不要跟」——判準是影響:
情況決定
上游修了你也踩到的問題跟進,這是唯一「必須同步」的情況
有用的新能力,但這期排不進記台帳、延後——在台帳的上游版本欄記下差距
與本地的刻意做法衝突偏離,在台帳寫下原因(沒寫原因的偏離是待修項目)
✅ 這樣做

把「上游 bump」當成一個要排程的決定:逐列評估、更新台帳、 在自己的 CHANGELOG 記一則。

🚫 不要這樣

不要 npm update 之後看 CI 綠就當作升級完成。 設計系統的變更改的是已上線畫面的外觀與行為,CI 不看外觀。

決定跟進之後:每層的程序​

層程序
tokennpm update @dooping/tokens(^ 範圍內)。跨大版先讀 CHANGELOG;0.x 期間任何版本都可能 breaking,語意色名稱已穩定、值仍可能調
元件重跑同名 npx shadcn@latest add <URL>(覆寫 components/dooping/ 同名檔,相依會一起覆寫;先加 --dry-run --diff 看會動到哪些檔)→ 用 git diff 逐檔審查——落點固定就是為了這一刻 diff 是乾淨的 → node scripts/dooping-check.mjs update <item> → 台帳該列更新上游版本
模式/頁面重讀該則文件,對照本地實作;有差就記台帳(遵循/刻意偏離)
✅ 這樣做

元件更新走「重抄+diff 審查」,把上游的改動看過一遍再合進去; 本地改過的部分會在 diff 裡現形,逐塊決定保留或讓位。

🚫 不要這樣

不要手動把上游的改動「挑幾行抄過來」。半套的同步讓台帳那一列 既不是遵循也不是偏離,下一次升級就沒有人敢動它了。

開發中的節奏​

跟上游的關係不是升級當天才存在。日常開發的四個習慣,讓每次升級都是小事:

  1. 新畫面動工前先查上游:到頁面章選頁型、查元件章有沒有現成件。 最貴的漂移是「上游有,但我們自己又做了一個」。
  2. 缺件不長私有版:先用缺件表的替代方案,同時把缺口回饋上游—— 每一則都是三次法則的一次證據,由守門人在上游串起來,過了就是大家的元件。 入口與格式(取用端 agent 送 PMIS、人走 GitHub 表單)見回饋與 RFC 流程。
  3. 節奏掛在里程碑上:sprint 或版本邊界檢查一次訊號就夠,不必每天。 衝刺中收到新版訊號,記台帳延後即可——衝刺中途不升大版。
  4. 台帳與離線摘要跟著改: 台帳記「跟上游的關係」,摘要記「最常用的判斷依據」,兩者過期比沒有更糟。
✅ 這樣做

把「檢查上游」寫進里程碑的定型工作(跟「更新相依」同一個時段做)。

🚫 不要這樣

不要等到「畫面看起來怪怪的」才發現落後了四個版。中間每一版的 CHANGELOG 都在講你要不要動作,一次補讀四版的成本遠高於四次各讀一版。