更新日誌

Swift Web 框架的版本發布歷史,包含 CLI 工具、框架模組與文件站的所有變更記錄。

本文件按月彙總 Swift Web 5 倉重大變更,月內按 framework / starter / standards / cli / docs 5 倉拆分。只記錄重要新特性 / 重要重構 / 重要 BUG 修復 / Breaking Change / 跨倉事件。完整變更請查 git log。


2026-09

framework v0.140.0 → v0.155.0 · starter v0.35.13 → v0.37.0 · standards v0.13.27 → v0.13.89 · cli v0.21.1 → v0.23.1

本月聚焦快取與部署一致性、API 產生可靠性及雙工具協作;同步統一時長單位,補齊影視 SEO、驗證控制和播放品質追蹤。

framework

  • ⚠️ 時長與上傳 API 統一 — 元件、composable 與模組設定的數字時長統一為毫秒,週期設定改用 Nm / Nh / Nd 或 always(ISR TTL 仍為秒);上傳族 isSmall → thumbnail、retryNum → retries、threadNum → concurrency,回頂層級 token 改為 --sw-back-top-z
  • ⚠️ ISR TTL 明確設限 — 禁止 isr: true,宣告值限定為 60–3600 的整數秒;對外 s-maxage 上限為 60 秒,避免多層快取疊加放大過期內容(#394 / #414)
  • 🚀 影視結構化資料 — useSeo 新增 video / media / itemList,輸出 VideoObject、Movie / TVSeries / TVEpisode 與 ItemList,並接入影片 sitemap;呼叫端提供真實業務資料(#381)
  • ⚠️ 請求設定統一 — 新增 request.transport 支援 base64 / binary;nitroApiFetch 直接讀取 runtimeConfig 並使用全域 request.headers,移除 swTimeout / apiTransport 扁平鍵及業務橋接外掛;明文業務失敗保留真實 errorCode(#383 / #391 / #392 / #409)
  • ⚠️ API 產生邊界重整 — 文件來源設定位於 nuxt.config.ts 的 swiftConfig.apiDocs,憑證使用 API_DOCS_TOKEN;OpenAPI 優先按 tags 分組,產生檔標記 @generated,手寫介面放 app/api/manual/ 並自動註冊;YAPI 支援參數範本路徑,擷取、解析或命名失敗時保留舊產物(#402 / #403 / #404 / #406)
  • 🚀 驗證與系統資訊控制 — auth.deviceLogin 可單獨關閉裝置登入,auth.enabled 統一控制自動登入入口;自動重新登入拆分身分 cookie 與使用者資料,用戶端系統資訊按 clientRefreshTtl 重用(預設 300 秒)(#410 / #412 / #413)
  • 🐛 播放異常與簽章續播 — 修正 iOS 全螢幕和切換異常;SwVideoPlayer 與 SwVideoFeed 的 hls.js 路徑在分片簽章過期或網路錯誤時有限次數重新載入同一網址並續播(#398 / #405 / #408)
  • 🐛 圖片與加密資源容錯 — SwImage 缺少網址時降級為預留圖,避免整頁 SSR 500;加密資源忽略過期請求結果,快取讀寫失敗時降級至資源載入(#380 / #397 / #421)
  • 🚀 工作階段與播放品質追蹤 — 自建通道增加來源、UTM、到達頁和裝置脈絡,30 分鐘無活動後更換工作階段;新增首幀、起播耗時、緩衝累計與 play_id,修正首屏重複 PV,並補記 hls 致命錯誤(#415 / #417 / #423 / #425)
  • 🚀 外連與預覽控制 — 新增 useExternalRedirect 提供安全外連中轉邏輯;SwVideoPreview 增加 settled 彙總終態,useHoverPreview.closeOnScroll 支援原位預覽情境(#400)

starter

  • 🔄 部署統一單行程 — 測試與正式環境均採用 PM2 fork 單行程,搭配行程設定套用與 nginx 快取探針,避免多實例 ISR 快照交替;頁面按類型宣告明確 TTL(standards#86 / framework#414)
  • 🔄 介面接入範本更新 — 手寫介面範例移至 app/api/manual/,移除執行期環境橋接外掛;API / 追蹤代理攜帶 X-Site-Id,代理入口跟隨專案 API_PREFIX

standards

  • 🔄 Claude / Codex 共用規則 — 共用入口統一至 AGENTS.md,補齊 Codex MCP 薄殼;skills 鏡像統一為實體目錄,消除 Windows symlink 簽出差異(#72)
  • 🔧 MR 提交與收尾完善 — 提交前核對預設分支基線,阻止重用已合併分支;審核追蹤按實際 reviewed SHA 判定,明確 Closes / Refs 與 issue 收尾邊界(#70 / #73 / #78)

cli

  • ⚠️ 手寫 API 指令對齊 — sw add api 改為產生 app/api/manual/ 頂層函式模組,sw_project_apis 根據 @generated 區分產生檔
  • 🐛 專案建立與設定修正 — 新專案使用 skills 實體鏡像,關閉 dev mock 時保留測試夾具;補齊 transport、裝置登入與系統資訊重用設定,並提示 JSON 設定可能被 nuxt.config.ts 覆蓋

docs

  • 🚀 使用指南補齊 — 新增 useExternalRedirect 三語參考,補全元件 CSS token 表;API 產生、渲染 TTL 與部署指南同步新契約
  • 🐛 文件站建置設定修正 — catch-all 文件頁改用明確 prerender 規則,移除不存在的 ~/api 自動匯入,PWA 名稱與描述改從網站設定衍生

跨倉事件

  • 🔧 核心五倉接入 MR 門檻 — 一般開發統一短期分支 → MR → dev,接入自動審核及檢查;npm 發版保留維護者本機明確操作,docs 保留 dev 部署(framework#416)
  • 🔧 Nuxt 安全升級 — framework、starter 與 docs 升級 Nuxt 4.5.2,修正開發工具與 SSR 相關安全問題,並檢查使用端相容性(framework#386)

2026-08

framework v0.95.0 → v0.140.0 · starter v0.32.0 → v0.35.13 · standards v0.4.4 → v0.13.27 · cli v0.16.4 → v0.21.1

特大月(5 倉合計 1000+ commits)。月初收尾 ISR 快取正確性戰役(canonical 策略反轉為「預設跟隨訪問網域」);隨後主線轉向工程治理三役——規則三層化、e2e 進 CI 門禁、feature-branch flow 遷移(dev/vN 退役);framework 側完成 PWA 體系大修與行動端播放相容批。

framework

  • ⚠️ SwVideoPreview 預設播滿 60 秒即停 + loop 預設改 false(#286,0.101.0)— 兩條行為 BC。預覽位址的常見形態是「營運沒單獨設定預覽資源時,回退正片播放位址」,而元件此前沒有任何時長上限且預設循環 ⇒ hover 多久就串流多久,等於付費正片能被當預覽看完。這個缺口對所有 applier 都開著,只能靠每個業務方自己想起來堵。
    新增 maxDuration(預設 60,0 = 不限),按累計播放時長計(暫停 / 緩衝不計入),到點 hls.stopLoad() + pause()(保留最後一格畫面)並 emit capped。60 的依據:實測業界策展預覽片素材本就 55s~2min(騰訊 112s / 優酷 55s),60 秒對它們幾乎不觸發(走 @ended 自然收尾);而 60 秒之於 90 分鐘正片是 1.1%,靠 hover 累積看完不可能。loop 同期翻為 false —— 實測兩家均不循環,循環本質是「素材太短」的補丁,且它與上限是一對(6 秒素材配 60 秒上限會重播 10 次)。
    順帶收口取來源為空時的靜默:此前三條路徑(fetchPlayUrl: null 卻沒傳 url / id 為空 / 拉取結果無可用位址)都是 emit 完 loading 就再無音訊 ⇒ 消費方只能永遠停在 loading 態(cinebay 的載入掃描線因此無限掃)。統一 emit 新事件 empty(不用 error——「本來就沒有預覽來源」是業務合法狀態)。
    遷移:需要循環請顯式傳 loop、需要更長請顯式傳 maxDuration;applier 側自寫的「N 秒後 v-if 卸載播放器」兜底與「逾時強解 loading」hack 都可整段刪掉
  • 🐛 useHoverPreview 內建觸控門控(#287,0.101.0)— 原始碼註解此前寫著「觸控裝置無 mouseenter,天然不觸發(無需額外守衛)」,這是錯的:瀏覽器為相容只監聽滑鼠事件的老網站,會在 tap 之後補發一串相容性滑鼠事件(mouseover / mouseenter / mousemove / click)。實測(Pixel 7 裝置畫像 + 真實觸控輸入)還暴露出比「多彈一下」更重的後果:tap 之後根本不會有 mouseleave —— 手指離開螢幕不產生「指標移出」,要等下次 tap 別處才補發 ⇒ 行動端點一下卡片,浮層彈出來後一直掛著,而不是「閃一下就被導航沖掉」。
    判定優先按 PointerEvent.pointerType(判「這一次互動用什麼發起」),拿不到才回落 matchMedia,並留 allowTouch opt-out。別單獨用媒體查詢判:(hover:hover) and (pointer:fine) 判的是「裝置主要輸入能力」,二合一裝置上雙向誤判 —— iPad + 觸控板回傳 true(手指 tap 照樣放行)、觸控主導 + 外接滑鼠回傳 false(滑鼠 hover 被誤殺,比原 bug 更糟)。呼叫方建議從 @mouseenter="show" 改為 @pointerenter="show" 才能吃到精確判定
  • ⚠️ --container-padding 加寬螢幕階梯(≥1280 → 48px,≥1600 → 96px)(#284,0.100.0)— 視覺變更:寬螢幕內容區四周出現留白。這是 #283 的續修:把預設上限提到 1920 後,使用者在 1920 CSS 視口驗收發現「看著沒以前好看」——根因是 1920 的容器在 1920 螢幕上等於滿鋪,max-width 形同虛設,內容只被 24px 的 padding 內縮、觀感貼邊。
    業界實測定案(playwright 在 1920 視口量線上 DOM):與我們同形態(無側欄、置中容器)的 bilibili,留白不靠 max-width、靠 padding —— max-width: 2260px; padding: 0 140px,且 padding 按斷點遞增(1440 視口時降到 60px)。YouTube(內容 240→1920)與愛奇藝(192→1897)看著「左邊有留白」其實是側欄佔位、內容區本身滿鋪,與我們非同類,不作對標。
    ⇒ 職責劃分(本次的核心結論):--content-max-width 定「最寬到哪封頂」(只對 2K/4K 螢幕起作用);--container-padding 定「任何寬度下邊上留多少」。此前一直在調 max-width,方向錯了。
    頂檔取 96 而非 bilibili 的 140:140 是配合其 2260 上限設計的(主場 2560 螢幕),我們 1920 在 1920 螢幕即到頂,再留 140 會偏空。
    遷移:無需任何 applier 改程式碼(實測七個 applier 無一覆寫過該變數)。想收窄內容區的站,--content-max-width 與 --container-padding 必須一起調 —— 只改前者會在寬螢幕被 96px padding 二次擠窄(設 1280 實際只剩 1088)。範例見 starter overrides.css 範例 3。
  • ⚠️ --content-max-width 預設 1200px → 1920px(#283,0.99.0)— 視覺變更,全站內容區變寬。1200 是「文章站 / 行銷站」傳統檔(Bootstrap .container 1320 / Tailwind max-w-screen-2xl 1536 同派),而本生態消費方以內容站為主,寬螢幕下明顯偏窄。
    判據是生態自己投的票,不是業界對標:anibay / cinebay / yc001 三站各自獨立在 overrides 裡收斂到 1920(yc001 寫 120rem,同值)。預設值站在 1200 等於讓每站都記得寫那一行 —— 漏寫就是 bug(cinebay#7 驗收當場才發現)。業界數據只作佐證:內容站無一使用 ≤1536 的窄容器(iQIYI 1808 / bilibili 2260 / YouTube 2864,Netflix 與 Disney+ 乾脆不限)。
    要理解的語義:1920 在 1920 螢幕上等於滿鋪(只剩 --container-padding 的 24px),2560 螢幕上才置中留白 —— bilibili / YouTube 在 1920 螢幕同樣滿鋪,且那三個站都沒覺得需要另調 padding。長文字頁不受影響:正文行長由頁面自己的 max-width 約束(starter 的 8 個靜態頁均為 44rem),與站級容器無關。
    遷移:不想變寬的站在自身 overrides.css 寫回 --content-max-width: 1200px(一行)。已寫 1920 覆寫的站不必立刻刪(同值冪等),下次改 overrides 時順手清理。
  • 🚀 建置期攔下「宣告不快取卻被可快取通配吞掉」(#277,0.98.0)— 存在可快取通配時,它覆蓋的每個路徑都被快取,子路徑寫 isr: false / cache: false 都擋不住(快取包裝在 app 初始化時按「已註冊 handler 的路由模式」一次性決定,每請求合併出的 routeRules 不參與該決策)。這類頁面 lint / typecheck / build 全綠、顯示也正常,只有 curl 回應標頭看得出來。
    按 ssr 分檔,不是一律報錯:ssr: false 放過(回傳建置期產生的 SPA 空殼、按定義與請求無關,實測同一頁兩個不同 query 的 HTML 位元組完全相同 ⇒ 快取無害);ssr: true(或不宣告)報錯——它會真 SSR 渲染,且同時騙過 eslint no-query-in-cacheable-ssr(那條規則的前提是「檔案宣告了 isr/swr/cache/prerender」,而它宣告的是 isr: false)⇒ 能合法讀 query 卻被快取 ⇒ 內容錯配。分檔讓誤報為零,故 error 級站得住、不需要 opt-out 機制
    0.98.1 修了它自己的一處誤報:redirect / proxy 規則不渲染頁面(前者發 3xx、後者轉發上游),被通配快取不產生內容錯配,卻被 0.98.0 當成違規攔下。上線當天就在 yc118 的真實建置裡撞到(一條 /home 重新導向)。⚠️ 順帶一條教訓:0.98.0 發版前我判斷「全生態命中 1 處、零誤報」,依據是掃各倉 nuxt.config 的靜態 routeRules——那看不見頁面級 defineRouteRules 展開成的 glob。判「生態裡有沒有某種規則形狀」只能真跑一次 build
  • 🔧 錯誤 toast 與上報解耦(#282,0.97.0)— errorHandler 新增 toast 旋鈕:錯誤時是否給終端使用者彈可見 toast。預設 false = 靜默上報(對齊 Sentry / Bugsnag 業界預設;此前 0.87.0 起啟用即無條件彈「系統出現了一個錯誤」,對內容站沉浸瀏覽是純打擾)。要舊行為顯式 { "errorHandler": { "enabled": true, "toast": true } }。POST 上報路徑不變
  • ⚠️ origin / canonical 策略反轉(#278 續,0.96.0 – 0.96.1)— 上月 0.95.0 的修法是「以 NUXT_PUBLIC_SITE_URL 為主路徑」,實踐中被推翻,理由有三:開發者常不知道正式生產網域、生產網域會換、一個產品往往有多個網域。新策略:
    L1  顯式 useSeo({ siteUrl })   單頁覆寫
    L2  NUXT_PUBLIC_SITE_URL       設了它才收斂到該網域(opt-in,屬營運決策)
    L3  useRequestURL().origin     預設:跟隨使用者實際造訪的網域
    

    真正的修復落在 L3 能不能運作上——isr → cache 翻譯時固定注入 varies: ['host', 'x-forwarded-proto'],讓被快取的頁面拿回 Host。代價是這兩個標頭進快取鍵 ⇒ 條目數 ≈ 合法網域個數(對多網域產品正是想要的);「任意 Host 造條目」應在反向代理層擋(server_name 列全 + default_server 回 444)。連帶把「未設定 NUXT_PUBLIC_SITE_URL」從告警降為正常狀態——只有存在 prerender 頁時才必須設定
  • ⚠️ SwInput 升級為 wrapper 結構(#305,0.108.x)— 皮膚(邊框 / 背景 / focus 態)從內層 input 上移到新增的 wrapper 元素,結構 BC:applier 把 --sw-input-* 變數或選擇器寫在內層 input 上的會退回預設皮膚。適配前先升 ≥0.108.3——0.108.2 及更早存在 class/style 落點錯位,變數會落錯層
  • 🐛 PWA 體系大修:manifest 從來沒被 link 進 head(#355 等,0.122.0–0.128.0)— 全生態所有 PWA 站點的 manifest 一直在生成、卻從未被頁面引用(@vite-pwa/nuxt 只註冊元件不掛載,「註冊 ≠ 被消費」,只有查線上 DOM 才看得見)。同批:manifest 補 background_color(深色站冷啟白閃)/ lang / description(#357);iOS 主屏預填名與 standalone 判定修正(#352 / #353);BC:framework.pwa 收窄為純布林,manifest 內容遷至 swift.config.json(#359,0.125.0);SwAddToHomescreenGuide 適配 iOS 26 新工具列 + 預設皮膚重做(0.128.0)
  • 🔄 裸源發布試驗與撤回(#289 → #362,0.124.0–0.126.0)— dist/runtime 曾改發裸 TS/.vue 源(意圖讓消費方 IDE 直讀原始碼),實測撤回:裸源讓部分消費鏈型別解析劣化、發布產物形態變化牽連既有規則。0.126.0 恢復全編譯並加 assert-publish-shape 四條發布態守衛,防產物形態再靜默漂移
  • 🚀 鍵盤可達性批(#331,0.130.0)— 可排序表頭內容包進 <button>(W3C APG 範式,結構 BC:#header-* slot 內容成為 button 後代、只能放 phrasing content,th:hover 視覺選擇器需改指向 button.th-inner);SwTable 掛 @row-click 但列內無可聚焦元素時 dev 告警(WCAG 2.1.1);貼片按鈕 div→button、掃碼器 focus ring。9 個 applier 實測零適配
  • 🔄 升級 pinia 4 + 刪除 ESM alias hack(0.131.0)— Pinia 3.x 時代的 ESM 相容 alias 整段移除;連帶暴露個別 applier 自宣告 pinia 的存量違規(重複框架模組建置期護欄會攔)
  • 🚀 行動端播放相容批(#365 等,0.132.0–0.133.0)— iPhone 改為優先原生 HLS:hls.js 預設走 ManagedMediaSource,而 UC 等第三方核心「只推時間軸不渲染畫面」(真機實測);補齊行內播放屬性(webkit-playsinline / x5,防 iOS 強制全螢幕);新增劫持型瀏覽器攔截 blockHijackingBrowsers(UC / 夸克 / QQ / 百度預設攔截換提示、微信有意不攔,#hijacking-browser slot 可自訂)
  • 🚀 觸屏進度條兩態手勢(#372,0.138.0)— 播放中可在收起態進度條上橫向起手直接拖動 seek,不必先喚出控制列;收起 / 展開兩態各自獨立的手勢語義
  • 🐛 可快取頁 Set-Cookie 剝離 + 宣告衝突護欄(#374 / #375,0.139.x)— ISR 等可快取頁渲染期寫的 Set-Cookie 會進快取副本、向後續所有訪客重放,nitro plugin 統一剝離 + dev 告警;頁面級 defineRouteRules 與 config routeRules 同 key 衝突改為建置期報錯。升級跳過 0.139.0 直上 0.139.1
  • 🚀 SwSelect 遠端搜尋(#376,0.140.0)— 新增 remote / loading props 與 @search 事件,搜尋詞交由業務側非同步取數

starter

  • ⚠️ 模板預設改為「跟隨造訪網域」 — (footer) 下 8 個靜態頁 prerender: true → isr: true,NUXT_PUBLIC_SITE_URL 由必填改為可選。原因是 prerender 在建置期沒有真實請求、拿不到 Host,origin 只能來自那個變數 ⇒ 只要有一個 prerender 頁,就被迫設定、被迫收斂。isr: true(快取到下次部署)執行期開銷差別可忽略,卻不需要該變數
  • 🔧 CI 模板長出 e2e 門禁(standards#48 配套,0.35.0–0.35.1)— verify 與 e2e 同 stage 並行;e2e 按「改動是否落在適用面」的路徑過濾觸發(頁面 / 佈局 / 中介軟體 / server route / 框架配置 / 依賴),改元件樣式的 MR 只跑 verify;發布 MR 必跑全量兜底
  • 🐛 0.35.9 事故版與 CI 契約測試(0.35.10)— 一次腳本正則(re.S 貪婪匹配)把 .gitlab-ci.yml 吞剩 3 個 job 發了出去:ci/lint 合法、單測照綠——「刪除型 bug 對『驗存在』的測試免疫」。0.35.10 修復並新增 ci-jobs-contract.spec.ts(job 逐個在 + 總數 + 行數下限),隨模板帶給所有 applier

standards

  • 🔧 CI 裡呼叫 pnpm 必須用 npx --yes pnpm@11,禁止 npm i -g pnpm — runner 是共享 shell runner(多專案並行跑在同一台機器、同一個全域 node 環境),全域安裝等於動全域 bin,並行時一個 job 能把另一個 job 正在用的 pnpm 二進位掀掉。實測事故:兩條 pipeline 同一秒建立、同落一台 runner,其中一條第四步炸 pnpm: No such file or directory,而它前三步用同一個 pnpm 都正常、重跑即綠。排障判據:verify 紅在「某步報 pnpm/node 二進位 not found」且前面幾步用同一二進位都成功 = 基礎設施 flake,先重跑別查程式碼
  • 🚀 sw-standards sync 自助同步 CLI(#32,0.10.0)— applier 一條命令自助同步規則(marker 段 / skills / 薄殼),替代「等維護者集中推送」;輸出規則變更摘要,--check 帶退出碼語義
  • 🔄 規則三層化(#43)— 下游約定檔案從「單檔巨石」拆為三層:AGENTS.md 常駐索引(P0 紅線 + 選型表 + 細則通道)+ .claude/skills/sw-* 按需載入細則 + standards rules/ 主源;sync 目標家族同步擴展(agents / skills / 薄殼三類),Codex / Copilot 經 .agents/skills 鏡像同享
  • 🚀 lint 執法批 — prettier 基座 semi: true + singleAttributePerLine(0.11.0,全生態存量重排);stylelint 新增 hover-media-gate(:hover 必須包 @media (hover: hover),配合觸摸端 hover 黏滯修復)與 component-token-prefix;eslint root-class-sw-prefix 升 v3(根 class 名字必須與元件名對得上)

cli

  • 🐛 sw config set 拒絕合法的物件設定(#46,0.16.5)— framework.pwa 與 framework.errorHandler 在 framework 側的型別是 boolean | XxxOptions,卻被錯列進 cli 的「純布林鍵」白名單 ⇒ sw config set framework.pwa '{"enabled":true}' 被當成非法形狀拒絕寫入。改為按 union 逐層校驗形狀(葉子鍵 / 子欄位 / 父物件整體 set 三種入口都涵蓋)
  • 🐛 pwa 物件設定反被判成「關閉」、刪掉 @vite-pwa/nuxt(#47,0.16.6)— 上一條的迴歸。#46 之前物件值在寫入前就被拒、這條路徑不可達;摘掉布林守衛後物件值合法了,但 applier 派發端仍是 getNestedValue(...) === true ⇒ 物件恆判為 false ⇒ 走 disablePwa()。設定寫著 PWA 開啟、package.json 裡的相依卻被刪,且提示語淹沒在成功回顯裡。修法是照抄 framework 自己的 resolvePwa 歸一(boolean → 自身;物件 → 看 .enabled,缺欄位即關)
    ⚠️ 教訓:從校驗白名單裡移除一個 key,等於給下游放行了它沒見過的形狀 —— 移除前要查這個 key 下游有沒有按舊形狀假設寫的消費者。同型的 cli#39 當年選擇在寫入端拒絕來迴避,#46 拆掉那道拒絕卻沒補派發端,於是原樣復發
  • 🔧 bin 路徑去掉 ./ 前綴(0.16.7)— 消除每次 npm publish 刷的 "bin[sw]" script name ... was invalid and removed 警告。措辭有誤導性(聽著像 bin 被刪了,實際只是剝前綴),零行為變化,改的是「每次發版都刷一遍的雜訊」
  • ⚠️ AI 呼叫安全批(#48 / #49,0.20.0)— sw upgrade 加 --check / --yes,非互動(MCP / 管道)寫操作不再零確認、退出碼分層 0/1/2(三條 BC);MCP 全部 15 工具補 annotations(唯讀 / 寫 / 破壞性外觀區分)
  • ⚠️ pwa 裝卸職責移交 framework(0.17.0–0.19.0)— cli 的 pwa feature 不再裝卸 @vite-pwa/nuxt(由 framework 統一攜帶);framework.pwa 配置形態隨 framework#359 收窄純布林,刪 validatePwaShape

docs

  • 🐛 /composables/use-hover-preview 自上線起線上一直存取不到 — docs 是 SSG 站、prerender 路由靠 crawler 從既有連結爬,而該頁既不在側邊欄、內文也無人連結 ⇒ 零入邊 ⇒ 從未被產生,線上回傳首頁 fallback。陰險處在於建置 / 測試 / lint 全綠,本機 pnpm dev 直接敲 URL 還完全正常(dev 按需渲染、不走 crawler),只能靠人肉發現。已補側邊欄條目,並加孤兒頁守衛:每個 content 頁必須至少有一條入邊(側邊欄 / catalog.ts / 其它頁內文連結,三選一即可 —— 強求「都進側邊欄」會誤傷後兩類合法形態)
  • 🚀 guide 跟進流程演進(三語) — 新增「測試同步與門禁」章(e2e 適用判定 / verify 門禁 / 覆蓋率 ratchet / 登入態注入);Git 協作規範整章重寫為 feature-branch flow;生產部署頁改運維 runbook 形態(首次上線 9 步 checklist + 第 N 次一個命令)

跨倉事件

  • 🔧 feature-branch flow 遷移(standards#51 / #52)— 9 個 applier 預設分支統一 dev/main,dev/vN 長期分支全部退役;只保留 dev/main(整合 / 測試)與 main(生產)兩條長期分支,其餘短期分支合併即刪;生產發布 = dev/main → main 發布 MR,mr-review 對發布 MR 出「🚀 發布摘要」(D5)、對觸及 server/ / CI / 依賴等風險路徑的 MR 不自動合需人工(D6);starter CI 新增 release-guard 提示 job。分支命名與 upstream-first 定調為推薦並預設、不強制——機械層只保護兩條長期分支本身
  • 🔧 e2e 進 CI 門禁 + 覆蓋率 ratchet(standards#48 / #49)— e2e 正式成為 applier 合併門禁(與 verify 並行、按路徑觸發、發布 MR 全量兜底);覆蓋率逐倉 ratchet 只升不降;登入態 e2e 由 setup 走 UI 登入一次 + storageState 複用(TS-003);首批接入 yc118 / yc124

2026-07

framework v0.58.1 → v0.95.0 · cli v0.10.0 → v0.16.4 · standards v0.3.2 → v0.4.4 · starter v0.21.0 → v0.32.0

月末最後一週是「ISR 快取正確性」戰役(#271 起):先發現自架 node-server 上 isr 完全不生效(nitro core 根本不消費它),繼而連鎖挖出通配污染、fs 驅動父子路徑衝突、多動態段規則被丟棄、零段父路徑漏配、被快取頁丟 Host 致 canonical 變 localhost 五個全綠卻靜默失效的坑——逐個補上建置期護欄。

主題 / 語言切換器收口與 0.64 架構正交化打底,中旬 CSS 變數兩層命名模型與 token 表面擴面固化設計語言,下旬管理台元件(SwTable)、SwSelect 搜尋/建立、tracker 自建通道與自助註冊連發;starter 電影三件套 + 通用頁腳模板落地;設計體系(Claude Design / Open Design 雙軌 + 20 卡管線)全量上線;月末 OpenAPI 雙源與 ISR 私有護欄、表單控件族統一高度 + SwInput、SwVideoFeed 預載省流開關收尾。

framework

  • 🚀 主題能力重構(epic #191)— theme 配置收斂為單旋鈕 theme.mode(system / toggle / dark / light)+ color-scheme 解耦 + resolvedTheme;內建切換器 SwThemeSwitch(僅 toggle 模式渲染,token / icon slot / 作用域插槽三檔定制);toggle 模式注入防 FOUC inline bootstrap
  • 🚀 SwLangSwitch 內建語言切換器(#192)— 自 gate(i18n 啟用且 locales ≥ 2 才渲染)+ 聯動 cli 語言配置 + SEO 前綴切換,修 SSR 直出前綴語言頁選中態
  • 🚀 加密 useCookie 覆蓋 + framework-api.json 結構化 props(#203)— framework 的 useCookie(自動 cachePrefix + AES)註冊 auto-import 同名覆蓋 Nuxt 內建;framework-api.json 元件層新增結構化 props 陣列 + tsLayer 三級兜底回讀原始碼
  • ⚠️ 0.64.0 架構正交化 BC(#206)— ModuleOptions 刪 theme 布林糖 + sitemap 併入 seo 套件;YAGNI 收縮公開 API;safeExternalUrl / safeInternalPath 守衛上收 framework
  • 🚀 dev mock 雙端化(#208,0.65.0)— registerApiMock 放寬為 dev 期 SSR + CSR 雙端攔截,universal plugin 成推薦範式,prod 雙端刪淨不變
  • 🚀 元件基線樣式口徑固化(#210,0.66.0)— 「基線樣式非零樣式」(醜但能用合格、看起來壞了不合格)入樣式規範;SwRail gap 退化預設修正、SwFormField 補狀態回饋基線
  • 🐛 修復批(0.66.x) — nuxt-schema-org 釘 6.1.3(修 client 不 hydrate 崩潰);貼片期 autoplay 聲畫錯亂(#211:貼片展示期壓制 autoplay,skip() 統一起播出口)
  • 🔄 CSS 變數兩層命名模型 + token 表面擴面(#219 / #213,0.68.0)— 語義層 Shadcn 裸名豁免、元件級一律 --sw-<元件>-<prop> 全名(--modal-*→--sw-modal-* 等遷移,0.x 直改不留 shim);token 新增 --foreground-soft / --gradient-brand,深色站 --shadow-* 覆蓋與 currentColor 圖示著色口徑固化
  • 🔧 WebSDK v1.1.6 vendored 升級(#225,0.70.0)+ seo-tdk-length lint(TDK 治理:title/description 字面量顯示寬度靜態預檢,warn 級)
  • 🚀 SwTable 資料表格(#227 → #234 管理台強化 → #235 型別匯出,0.71–0.73)— 管理台首選元件:columns 配置 + #cell-<key> 插槽、受控欄排序(v-model:sort 三態)、行選批量(v-model:selected 含 indeterminate)、loading 保結構遮罩、斑馬紋 / 緊湊密度 / 黏性表頭;SwTableColumn 等公開型別 barrel 匯出;自防全域 table 樣式入侵
  • 🚀 SwSelect searchable / creatable(#226,0.71.0)— Combobox 分支:輸入過濾 + chips 多選 + 「建立 "xxx"」輸入即建(multiple + searchable + creatable 即 tag-input 形態);連帶 SwVideoFeed 播放速率 / 線路切換 API(#229)
  • 🚀 tracker 自建通道 + 首屏 pageView(#228 / #236,0.71–0.73.3)— 無 WebSDK 站點用自建 endpoint 批量上報(batch + sendBeacon 兜底);SSR 場景首屏 pageView 補報(0.73.3 修補報 watch 的 TDZ 崩潰 hotfix,⚠️ 0.73.2 勿停留)
  • 🚀 sw-hit-area 觸控熱區 opt-out(#230,0.72.0)— 緊湊控件免除 44px 拉伸 + 偽元素熱區擴到 44×44(「視覺小 + 外包熱區」慣例內建);🐛 SwVideoFeed 手勢中斷吸附回彈(#231)、SwModal 關閉鈕 ✕ → 內聯 SVG(#232)
  • 🚀 userStore.register 自助註冊(#233,0.74.0)— 與 loginByUsername 對稱複用 setInfo 鏈,成功即進登入態(bayverse 使用者系統驅動)
  • 🐛 修復批(0.74.x) — sitemap XSL 標題 undefined(#237:site.name 從 app.head.title 兜底);SwCarousel 手動導航重置 autoplay 計時相位 + 鍵盤焦點暫停(#238:剛選的片不再被臨近 tick 換走)
  • 🚀 SwVideoFeed 下拉重新整理(#241,0.75.0)— pullToRefresh opt-in:首條頂部下拉超閾值觸發 @refresh,受控 refreshing 收尾 + #refresh-indicator slot 自渲染品牌指示器(懸浮不位移內容,僅 touch)
  • 🐛 useSeo lint 補齊 error.vue 覆蓋(#240,0.74.2)— require-useSeo-in-pages 此前只匹配 app/pages/**,與文件聲明不符;補 isErrorPageFile 後全域錯誤頁缺 useSeo 同樣報 warn(錯誤頁 noindex 是硬要求)
  • 🚀 generate-api 雙源:OpenAPI 3 接入(#242,0.76.0)— source adapter 架構,自研 server 的「API 文件 → 請求代碼」自動鏈與 YAPI 源並行
  • 🚀 ISR 私有數據護欄 L2–L4(#243 / #245,0.77.0–0.78.0)— generate-api 按 visibility 分檔案 + manifest + private 元數據注入;eslint isr-no-private-api 機檢 ISR/prerender 頁調 private API(判據收斂 SSR 執行路徑消事件處理器誤報);request dev 期 SSR 調 private 警戒;generate-api --check 漂移檢查
  • 🚀 表單控件族統一高度/字號 + SwInput(#244,0.78.0)— 語義 token --control-height(32px) / --control-font-size(14px),SwInput / SwSelect / SwSegmented 同行混排預設等高等字號(⚠️ SwSelect 36→32px·字號 16→14、SwSegmented 42→32px 有意視覺 BC);新元件 SwInput(表單基線盒子 + 觸摸設備防 iOS 聚焦縮放),starter LoginForm 遷移作參考實現
  • 🚀 SwVideoFeed 預載可控(#246 / #248,0.79–0.80.0)— preload?: boolean | number:預設預載後 2 條影片各前 5s(⚠️ 原視窗 ±1 條各 30s 全量預載,CDN 流量大降);廣告條跳過不佔名額、尾部截斷、掛載窗前伸;false 完全關閉
  • 🐛 滾輪慣性尾巴過衝修復(#247,0.80.0)— Windows 精密觸控板一次滑動竄多條:鎖定解鎖改 240ms 靜默窗 + 力度回升絕對下限;deltaY 補 deltaMode 歸一化(Firefox 滑鼠滾輪一格即翻條)
  • 🚀 埋點擴容三連(#249 / #250 / #251,0.81.0)— track 事件名放寬為「預置列舉 + 任意自訂字串」並按通道分流(自訂名僅自建 endpoint 入庫,WebSDK 通道列舉外名 dev 警告後忽略);影片播放心跳 + 累計觀看時長 watch_time;廣告關閉埋點 useAdTrack.reportClose(含 close_reason)
  • 🚀 useHoverPreview 機制層收編(#253,0.83.0)— 卡片 hover 放大預覽的意圖狀態機(300ms 彈出 / 140ms 關閉 / 順移保持 / 捲動即關)+ computePreviewBox 定位純函式;浮層視覺仍歸業務自繪,starter 刪本地副本改引 framework
  • 🔄 token 與幾何三件套 — 媒體遮罩語意 token --scrim / --scrim-top(#254,0.84.0,一行消費免 no-hardcode disable);SwRail 箭頭垂直錨點 --sw-rail-arrow-top(#252,0.82.0);SwModal 視口安全 width / max-height + class 透傳落 content(0.85.0,per-dialog 客製的官方通道)
  • ⚠️ SwSegmented 預設視覺對齊業界灰槽形態(0.86.0,視覺 BC)— 連帶修「選取項 hover 被通用 hover 規則壓成低對比黑字」
  • 🚀 內建文案多語言化(#261,0.88.0)— 新增 sw-i18n 內建文案字典 + useSwText,19 個元件的內建文案 / aria-label 全量接入(此前硬編碼中文,非中文站露餡)
  • 🚀 @swift-web/framework/store 子路徑匯出(0.90.0)— 讓「同名覆寫」的擴充模板真正成立:業務 store 與 framework store 同名時,唯有顯式 import 才拿得到 base,否則指向自己形成無限遞迴
  • 🐛 ISR 在自架 node-server 上完全不快取(#267,0.92.0,本月最重要的修復)— nitro core 只規範化 swr、不消費 isr(僅 vercel / netlify / zeabur 三個平台 preset 認它),自架上寫了 isr 等於零快取、每請求全量 SSR。改為建置期把 isr 翻譯成等價 cache 鍵並存(平台走 CDN、自架走伺服端快取,兩邊都對);同時把快取掛上有界 LRU(1000 條 / 50MB / 單條 2MB),把「隨機 query 撐爆行程記憶體」從 OOM 降級為命中率下降。業務側寫法不變,仍只寫 isr
  • 🚀 渲染策略建置期護欄四連(0.89–0.95)— 這類失效的共同點是 lint / typecheck / build 全綠、頁面看著也正常,只有 curl 產物才看得出,故一律做成建置期硬校驗並給可貼上的修法片段:#262(通配規則把渲染語意補進父路徑,0.89.0;0.89.1 修三處判據缺陷、0.89.2 排除 Nuxt 內部路由)/ #274(fs 快取驅動 × 父子路徑同時可快取 ⇒ ENOTDIR,0.93.0)/ #276(路徑含 ≥2 動態段時頁面級 defineRouteRules 被 Nuxt 整條丟棄,0.94.0)/ #279(可選段頁面的零段父路徑拿不到快取包裹,0.95.0)
  • 🚀 可快取頁禁讀 query(#271 配套)— 新增 eslint no-query-in-cacheable-ssr(error)+ no-ineffective-route-rules;護欄 L5 攔「可快取頁 SSR 攜帶使用者狀態」;dev 期大回應告警在根因處報出「哪個介面多大 / 多少條」。配合反向代理層 path-only cache key,快取爆炸由「止血」轉為根治
  • 🐛 被快取的頁面 canonical 退化成 localhost(#278,0.95.0)— cachedEventHandler 進 handler 前只保留 cache.varies 白名單裡的請求標頭,Host 被丟掉 ⇒ useRequestURL().origin 落到 http://localhost,canonical / og:url 全錯,且只有「被快取過的」頁面才錯
  • ⚠️ 移除全域觸控最小高度,改 sw-hit-area opt-in(#265,0.93.0,視覺 BC)— 原先給所有 a / button 加 min-height: 44px,落地一年累積 38 處繞行。調研 13 個主流函式庫的發布態 CSS:這種 blanket 規則零例;規範約束的是熱區而非視覺盒、合規線是 AA 的 24px 而非 AAA 的 44px、inline 文字連結明文豁免——三層全反了。改為偽元素擴熱區,視覺不變
  • 🔧 其它 — WebSDK vendored 升 v1.1.7(#280,新增四類硬體資訊事件自動採集;facade 12 個方法 + 28 個事件契約不變);播放器 autoplay 預設關閉 + 尊重 prop + 靜音降級,連帶補「在播但封面還蓋著」的兜底自癒(#281);useLocal / useSession 泛型不再塌成 unknown

starter

  • 🐛 中轉頁 DOM XSS 加固 — ?url= 跳轉補 http / https scheme 白名單(連帶沉澱 standards 通用規則)
  • 🚀 theme.mode 適配 + SwLangSwitch 接入 + Cursor 開箱配置 — swift.config 單旋鈕 + 頂欄改 framework 內建切換器;.cursor/mcp.json 入庫
  • 🚀 電影三件套 demo 全量落地(#48–#51,0.26–0.28)— /movie 樓層 / 列表 / 詳情參考實現:版式三旋鈕 + 全版式插位廣告 + 卡片資訊層 v2 + 選集面板 + 彈幕全鏈路 + 前貼片廣告示範(play_ads → SwAdPreroll 歸一)
  • 🚀 通用站點頁腳模板(#52,0.29.x)— 資料驅動 AppFooter(品牌區 / 連結組 / 圓形圖示連結 / 友鏈可選模組,5 常量改資料不動佈局)+ (footer) 分組路由 6 個靜態頁(about / contact / ads / terms / privacy / faq,prerender)+ 頂部導航字體層級與啟用態優化 + 閃電新 logo 統一
  • 🔄 審計修復批(0.26.1)— 登入方式切換遷 SwSegmented + 站內回跳守衛收斂 framework safeInternalPath
  • 🚀 合規占位頁補齊(0.30.0)— (footer) 新增 18 U.S.C. § 2257 合規聲明與濫用報告(DMCA)兩個結構占位頁(noindex + prerender),頁腳「政策」組註釋連結解開即用,面向成人內容站合規標配
  • 🚀 卡片 hover 放大預覽(Refs fw#253,0.30.3)— 熱播推薦樓層切 16/9 橫版 + MovieHoverPreview 浮層 + MovieCard / MovieFloor 的 preview prop(預設開);機制層隨後上收 framework,starter 刪本地副本改引 useHoverPreview / computePreviewBox
  • 🔄 稽核修復批(0.31.0)— deploy 不再沖掉伺服器上手填的 .env;佔位符網域歸位;noindex 頁排除出 sitemap;TabBar 死連結預設值;error-report 端點挪出 /api/(避開專案自身的代理遮蔽);留言發布框頭像改 onMounted 回填以消 ISR 頁 hydration mismatch
  • 🐛 擴充 store 模板修法(0.32.0,配套 fw 0.90.0)— 改用顯式 import 從 @swift-web/framework/store 拿 base,修「同名覆寫時 base 指向自己」
  • 🔄 排序參數 query → path 段(#271 範式落地)— movie/list/[id]/[[order]].vue + 邊界校驗;連帶補 nuxt.config routeRules 兜底(該頁 defineRouteRules 被 Nuxt 靜默丟棄,即 fw#276 的形狀)

cli

  • 🐛 Windows 必現失敗修復(#31)— spawnSync 補 shell,修 sw create / run 在 Windows 必現失敗
  • 🐛 升級與逾時誤報修復 — sw upgrade 補 --latest 修 0.x 跨 minor 假成功;npm pack 逾時誤報修正 + 上限 300s(#36)
  • 🚀 sw_project_apis MCP 工具(#40)— 解析 applier app/api 生成物,AI 直接查後端介面清單
  • 🔄 配置聯動 BC 批(0.15.2 – 0.16.1)— framework.sitemap 遷 framework.seo.sitemap;sw add page 模板 TDK 引導升級(中文口徑註釋 + TODO 佔位,0.16.0);schema 移除 tracker.autoPageClick(隨 fw#228,0.16.1)
  • 🐛 修復批(0.15.x)— sw info 缺欄位崩潰 / config set 校驗殘口 / 損壞 swift.config.json 走 CONFIG_PARSE_FAILED 錯誤碼
  • 🐛 輸入白名單加固(#45,0.16.2)— sw add / sw config 攔原型鏈鍵 / 非法識別字 / 路徑穿越 / 原型污染。⚠️ 首版正則誤傷了 Nuxt 動態路由段 [id] / [...slug](自造回歸,0.16.3 放行)
  • 🔄 --text 模式兌現「純文字」承諾(0.16.2)— 統一剝 ANSI 逸出序列;連帶修 KNOWN_DESCRIPTIONS 跨倉漂移 + sw info 的 framework 版本讀取口徑對齊 version-check

standards

  • 🚀 v0.4.x 規則增補 — 「使用者可控跳轉必過 scheme 白名單」/ SOP「issue 已存在→認領」/ no-hardcode 引入期姿勢 / --brand-* 業務 token 命名空間 / mocking 雙端化
  • 🚀 v0.4.3 TDK 治理 — 新增 eslint 規則 seo-tdk-length(warn 級字面量預檢)+ 「TDK 長度寫時就寫足」規則節(顯示寬度口徑)
  • 🔄 元件規則同步批 — SwTable / SwSelect searchable·creatable(SEL-003)/ sw-hit-area 緊湊控件 opt-out(含 chips/tab 正當場景界定)/ userStore 寫狀態清單補 register / 深色站 shadow 覆蓋與 currentColor 圖示著色 / SwInput 與 --control-* 表單控件族入元件優先表 / SVF-006 下拉刷新受控收尾
  • 🔄 渲染策略規則大改(v0.4.4 及以後)— 新增「可快取頁 SSR 禁讀 query」硬規則 + path 化的四個結構性前置條件 + 「觸控目標約束熱區不約束視覺尺寸」整節改寫(含 13 函式庫調研結論);訂正零段父路徑的根因表述——nitro 裡 routeRules 比對器與 h3 handler 路由器對 /P 是否命中 /P/** 行為相反,原文只寫了一半

docs

  • 🚀 demo props 覆蓋率閉環(#84)— 覆蓋率規則落地 + 四批缺口回填收官,終值 278/278 = 100%
  • 🚀 「設計體系」欄目上線(#85 – #88)— 三語 7 篇(設計語言 / Figma 工作流 / Claude Design 上手 / 協作 / 治理),Figma 與 Claude Design 雙軌等重;「認識 Open Design」接入本地 agent 設計系統 bundle;設計卡片總覽頁 20 張實卡 iframe 預覽 + 雙資源包下載
  • 🚀 部署文件補影片轉碼契約 — HEVC 必配 H.264 雙 codec 變體(mermaid 選檔流程圖 + 單 URL 前端契約 + 雙獨立 URL 反模式 + AV1 演進預告)
  • 🐛 修復 39 條失效的同頁錨點(#90,佔全站 113 條的 34%)— 根因是 heading id 由 @nuxtjs/mdc 產生,規則反直覺(吞 .、連續 - 摺疊成一個、數字開頭補 _);連帶新增 docs-anchors.spec.ts 全量校驗並對複刻演算法本身鎖了 8 條實測值
  • 🐛 修 6 組文件事實錯 + 新增表格結構護欄(稽核 07-28)
  • 🚀 新增「自架下 isr 如何真正生效」(三語)— 配套 fw#267,並修正原文對快取位置的描述

跨倉事件

  • 🔧 連續審計週期(07-02/03/04 三連 + 07-07/08 兩連 + 07-13 深審)— swift-web-audit 多輪批量修復,07-13 批疊加 TDK 治理四路聯動(framework lint + cli 模板 + standards 規則 + docs),發版鏈貫穿 framework 0.62–0.69 / cli 0.13–0.16 / starter 0.24–0.26 / standards 0.4.1–0.4.3
  • 🔧 設計體系雙軌管線(07-09 – 07-17)— framework scripts/design 流水線(ds-build 原始碼派生 20 卡 + brand-inject 品牌注入 + od-build Open Design bundle)→ Claude Design 底版 / yc001 品牌雙專案 + docs 站資源包與實卡預覽,全鏈單一事實源 = framework 原始碼
  • 🔧 ISR 快取正確性戰役(07-29 – 07-31,framework 0.89 → 0.95 + starter + standards + docs + 8 個下游站)— 由「反向代理層要不要做 HTML 快取」一路挖出五個全綠卻靜默失效的渲染策略坑,逐個補建置期護欄、改規則主源與三語文件、並把 8 個消費方全部升上來。教訓沉澱成一條判據:「站不慢」不能作為「快取規則生效了」的證據——反向代理層的固定 TTL 會掩蓋應用層的漏配,判據只能是產物 curl 出來的回應標頭
  • 🔧 設計體系派生改原始碼直讀(fw#257)— ds-build 的元件卡 CSS 從各 .vue 的 <style> 區塊直讀,消除手抄快照漂移

2026-06

framework v0.16.1 → v0.58.1(42 個 minor + 20 個 patch)· cli v0.5.6 → v0.10.0 · standards v0.2.0 → v0.3.2 · starter v0.14.4 → v0.21.0

元件大爆發月:廣告元件家族(12 個 SwAd*)+ WebSDK 埋點底座、輪播 / 橫排 / 影片流 / 網格元件族(徹底去 swiper)、播放器廣告與付費牆、SwEditor 富文字,疊加 module setup 分層重構、設定體系整改、pnpm 11+ 全生態閘門、obfuscate CSR 裸樣式根治等跨倉事件。

framework

  • 🚀 廣告元件家族 + 統一埋點底座(epic #94)
    • 全月落地 12 個自渲染廣告元件:圖片類 SwAdBanner / SwAdMrec / SwAdIcon、文字卡片類 SwAdText / SwAdMarquee / SwAdNative、彈窗 / 懸浮類 SwAdSplash / SwAdPopup / SwAdFloating、播放器位 SwAdPreroll(前貼片,play_ads 協議歸一)/ SwAdPause(暫停廣告)、合規角標 SwAdLabel,內建曝光 + 點擊埋點;圖片廣告可選文案 + CTA overlay
    • 集團 WebSDK 上報底座:useTracker(28 個 WebSdkEvent)/ useAdTrack(廣告欄位自動組裝)/ useAdFrequency(頻控走加密快取)+ tracker.client 外掛(懶載入 / 自動 pageView / 設定缺失靜默降級)
    • :track 元件內建埋點(SwLink / SwButton / SwCarousel / 播放器,#123)+ 通用曝光 useExposure
  • 🚀 輪播 / 橫排 / 影片流 / 網格元件族(#106)— SwRail(原生橫滾 + scroll-snap)/ SwCarousel(transform 翻頁 + 無縫 loop + autoplay + dots / 縮圖指示器)/ SwVideoFeed(抖音式直划短影片流,裸 hls 影片池 + 虛擬化)/ SwGallery(響應式網格 + 載入更多)/ SwPagination(頁碼翻頁,starter 向上歸併)
  • 🚀 播放器廣告 + 付費牆 + 彈幕 — SwVideoFeed 資訊流廣告條 + 入口貼片(強制觀看 prerollAdForceWatch,#179);SwVideoPlayer / SwVideoFeed 試看牆 paywall(#174)+ 重看試看片段 replayPreview(#186);SwVideoPlayer 內建彈幕 danmaku(條件懶載入 + 主色 token)
  • 🚀 SwEditor 富文字(#187)— 保留 Tiptap 內核重寫封裝:v-model / @提及 #話題 / 內建 emoji 面板 / 圖影片上傳(emit-to-business)/ 配菜式工具列 / token 化預設皮膚
  • 🚀 新元件與皮膚上移 — SwSegmented / SwSelect(平鋪單選 / 下拉選擇)、SwBreadcrumb(headless 麵包屑 + BreadcrumbList JSON-LD);modal / toast 預設皮膚 token 化上移進 framework(#173),applier 刪副本即得
  • 🚀 registerApiMock dev 期請求 mock 層(#188)— 明文層宣告式攔截(dev-only + client-only + prod DCE 刪淨)+ 內建 login / system-info 預設;build 產出 framework-api.json(四層 API JSDoc 資料源,cli MCP 消費)
  • 🔄 module.ts setup 分層重構(#99)— 抽 setup/ 七層(types / defaults / resolve-options / diagnostics / register-config / register-runtime / configure-build),module.ts 收斂為薄編排 + 裝配快照護欄測試
  • ⚠️ BC 集 — userStore login() → autoLogin() + 新增公開 loginByDevice();useLoginDialog 的 show → open;SwAdSide → SwAdFloating 改名;廣告彈窗按場景拆分 SwAdSplash / SwAdPopup;player API 命名對齊 HTML / 業界慣例
  • 🐛 obfuscate 破壞 CSR CSS preload 根治(#169)— 生產混淆吞 Vite css preload url 致 SPA 導航整頁裸樣式,0.39.4 關 stringArray + 預設關 inlineStyles(框架級修復,升級即得)
  • 🐛 SSR / 安全修復批 — deviceId 改 secure-context 安全的 randomUuid()(修非 HTTPS / LAN HTTP 500);useSeo prerender 頁 origin 回退 NUXT_PUBLIC_SITE_URL(#117,修 OG / canonical 烤成 localhost);cacheAesKey 長度 / auth cookie 名建置期 fail-fast

starter

  • 🔄 廣告體系換血 — 徹底去 swiper,自建廣告元件全刪改用 framework SwAd* 元件族;開屏廣告遷 SwAdSplash(system/info.layers 驅動)
  • 🚀 登入與能力上移收編 — yc001 登入元件 UI / 結構回灌(LoginForm + login.vue);modal / toast 皮膚副本刪除走 framework 內建;PaginationBar 退役歸併 SwPagination
  • 🐛 sitemap 收斂 framework 內建 — 刪自建 sitemap 管線(根除自寫檔案服務路由的路徑穿越隱患),統一走 framework 的 @nuxtjs/sitemap
  • 🔧 CI / 部署 / mock 工程化 — verify 門禁 job(type-check + lint)+ CI 改 pnpm;deploy/ 運維三件套 + pnpm deploy:prod(獨立目錄 build、rsync 不帶 --delete,根治首屏裸樣式視窗);內建業務 dev mock 預設(movie / search 整套)

standards

  • 🔄 rules 單一事實源重構 — 拆單檔案為 rules/ 多主源 + 雙裝配清單(_claude / _mr),下游 CLAUDE.md 瘦身職責分離
  • 🚀 stylelint no-hardcode 強制(#17)— color 類屬性禁 hex 字面量(error 級)+ Tailwind at-rule / 函數白名單
  • 🚀 統一開發流程 SOP + applier CI/CD + 部署規範 — issue-dev-sop 主源落地(issue 即方案 / 按 task 原子提交 / 自測留證),治理類 wiki 全棄;applier MR 門禁工作流 + 長期分支同步紀律 + 測試 / 生產部署規則
  • 🚀 usage-review-rules 大擴充 + 互動體驗規範 — 收編 utils / store / composable 層 20+ 條編號規則(CACHE / REQ / AES / DB / STORE 等);新增前端快取加密 util / 廣告位與打點 / dev mock 護欄 / 文件中等資訊密度等規則;互動與體驗規範 UX-001~010(#25)

cli

  • 🚀 theme applier + MCP 富文件 — theme feature applier(#20,theme.enabled 自動 toggle 暗色 marker 塊);sw_framework_docs 讀 framework-api.json(四層 API + gotcha 關聯 + 框架設定層)
  • 🚀 create / config 能力補全 — sw create 詢問啟用 dev mock(選否刪預設);sw config + MCP 全量覆蓋 swiftConfig + auth 危險項二次確認;applier 建立補 pnpm 11 守衛 + 生成 .npmrc

docs

  • 🚀 元件族三語文件批量新增 — 輪播族(SwRail / SwCarousel / SwVideoFeed)三語 + DemoBox;「廣告底座與打點」指南三語
  • 🚀 llms.txt / llms-full.txt 建置期生成(AI 友好文件入口)

跨倉事件

  • 🔧 pnpm 11+ 全生態統一閘門 — 各倉 engines.pnpm ">=11" 下限、去 corepack / packageManager 釘死、pnpm 欄位遷 pnpm-workspace.yaml、CI 改裝 pnpm@11
  • 🔧 release 鏈路安全化 — 4 發版倉統一 npm version(pnpm version 忽略 tag prefix 的坑)+ release 閘門加 typecheck 硬門 + release script 安全載入 .env(杜絕 secrets 打到 stdout)+ 刪各倉 .env 收斂 ~/.zshrc 單一憑證源
  • 🔧 設定體系整改(framework#164)— 專案常量進 nuxt.config、.env 只留環境相關、執行時零必填 env(根除 cluster 非主實例設定為空的雷),framework / starter / standards 聯動落地
  • 🔧 測試大補齊 — framework e2e 夾具場景數門檻入規 + 全元件夾具擴充(#143–156 群,e2e 240 全綠);starter 頁面 smoke 消覆蓋率 0/0 盲區;cli 參數組合 + 邊界測試

2026-05

framework v0.7.0 → v0.16.0(9 個 minor + 數十 patch) · cli v0.2.7 → v0.5.1 · standards 首發 v0.0.1 → v0.1.3 · starter 首發 v0.14.0

5 倉體系(framework + starter + standards + cli + docs)成型並加速迭代的關鍵月,覆蓋 ISR 安全增強、Cookie 加密、SEO 鏈路收歸、SwButton 回歸 vue idiom、verdaccio 私服上線、starter / standards 首次發 npm 套件等多個跨倉事件。

framework

  • ⚠️ useSeo 單一入口 + 修 <title> 重複(v0.16.0 BC,refs framework#89)
    • 刪 system.client 鏈:舊版 hydration 後用後端 header 呼叫 useSeoMeta 覆蓋頁面 title/description,導致 <title> 重複成 站點名 | 站點名 + description 被後端值蓋掉
    • SEO 全顯式單一入口:useSeo 不再從後端 systemStore.header 兜底 title/description/keywords/og_image(缺失改 dev console.warn,不靜默兜底)
    • titleTemplate 交還 Nuxt 原生:移除 ModuleOptions.head.titleTemplate + useSeo 的 disableTitleTemplate 入參;applier 改在 nuxt.config.ts 的 app.head.titleTemplate 配站點名後綴(源自 swift.config.json 的 project.title)
    • JSON-LD WebSite.name 取 runtimeConfig.public.siteName,不再讀後端 site_title;og:image 兜底僅本地 /og-image.png
    • 升級 applier 須:每頁顯式傳 title/description + nuxt.config.ts 配 app.head.titleTemplate + runtimeConfig.public.siteName
  • 🚀 sitemap.xml 精細化 + i18n strategy 檢測(refs framework#85,配套 #87)
    • GAP1:sitemap siteUrl 由 NUXT_PUBLIC_SITE_URL 鎖定,跟 useSeo runtime origin 解耦(sitemap 是搜尋引擎目錄,必須穩定主網域;canonical 跟使用者存取網域一致)
    • NUXT_PUBLIC_SITE_URL host 格式校驗:合法 URL + http/https 協定 + 純 origin(不帶 path/query/hash)。dev console.warn / build console.error,不阻斷 build。能攔下漏協定(example.com)/ 佔位符(<your-domain>)/ 錯協定(ftp://)/ 帶 path(https://x.com/api)等髒資料
    • GAP2 簡化版:檢測 @nuxtjs/i18n strategy === 'no_prefix' → dev console.warn 引導改 prefix* strategy(hreflang 互鏈自動設定由 framework#88 跟蹤)
    • GAP3 預設 exclude 私有路徑:sitemap 預設排除 /login、/register、/mine/**、/profile/**、/admin/**、/dashboard/** 等通用私有路徑,避免跟 useSeo({ robots: 'private' }) 自相矛盾
    • 新增 ModuleOptions.sitemap.exclude?: string[] 讓 applier 追加業務自訂私有路徑(與 framework 預設合併,不是取代)
    • 新增 docs:sitemap 設定 / NUXT_PUBLIC_SITE_URL 設定 / ModuleOptions.sitemap
  • ♻️ useSeo origin 兜底鏈簡化為單一事實源 + CSR 一致性診斷(refs framework#87)
    • 4 層兜底(L1 explicit → L2 systemStore.info.site_url → L3 runtimeConfig.public.siteUrl → L4 useRequestURL().origin)→ 1 個事實源 + 1 個顯式逃生口
    • 主路徑:useRequestURL().origin(SSR Node 端從 Host/X-Forwarded-* 解析 / CSR window.location.origin)
    • L1 explicit input.siteUrl 保留為「顯式逃生口」(多副網域想強制 canonical 收斂到主網域時用)
    • CSR hydration 階段一次性比對 <link rel="canonical"> 與 window.location.origin,不一致 = nginx 透傳設定錯 → dev console.warn / prod console.error + 修復指引 + docs URL(nginx origin 透傳設定)
    • SystemInfo.site_url 欄位保留供業務讀取(如「最新地址」跳轉連結),不再參與 SEO origin 決策
    • NUXT_PUBLIC_SITE_URL 僅 build-time 用(prerender / sitemap)
    • 行為變化但 API 簽名不變 —— 舊依賴 L2/L3 兜底的專案需確認 nginx 透傳 Host / X-Forwarded-Host / X-Forwarded-Proto,否則 canonical 會拿到內網位址(診斷 console 會立刻報警)
  • 🔧 publishConfig 切 verdaccio(v0.14.0 / v0.14.1,refs framework#77 / #78 / #79)
    • framework 切自託管 verdaccio 私服(npm.djatm.cloud),下游 applier 裝套件不再經 GitLab npm registry
    • prepublishOnly 鉤子在發版時從 publish manifest 剝離 scripts.preinstall,避免消費方 install 時誤觸發 pnpm 檢查腳本
    • workspace 設定 @swift-web/standards: false 防 consumer 跑 standards 的 preinstall
  • ⚠️ defineRouteRules 硬校驗 + 刪預設 error.vue(v0.13.0 雙 BC,refs framework#71)
    • applier 須顯式開啟 experimental.inlineRouteRules,未開啟時 framework 模組 setup 階段直接報錯
    • 此前是 silent no-op:applier 寫了 defineRouteRules 但實際無效,ISR / SSR 行為切換會暴露既有問題
    • 刪 framework 預設 error.vue,errorComponent 完全交 applier 自訂
    • framework 內部 createError 直接拋錯,不再 fallback 渲染兜底頁
  • 🐛 SSR / 錯誤處理強化(v0.12.7 ~ v0.13.0 系列)
    • SystemInfo onError 預設改為 fail-fast throw,刪 SSR 階段 deviceId guard 讓 onError='throw' 真實生效
    • createError 改用 error.data: { source, title, cause } 結構化攜帶診斷資訊,不再靠 message 字串拼接
    • SSR 期空 apiBase fail-fast 明確報錯,不再 silent 跳過
    • SSR 期 deviceId 用固定值 'node'(後端約定),跟客戶端邏輯解耦
    • SSR error.vue 渲染時 client 不再後台拉 systemInfo + title 含完整 API 路徑
    • 整體讓 SSR 失敗立刻可見,不再累積隱性損壞
  • ⚠️ SwButton API 重設計(v0.12.0 BC,refs framework#56 / #57)
    • 自 v0.6.0 起 SwButton 使用 onTap callback prop + 100ms 內建節流 + 主動 filter onClick,反 vue idiom + 反業界慣例(el-button / antd / mui / reka-ui 都不做內建節流,全部 emit @click)
    • 刪 onTap callback prop,改用標準 @click event:<SwButton :on-tap="fn"> → <SwButton @click="fn">
    • 刪 wait prop + 100ms 內建節流,async 期間防 double-submit 改由父元件管 :loading 狀態機
    • 刪 inheritAttrs:false,vue 標準透傳,class / style / aria-* 自動透傳到原生 <button>
    • 新增 nativeType: 'button'|'submit'|'reset'(form submit 必備)/ autofocus / icon(左側圖示 Vue 元件,loading 時被 spinner 替換)
    • 新增預設 loading spinner::loading="true" 沒傳 #loading slot 時自動渲染(約 10 行 CSS,1em + currentColor 自適配按鈕文字大小顏色)
    • 配合 standards mr-review SB-001(@click 綁 async handler 必須傳 :loading)+ SB-002(form submit 必須傳 native-type="submit")兜底
  • 🚀 測試基礎設施(v0.12.7 ~ v0.12.12 系列)
    • 接入 vitest coverage(v8 provider + json-summary reporter)
    • 重寫 SwButton e2e 覆蓋 disabled / loading / type / icon 主要 props
    • utils/debug-log.ts 單測覆蓋率 0 → 89.47%
    • framework e2e gotoPage helper 繞開 @nuxt/test-utils createPage hydration 時序問題
  • 🔧 release 流程 + 工程基礎設施(v0.12.0+)
    • release script 拆三:release:patch / release:minor / release:major,裸 release 報錯強制選版本(防 v0.12.0 BC 誤發 patch 教訓)
    • release script 顯式傳 --tag-version-prefix=fw/v,繞開 pnpm 不讀 .npmrc 的 bug
    • 鎖 packageManager pnpm@11.0.8
    • playground devServer 連接埠 3500 → 3000(monorepo 連接埠統一)+ host env-aware
  • 🐛 業務元件小修復(v0.12.x patches)
    • SwQrcodeScanner 加 decode timeout 兜底,修非二維碼圖永掛 loading 真實使用者 bug
    • upload-chunk 空檔(size <= 0)silent skip + 無任何回呼,致消費方 pending 永鎖(refs framework#60)
    • SwImage URL.createObjectURL 記憶體洩漏(refs framework#61,已含在 SwImage 重構)
    • SwTiptapEditor template 內聯 type cast as 在下游 applier rollup 解析失敗 → 移到 script setup computed
  • ⚠️ framework 接管 head 元素(v0.10.0 / v0.11.0 BC,refs framework#51)
    • <html> htmlAttrs 收歸 framework(v0.11.0):lang 單一事實源 framework.i18n.defaultLocale;data-build-id / data-build-time 按 CI_COMMIT_SHORT_SHA → VERCEL_GIT_COMMIT_SHA → GITHUB_SHA → 'local' 優先序讀環境變數
    • i18n plugin 自動注入 <html lang>(refs framework#51),替代 starter 在 nuxt.config.app.head.htmlAttrs.lang 寫死
    • <title> titleTemplate 收歸 framework(v0.10.0):預設 '%s | %site_title',%site_title runtime 替換為後端 system.info.header.site_title
    • useSeo 取消 site_title 當 title 兜底,避免與 titleTemplate 疊加產出 siteTitle | siteTitle 的首頁重複 bug
    • useSeo({ disableTitleTemplate: true }) 單頁關閉 titleTemplate 注入(適行銷落地頁 / 錯誤頁 / 全螢幕專題頁)
    • 新增 eslint 規則 swift-web/require-useSeo-in-pages:app/pages/**/*.vue 必須顯式呼叫 useSeo,阻斷 AI / 開發者漏寫
    • applier 的 app.head.htmlAttrs 整塊 + 頂部 buildId / buildTime 常數都可刪
  • ⚠️ Cookie / 登入態 / 裝置認證安全加固(v0.9.0 BC,refs framework#48 / #45)
    • AccountInfo 從 cookie 搬到 localStorage(加密),密碼不再隨每個 HTTP 請求飛到 header,DevTools Cookies 面板不再可見明文 JSON
    • 🔴 修復「記住我」被繞過的隱私 bug:0.8.x 起 framework 在 loginByUsername / loginByQrcode 內部總是無條件呼叫 setAccount 寫 cookie 30 天,無視消費方「記住我」意圖;0.9.0 透過 options.remember 讓使用者意圖真正生效
    • AccountInfo 介面新增必填 remember: boolean 欄位;loginByUsername / loginByQrcode 簽名 extra?: Record → options?: { remember?, extra? },remember 預設 true 保持相容
    • 核心 cookie(token / deviceId / channel_code / share_code)全部 AES-CBC 加密 + 預設 secure: true(localhost / 127.0.0.1 瀏覽器自動豁免)
    • 新增 userStore.clearAccount() action(單獨清 AccountInfo 不動 tokenInfo)+ useTheme.setTheme(theme) action
    • useCookie wrapper 擴展支援 maxAge / sameSite / secure / path / domain / default / watch;解密失敗自動 fallback 相容舊明文 cookie
    • 新增 eslint no-direct-cookie-in-app 規則編譯期攔截 app/ 下直讀寫敏感 cookie
  • 🚀 ISR 安全增強 + path-aware lint plugin(v0.8.0 BC,refs framework#44)
    • 針對 ISR 路徑上的「裝置 token 透過 Pinia payload 烤進快取」等使用者態洩漏隱患做系統性重構
    • device + auth 身份從 SSR 期完全挪到 client hydrate 後建立,新增 auth.client.ts plugin 作為唯一建立點
    • system.server.ts 簡化:刪 SSR 期 userStore.login() + 內建 IGNORE_PATHS,保留 systemInfo 拉取 + initCode
    • useAuthReady composable 讓業務 request() 透明等到 auth.client 完成
    • framework module.ts 自動注入 experimental.inlineRouteRules: true 讓 page 級 defineRouteRules 真正生效
    • 新增 @swift-web/framework/eslint subpath export,3 條規則:require-define-route-rules / no-isr-on-paid-paths / no-isr-on-user-state-paths
    • 0.8.1 path-pattern 改 segment 級匹配,覆蓋巢狀路由;0.8.2 規則 options 支援自訂 segments;0.8.3 ModuleOptions.auth 擴展 boolean | AuthOptions 支援 auth: false 關掉整套 client auth init
    • BC:systemInfoIgnorePaths: string[] 刪除,改 systemInfo: boolean | { enabled?, endpoint?, ignorePaths? };遷移範例 ['/'] → false,['/p'] → { ignorePaths: ['/p'] }
  • 🔄 SwImage / SwAsyncText 重構(v0.7.x ~ v0.8.x BC,refs framework#34 / #35 / #61)
    • 移除 @nuxt/image 依賴,新引入外連圖 provider 抽象
    • SwDecodeImage 刪除,其加密能力收納進 SwImage 統一圖片入口(清理 .cursor-scale / .cursor-scale-av 業務專屬樣式)
    • SwDecodeText 改名 SwAsyncText,並切到 useDecryptedAsset composable(依賴 #34)
    • fix URL.createObjectURL 沒對應 revokeObjectURL,加密圖片列表場景記憶體洩漏(#61)
    • SwImage 能力補齊:外層 click 事件(覆蓋 overlay)、title prop(hover tooltip / SEO)、placeholder 擴展 string | { dark, light } | false、#placeholder slot、@load / @error 透傳、hover-zoom class
  • 🚀 PWA SW 設定改業界主流(v0.7.7,refs framework#43)
    • skipWaiting: true(新 SW 立即啟用,不等所有 tab 關閉)
    • clientsClaim: true(新 SW 接管所有 client)
    • 圖片 runtime caching 改為 StaleWhileRevalidate 策略(先返快取 + 後台更新)
    • 對齊 Workbox 推薦 + el-ui / antd-pro 等業界 PWA 預設行為
  • 🚀 useSeo 長度閾值改用顯示寬度演算法(v0.7.5,refs framework#39)
    • 原 validateSeoLengths 用 JS .length(UTF-16 code units)對 ASCII / CJK 一視同仁
    • 但 50-160 字元閾值按 Google SERP 英文字元寬度標準設計,CJK 在 SERP 視覺寬度約英文 2 倍
    • 引入 displayWidth 函式(CJK Unified Ideographs / Extension A-H / 全角符號 / CJK 標點算 2,ASCII 算 1)
    • title / description 走 displayWidth;keywords 檢查數量和總長度保持 .length
    • 閾值數字(10/60/70 / 50/160/200)不變,單位含義升級為「顯示寬度」
  • 🔄 codegen 抽離到 framework(v0.7.0)
    • 把 starter 的 optimize-images / generate-icons / check-og-image 等建置腳本抽到 @swift-web/framework/codegen 子模組
    • 下游 scripts/*.ts 退化為一行薄封裝(import + 呼叫)
    • 核心邏輯跟隨 pnpm update @swift-web/framework 升級,applier 不再需要「複製 starter 腳本到自己專案」的舊維護模式
    • framework 提供純函式 + 回呼介面(如 generateIcons 的 onFaviconConflict callback),終端互動留在呼叫方
    • starter 五個腳本完成遷移

starter

  • ⚠️ 適配 framework#89 SEO 單一入口(v0.14.2)
    • nuxt.config.ts 改用 Nuxt 原生 app.head.titleTemplate: \%s | ${swiftConfig.project.title}`+runtimeConfig.public.siteName(站點名源自 swift.config.json的project.title`,單一事實源)
    • 同步帶 starter#24 修復:.npmignore 排除發包專用 template-integrity.spec.ts,防洩漏到 sw create 派生的 applier
  • 🚀 首發 npm 套件(v0.14.0)
    • starter 此前是 git-only template(cli 用 SSH git clone 拉範本),不發 npm
    • v0.14.0 起作 npm 套件發版,給 cli 用 npm pack 取(配合 cli 0.5.0)
    • prepack / postpack 鉤子處理 publish manifest:reset version 0.0.0、設 private:true、去 publishConfig / release scripts
    • 保證發出來的套件是「新專案」範本狀態而非業務實例
  • 🔧 publishConfig 切 verdaccio + 升下游依賴
    • 升 framework ^0.14.0 + standards ^0.1.1
    • .npmrc 切 verdaccio
    • 鎖定 Vue 全家桶單版本修復生產建置 SSR 500
    • patch vue-router 5.0.7 修復 @nuxt/test-utils 下的 TypeError
  • 🔧 加 pnpm 11+ preinstall 阻塞
    • check-pnpm.mjs 在 preinstall 階段校驗 process.env.npm_config_user_agent
    • 未達 pnpm 11 / 用 npm / 用 yarn 立即 exit 1 + 中文引導
  • 🔧 systemInfo onError 改 throw + nuxt-config 適配 fw 0.13
    • 跟 framework fail-fast 策略對齊
    • 開啟 experimental.inlineRouteRules 配合 fw v0.13.0 硬校驗
    • 升 framework 0.13.0
  • 🚀 error.vue dev 詳情結構化(配合 fw v0.12.9-0.12.11)
    • dev 模式 error.vue 展示 error.message 詳情
    • 改用 error.data 結構化展示替代 message 字串拆分
    • 詳情標題改紅色(不再用前置圓點)
  • 🚀 LoginForm 複用 framework 帳號儲存(配合 fw v0.9.0)
    • 刪 self-maintained useLocal('login-username' / 'login-password' / 'login-remember') 三項
    • 改用 framework userStore.setAccount / getAccountInfo / clearAccount
    • 透過 loginByUsername(u, p, { remember: isRemember.value }) 把「記住我」勾選意圖正確透傳給 framework
  • 🚀 home 首頁重寫 + 視覺元件(v0.7-0.8 期)
    • 重寫首頁 + icons 演示頁
    • 新增 LogoMark / LangSwitch / ThemeSwitch 業務元件
    • 閃電 LOGO 重生成圖示

standards

  • 🚀 首次上線發版 v0.0.1 → v0.1.3(最新一波)
    • v0.1.1:切 verdaccio publishConfig
    • v0.1.2:preinstall 加 cwd-in-node_modules guard(防 consumer install 誤觸發)
    • v0.1.3:prepublishOnly strip preinstall
  • 🔄 目錄重構 common-standards/ → rules/(marker 協議 v1 → v2 BC)
    • 檔名去前綴編號:10-rendering-strategies.md → rendering-strategies.md
    • _order.json sections 結構控制拼接順序(替代靠檔名編號)
    • marker v2 加版本號防回退(v1 BEGIN/END 包夾 → v2 加 <!-- swift-web/standards@version -->)
    • 同步下游 4 倉的字面量引用 common-standards/ → rules/
  • 🚀 component-review-rules 體系(陸續完善)
    • 按元件名縱向組織 mr-review 規則的新章節
    • 首版 SwButton 兩條:SB-001(@click 綁 async handler 必須傳 :loading 狀態機,防 double-submit)+ SB-002(form 內提交按鈕必須傳 native-type="submit")
    • 後續陸續擴展到 18 條,覆蓋 SwImage / SwModal / SwUploadImage / SwTiptapEditor 等元件的常見 review 失誤
    • 後續逐條機械化為 eslint 規則進 @swift-web/standards/eslint
  • 🚀 eslint 規則集演進(v1 → v4 跨期)
    • v4(fw v0.12.x):SwButton SB-001/002 機械化兜底
    • v3(fw v0.10.0):require-useSeo-in-pages
    • v2(fw v0.9.0):no-direct-cookie-in-app
    • v1(fw v0.8.0):require-define-route-rules / no-isr-on-paid-paths / no-isr-on-user-state-paths
    • 三檔分級:必改(block PR) / 重要(討論) / 次要(review 總結)
  • 🚀 客戶端安全主源章節(配合 fw v0.9.0)
    • 5 條 review 規則:cookie secure、敏感欄位禁 cookie、remember 透傳、不繞開 wrapper、加密非安全屏障
    • 客戶端加密安全模型文件化:明確「加密 ≠ 安全屏障」(cacheAesKey / apiKey 在 client bundle 暴露),真正安全依賴 HTTPS + 後端鑑權
    • 三語 /guide/client-encryption-boundary 同步上線
  • 🚀 ISR 安全 mr-review checklist + discuss-rendering v3(配合 fw v0.8.0)
    • 渲染策略 §三 使用者態洩漏(最嚴重風險)專章
    • SWR 降級為 ISR 別名(簡化判斷複雜度)
    • 決策樹補 prerender (SSG) 行
    • rendering-quick-guide 實踐型指南
  • 🚀 standards 倉上線 + npm 套件發版(refs standards#1 / #3 / #4)
    • 抽出 swift-web 通用規範作單一事實源 —— 渲染策略 / SSR 安全 / 公私 API 邊界 / AI 提交標記 / 客戶端安全等規則不再分散在 framework / starter / docs 的 CLAUDE.md
    • 統一在 standards/rules/*.md 維護,_order.json 顯式控制拼接順序
    • pnpm sync 腳本透過 marker 協議把規則段注入下游 4 倉的 CLAUDE.md
    • 作為 npm 套件 @swift-web/standards 發版,對外暴露 /eslint 子路徑
    • 含 navigate-to-must-return(Nuxt navigateTo 不能裸呼)/ root-class-sw-prefix(無 class 自動放過 + 多根獨立判定)等機械化規則
    • /prettier + /stylelint 子路徑讓各倉設定走 import base + spread override 模式

cli

  • 🔧 適配 framework#89(v0.5.5)
    • applyProjectVars 移除 titleTemplate 佔位符替換(starter 改用讀 swift.config.json 的模板字面量,sw create 派生專案天然拿到自己的站點名,無需字串替換)
    • add.test.ts store 演示輸入改 shopping-cart,避開舊 user store 命名觸發 pre-release-doc-check 跨倉字串誤報
  • 🚀 sw create 改 npm pack 模式(v0.5.0,refs framework#79)
    • 此前 sw create 透過 SSH git clone @swift-web/starter 倉拉範本,要求新機器配 GitLab SSH key + 有對應 repo 權限
    • v0.5.0 起改用 npm pack @swift-web/starter 從 verdaccio 拉 tgz 解壓(配合 starter 首次發 npm 套件,見 starter 節)
    • 新機器零 GitLab 依賴:範本每次拉 latest,不再擔心版本滯後
    • applyProjectVars 替換 package.json / nuxt.config.ts / README.md 三處佔位符的邏輯不變
  • 🔧 publishConfig 切 verdaccio + install 腳本刪 AUTH 段(v0.4.0 / v0.5.0)
    • cli 自身發版切到 verdaccio
    • install.sh / install.ps1 刪除 NPM_TOKEN AUTH 段(verdaccio access:$all 後匿名安裝 OK)
  • 🐛 sw info 補 errorHandler 行 + sw run 失敗補 exit(1)(v0.3.x)
    • sw info 輸出補全 errorHandler 設定項展示
    • sw run 子進程失敗時正確傳遞 exit code
  • 🐛 sw add page 預設渲染策略改 ISR(v0.3.x)
    • 預設 ssr: true → isr: 3600,對齊 swift-web「ISR 是主力」的設計初衷
    • 效能優先,必要時再走完整 SSR
  • 🔧 release script 拆三 + 裸 release 報錯(v0.3.1+)
    • 對齊 framework 拆 release:patch / release:minor / release:major,裸 pnpm release 報錯 + 提示三選一
    • 防 BC 改動「按 enter 預設 patch」誤發(framework v0.12.0 已踩坑,cli / standards 同步對齊)
    • release script 顯式傳 --tag-version-prefix=cli/v
  • 🔄 命令層輸出統一走 core/output(v0.3.1)
    • 之前各命令檔零散呼叫 console.log / console.error
    • 統一改 output.success / output.error / output.warn / output.info / output.hint
    • 配合 --text / --json 模式實現 interactive / text / json 三態輸出
    • setNestedValue 泛型化
  • 🚀 接入 ESLint flat config(v0.3.x)
    • 跟 framework / starter / docs 統一 lint 體系
    • 接入 @swift-web/standards/eslint
  • ⚠️ configKey 改名(v0.3.0 BC)
    • swiftWebFramework → swiftConfig,設定項 key 縮短
    • 註解 + 測試 fixture 同步更新
    • 專案範本 nuxt.config.ts / swift.config.json 同步遷移
  • ⚠️ 刪 sw init-mcp 命令(v0.3.0 BC)
    • MCP 設定改為透過文件指導 applier 手工寫 .mcp.json,不再由 cli 命令生成
    • 配合 sw_framework_docs MCP tool 在 cli 內部一站提供

docs

  • 🔧 publishConfig + .npmrc 切 verdaccio
    • 升下游依賴 framework ^0.14.0 / standards ^0.1.1
  • 🔧 加 pnpm 11+ preinstall 阻塞
    • 跟 starter 同款 check-pnpm.mjs
  • 🔧 跟 framework 0.10 / 0.11 / 0.12 / 0.13 BC 同步文件
    • SwButton API 重設計 → seo / 元件文件全面更新
    • titleTemplate / htmlAttrs 接管 → framework/seo 文件章節新增
    • defineRouteRules 硬校驗 / removed default error.vue → routing / error-handling 重寫
    • SystemInfo fail-fast / createError 結構化診斷 → 文件同步更新
    • 7 個元件文件同步 v0.12 API 重設計
  • 🚀 三語 client-encryption-boundary 新增(配合 fw v0.9.0 cookie 安全)
    • 明確「加密 ≠ 安全屏障」
    • cacheAesKey / apiKey 在 client bundle 中暴露,真正安全依賴 HTTPS + 後端鑑權
    • 與 standards 客戶端安全主源章節同步
  • 🚀 docs framework/module-options systemInfo 文件遷移(配合 fw v0.8.0)
    • 舊 systemInfoIgnorePaths 章節替換為新 systemInfo schema 文件 + 遷移說明
    • systemInfo Store 自動初始化章節更新到新 API
    • 簡介示例設定移除 systemInfoIgnorePaths,改 systemInfo
  • 🚀 三語 rendering-quick-guide 新增(配合 fw v0.8.0 ISR 安全)
    • 5 分鐘決策矩陣 + 詳情頁決策樹 + 反模式速查 + 範例代碼 + review checklist
    • 與原 /guide/rendering-strategies(理論篇)並列
    • 讓實踐派開發者快速決策選 ISR / SSR / CSR / SSG

2026-04

framework v0.4.x → v0.6.x · cli v0.2.1 → v0.2.7

SEO 標誌性發布 + 元件大規模重新命名 BC + 業務元件三態 prop 模式統一。

framework

  • 🚀 auth 安全加固(v0.6.5)
    • initCode 渠道碼 URL 注入防護:?switch=1 路徑下從 URL 注入的渠道碼會被中介層拒絕,防惡意連結劫持渠道歸因
    • logout 清理同步:登出時同步清渠道碼 cookie / IDB 解密快取 / 約定登入憑證 localStorage 三處狀態
  • 🚀 useSeo dev 體驗完善(v0.6.1 ~ v0.6.4 系列)
    • v0.6.4:SEO 指南頁從 framework 內部 wiki 遷出到公開 docs 站
    • v0.6.3:警告 console 輸出緊湊化 + 連結到 SEO 知識庫 wiki
    • v0.6.2:dev 長度警告加頁面 URL + 新增 silenceLengthWarnings: true 靜音開關(私有頁 / 工具頁用)
    • v0.6.1:JSON-LD 切換到 @unhead/schema-org/vue 匯入路徑(解決與 nuxt-schema-org 的簽名差異)
  • 🚀 SEO 標誌性發布(v0.6.0)
    • useSeo() composable 一站式 SEO 元資訊:每個 page 一次呼叫自動輸出全套 og:* / twitter:* / canonical / JSON-LD
    • origin 4 層兜底:顯式 → systemStore.info.site_url → runtimeConfig.public.siteUrl → useRequestURL(解決多副域名 + 反代未配齊 X-Forwarded 頭時 canonical 漏內網位址)
    • image 4 層兜底鏈:顯式 → header.og_image → header.img → /og-image.png
    • robots prop:'private' (noindex,nofollow) / 'noindex' (noindex,follow) / 任意原始字串
    • JSON-LD 預設輸出 WebSite + WebPage schema;type:'article' 時加 Article schema
    • 強制啟用 @nuxtjs/sitemap + nuxt-schema-org + @nuxtjs/robots 三子模組(不可關閉,僅 aiBotPolicy 選項控制 GPTBot/ClaudeBot/CCBot/PerplexityBot 等 AI 訓練 bot)
    • SwImage 新增 preload prop 自動注入 <link rel="preload" as="image">,配合 loading="eager" + fetchpriority="high" 用於詳情頁 hero 大圖 LCP 最佳化
    • 後端 system.info.header.og_image 欄位(運營 CMS 上傳 1200×630 PNG/JPG);舊 img 欄位保 0.6.x 相容期 0.7.0 移除
  • 🐛 業務元件多項修復(v0.5 / v0.6)
    • useLoginBy iOS Safari 誤判 WebView:原 /Version\/[\d.]+(?: Chrome\/)?/ 正則 Chrome/ 可選分組導致 iOS Safari Version/X.X Mobile/... 命中後被誤判走 redirect 登入;修復為強制要求字面 <空格>Chrome/
    • SwModal:description 在同時傳入預設 slot 時不渲染(aria-describedby 警告),現在傳入 description 即始終渲染
    • useToast / useModal:crypto.randomUUID 在非 HTTPS 環境(如 http://0.0.0.0)不可用,新增 Date.now + Math.random 降級兜底
    • SwTiptapEditor:移除範本繫結中的 as Editor 類型斷言,修復 vite-plugin-vue-tracer 解析報錯
  • 🚀 SwImage 能力補齊(c-image 遷移缺口,v0.5)
    • 外層 click 事件(覆蓋 overlay 區點擊)
    • title prop(hover tooltip / SEO)
    • placeholder 類型擴展為 string | { dark, light } | false,物件形式走 CSS-only 主題切換
    • placeholderClass prop + 內建最小化佔位兜底樣式
    • #placeholder slot(slot 優先於 prop);@load / @error 事件透傳
    • hover-zoom class(opt-in)+ CSS 變數 --sw-image-hover-zoom-scale
  • 🚀 新增元件(v0.5)
    • SwAddToHomescreenGuide:H5 PWA 加入主畫面引導,從螢幕底部滑入非阻斷式 bottom-sheet,iOS Safari / Android Chromium 各給對應步驟,桌面 / WebView / 區域型瀏覽器靜默不彈;rememberFor prop 支 'session' / 正數 N(N 天內不再彈);CSS 變數 --sw-add-to-homescreen-guide-bg / --sw-add-to-homescreen-guide-radius / --sw-add-to-homescreen-guide-z 自訂
    • SwQrcodeScanner:圖片二維碼識別,含 trigger / preview 插槽 + 完整事件流
    • SwQrcodeGenerator:二維碼生成,自訂尺寸 / 容錯等級 / 前景背景色 + PNG 下載
    • SwFormField 簡單模式:name 可選,新增 required / hint / error prop,作為表單欄位版面容器使用,不依賴 vee-validate
  • 🚀 業務元件「三態 prop」模式統一(v0.5)
    • onRecord / fetchPlayUrl 等 prop 支援三種語意
    • undefined → 走預設 API(SwVideoPlayer 預設 POST /movie/doHistory、SwAudioPlayer 預設 POST /audio/doHistory、SwVideoPreview 預設 POST /movie/play)
    • function → 覆寫預設行為
    • null → 顯式停用
    • 業務方零設定即可運作,需要走自己 API 時傳 function,明確停用傳 null
  • ⚠️ 元件大規模重新命名 + API 重設計(v0.5 BC)
    • SwBtn → SwButton:CSS class sw-btn → sw-button;新增 type 語義類型 prop + loading prop + #loading / #icon / #icon-right 三插槽
    • SwAlink → SwLink:sw-alink → sw-link;安全修復 target="_blank" 自動加 rel="noopener noreferrer",外部連結額外 nofollow
    • SwPlayer → SwVideoPlayer:僅 rename,API 不變
    • SwPlayerAudio → SwAudioPlayer:rename + 完全重寫對齊 SwVideoPlayer。新增 url / type / linkCode v-model / initialSeekTime(替代 seekTime)/ 14 emit / 6 expose(含 switchLink 保留進度),刪 playMode,修「切換線路 N 次 → N 個 timeupdate 監聽堆疊」
    • SwPlayerPreview → SwVideoPreview:rename + 能力補齊。fetchPlayUrl 三態預設走 /movie/play,新增 url 直傳跳過 fetch + mp4/webm 支援 + reload() 應對 URL 過期
    • AudioRecordParams 類型變化:新增 event / view_time / code 欄位(向 VideoRecordParams 對齊),自訂 onRecord 需更新類型簽名
  • 🔧 reset.css / theme.css 增強(v0.5)
    • 新增 scrollbar-width: thin 全域細捲軸,消費專案開箱生效
    • 暗色模式兩個選擇器加入 color-scheme: dark,瀏覽器捲軸軌道等系統 UI 自動切換為暗色
    • dexie / qrcode 自動注入 Vite optimizeDeps.include,pnpm 嚴格模式下消費專案不再需要手動設定

starter

  • 🚀 useSeo() 全量替代 useSeoMeta(配合 fw v0.6.0)
    • starter 6 頁全部遷移到 framework 接管的 useSeo()
    • local-seo/require-seo-meta ESLint 規則強制每頁必填 SEO
    • 私有頁(profile / login / register / mine 等 4 頁)設 robots: 'private' / 'noindex'
  • 🚀 public/og-image.png 佔位圖 + prebuild check-og-image 檢查(配合 fw v0.6.0)
    • 1200×630 PNG 佔位圖放進 public/
    • scripts/check-og-image.ts 在 prebuild 階段驗證,缺失則 build 失敗
    • 防 applier 刪 og-image.png 後社交分享卡片 broken
  • 🚀 @phosphor-icons/vue(v0.5 期)
    • 1300+ 圖示、6 種風格作為標準圖示庫加入直接依賴
    • 替代之前依賴 framework 自帶圖示方案
  • 🚀 modal.css 預設視覺樣式(v0.5 期)
    • SwModal 預設視覺樣式(遮罩、置中卡片、按鈕、進場動畫),亮 / 暗主題自動適配
    • 可在 custom.css 中覆寫 --sw-modal-* CSS 變數自訂
  • 🔧 CSS rem 單位強制(配合 fw v0.4)
    • stylelint declaration-property-unit-allowed-list 強制版面尺寸(width / height / padding / margin)用 rem
    • 跟隨瀏覽器字號縮放提升無障礙
    • border-* 和定位屬性保留 px
    • 整工程從硬編碼 px 切到 rem 單位制
  • 🔧 auth 中介層增強(配合 fw v0.4)
    • guest.global 中介層支援 ?switch=1 參數,允許已登入使用者進入登入頁切換帳號
    • logout 後憑證自動清除
    • Guest 中介層匹配改用 startsWith,修復子路徑未被正確攔截

cli

  • 🐛 sw upgrade 私倉認證修復(v0.2.7)
    • 原本 sw upgrade 用 npm view @swift-web/framework version 拉版本,沒透傳 ~/.npmrc 的 _authToken,私倉存取 401
    • 修復後正確傳遞 token,能從私有 registry 取得最新版本號
  • 🚀 MCP 工具 sw_framework_docs(v0.2.6)
    • 動態查詢 framework 中可用的元件 / composable 清單
    • 讓 Claude Code 等 AI 工具不再憑印象引用舊元件名(避免如 SwBtn 已改名後 AI 還在生成 SwBtn 的失誤)
    • 配合 sw init-mcp 生成 .mcp.json(後續 v0.3.0 刪 init-mcp 改文件指導)
  • 🚀 i18n-applier 對稱化 + scanBusinessI18nUsage(v0.2.4 / v0.2.5)
    • enable / disable 流程對稱,對齊 PWA / Tailwind 冪等原則
    • 新增 scanBusinessI18nUsage 模組掃描業務代碼 i18n API 殘留
    • 精簡 enable 彙報;列出 disable 殘留
  • 🚀 sw config sync 命令(v0.2.3)
    • 重跑所有功能開關 applier(i18n / pwa / tailwind 等),把 swift.config.json 與 nuxt.config.ts 強制對齊
    • 用於:手工改了 swift.config.json 後同步專案檔 / 升級 cli 後回灌新的開關預設值
  • 🚀 Tailwind v4 applier(v0.2.1)
    • sw init 互動擴充支援 Tailwind v4 一鍵啟用
    • 自動注入 @import "tailwindcss" + 必要 vite 外掛 + tailwind.css + stylelint 白名單
    • 六步注入冪等可重跑,關閉時自動回滾
  • 🚀 swift.config.json 精簡(v0.2.1)
    • 移除冗餘欄位,與最新 ModuleOptions 形狀對齊
    • sw add page 範本加 useSeo 佔位與 framework SEO 強制啟用對齊
  • 🚀 @swift-web scope 遷移到 group registry(跨 v0.2.x)
    • 從 project-level(432 / 435 分別 framework / cli)遷到 group-level(group 754)
    • 單 token 存取全部套件;安裝腳本(install.sh / install.ps1)同步更新
    • 簡化 token 管理(之前每個套件一個 deploy token)

docs

  • 🔧 Sidebar 調整
    • 各元件文件頁同步 v0.5 元件重新命名(SwBtn → SwButton 等)
    • 新增「渲染模式快速指南」入口(指向待新增的 rendering-quick-guide)
  • 🚀 6 個中文 markdown frontmatter 擴長達標
    • 按新 useSeo 長度閾值(中文 25-80 字 = 英文 50-160 字元)
    • use-add-to-homescreen / use-login-by / quick-start 簡繁各 3 個
    • SEO 長度建議表加「顯示寬度」說明 + 中英對照
  • 🚀 24 頁 useSeo() 遷移(配合 fw v0.6.0)
    • docs 自己也跟著 starter 走
    • 英文頁 silenceLengthWarnings: true(英文從中文翻譯過來,長度不可控,length 警告對它們無意義)
  • 🚀 三語 framework/seo.md 同步(配合 fw v0.6.0)
    • 完整 useSeo() API 文件、origin / image / robots / JSON-LD 詳細說明、SEO 強制啟用機制
    • /guide/seo 附錄 A 提供 MR review 自檢清單 + eslint 規則名映射

2026-03

5 倉首發月。

framework

  • 🚀 首發 v0.1.0
    • 20 個無樣式核心元件:SwButton / SwImage / SwModal / SwToast / SwUploadImage / SwPlayer / SwQrcodeGenerator 等
    • 8 個 composable:useModal / useToast / useTheme / useUploader / useLoginCheck / useLoginDialog / useLoginBy / useUserActive
    • 2 個全域 store:userInfo(使用者資訊 + Token 管理)/ systemInfo(系統設定)
    • 主題系統:light / dark / auto,localStorage 持久化
    • 路由守衛鑑權體系:guardedPaths / guestPaths 設定
    • 全域錯誤監控:Vue runtime 錯誤捕獲上報
    • 生態整合:@nuxt/image / @vite-pwa/nuxt / @nuxtjs/i18n

starter

  • 🚀 首發
    • Nuxt 4 專案工程結構 + ESLint + TypeScript 嚴格模式
    • 內建 CI/CD(Dockerfile + GitLab CI 流水線)
    • SEO 基礎設施(useSeoMeta() / sitemap / OG 圖片生成)
    • 作為 swift-web 唯一的下游業務範本源

cli

  • 🚀 首發 v0.1.0
    • sw create <project-name> — 從 starter 範本生成完整 Nuxt 專案
    • sw config — 互動式管理 swiftWebFramework 設定項(啟用 / 停用各子模組)
    • sw add <type> — 程式碼產生器,快速生成頁面 / 元件 / store 檔案範本
    • --text 模式 — 在不支援彩色輸出的 CI 環境降級為純文字輸出

docs

  • 🚀 首發
    • 基於 Nuxt Content 搭建官方文件站
    • 自訂 docs 版面 + 導航(DocsNavSidebar / DocsToc / DocsPageHeader / DemoBox / ApiTable 等專用元件)
    • 完成 20 個 Sw* 元件的 Props / Events / Slots 文件頁與互動 Demo
    • 完成 useModal / useToast / useTheme 等 composable 文件頁
    • 完成框架設定參考頁(Module Options)
    • 支援亮 / 暗 / 跟隨系統三種主題,PWA 離線存取
    • 三語言切換(簡體中文 / 繁體中文 / English)