聽尤雨溪談 AI 時代的工具鏈:瓶頸在驗證,不在寫
Evan You 在 Vue Conf Taiwan 2026 的演講,前半是 Vue、Vite 與 VoidZero 的近況,後半談 JavaScript 工具鏈該怎麼為 agent 重新設計。 這是我在現場聽完的整理,並對照我們團隊同時跑多個 agent 的經驗:後半幾乎每一點都對得上我們踩過的痛。
來自實際專案的開發經驗——Nuxt、Vue、Supabase 與現代 Web 工程的踩坑紀錄與解法整理。
共 26 篇 由新到舊
Evan You 在 Vue Conf Taiwan 2026 的演講,前半是 Vue、Vite 與 VoidZero 的近況,後半談 JavaScript 工具鏈該怎麼為 agent 重新設計。 這是我在現場聽完的整理,並對照我們團隊同時跑多個 agent 的經驗:後半幾乎每一點都對得上我們踩過的痛。
vp env 能接手 Node.js 與套件管理器的版本,專案裡寫了 .node-version 也 pin 好了,跑出來的卻是別的版本。 原因是 vp env use 寫下的覆寫檔不只對當下的 shell 有效,還會蓋過所有專案的 pin。 附上隔離環境的重現步驟,以及這個站實際用 Vite+ 的版本與升級紀錄。
一條 AI code review 的 Major finding 指控掃描器把註解當程式碼掃。它讀起來完全合理, 呼叫端的變數名也支持它。用一次乾淨安裝做對照實驗,十分鐘就推翻了——順帶發現同一個 版本號底下躺著兩份不同的程式碼。
多數系統宣稱自己有稽核軌跡,實際保證比想像中弱。這篇拆開五個決定:hash chain 到底 保證什麼、稽核列為什麼必須跟業務寫入同生共死、事件串流為什麼不能當來源、 append-only 為什麼讓 PII 變成收不回來的負債,以及多租戶的鏈該在哪裡上鎖。
不是幻覺,也不是寫錯語法。四個我們實際踩到的 AI 協作失效模式:把搜尋不到當成不存在、 把查得出答案的事升級給人、用 agent 當輪詢器燒掉二十多萬 token、等待迴圈匹配到自己。 每一個都附上實際的判準。
比 bug 更貴的是「用來抓 bug 的東西壞了而沒人知道」。SIGPIPE 讓 grep 命中被讀成沒命中、 pnpm 的 Already up to date 保證錯了東西、斷言被自己的註解滿足、空輸出的 hash 塌縮成同一個值、 core.hooksPath 讓 git hook 靜默變成死檔。
log 管線兩天沒有任何內容而沒人發現、staging 送出的每一個事件都標成 production、 docker.sock 掛唯讀對 Docker API 零保護。三個看起來已經處理好、實際上什麼都沒有保護到的 設定,以及它們共同的成本。
保留字讓你的 script 從沒被執行、dangling symlink 炸掉 build、跨版 orphan 讓 app 初始化 就崩、script 前置 install 把檢查機制自己修好、超長 PATH 讓 spawn 慢十倍。六個實際踩過的 pnpm 行為,以及各自的判準。
本機正常、上了邊緣就壞。CDN 快取鍵不含 Accept 把 CSS 餵成 module script、dev 模式不套 Cloudflare preset 讓 binding 全數缺席、Nitro 追不到動態載入的 WASM、CDN 自動注入的 analytics beacon 撞上 CSP。四個落差與各自的判準。
typecheck 綠、lint 綠、測試綠、console 乾淨,功能卻整條失效。四個真實踩過的 Vue 與 Nuxt 靜默失效:被編譯器丟棄的 props、被遮蔽的具名插槽、解析錯位的 layer alias、烘焙成空值的 runtimeConfig,以及每一個該怎麼判定。
Tailwind v4 的內容掃描來源是宣告出來的,不是自動的。CSS 入口少一行 library import, 該套件獨有的 utility 整批不生成,畫面卻看起來正常。這篇拆解為什麼所有既有的檢查關卡 都量不到這件事,以及唯一那行決定性的判準。
Migration 成功但 API 說找不到表、DISABLE TRIGGER 關不掉外鍵、upsert 讓 pinned UUID 永遠不生效、換個搜尋條件就回 500。四個每一層單獨看都是綠的資料庫故障,以及它們各自 唯一的分岔觀測點。
一個沒有動任何測試、任何元件的 commit,讓 E2E 開始紅。root cause 是 service worker 接管之後,page.route 就攔不到請求了。這篇拆解為什麼只有 reload 之後才壞、為什麼失敗訊息 完全指向錯的方向,以及修法本身要付的代價。
在 ssr: false 的 Nuxt 專案裡,API 回傳 500 時 console 一片安靜,卻能透過 useNuxtApp().payload.error 看到完整錯誤內容。本文記錄這個現象的成因,以及純 Vue 專案如何復刻同樣的除錯體驗。
自架 Supabase 真正的成本不是伺服器,是你收回來的那些責任:migration 不再由 CI 推、 備份變成自己的事、埠號撞在一起時會連到錯的環境而不報錯。這篇記遷移前該先確認的兩件事。
使用 Oxlint 和 Oxfmt 取代 ESLint 和 Prettier,享受 50-100 倍的速度提升,同時保持程式碼品質。
寫給 AI 看的專案規範,寫了不代表會被遵守。真正決定它有沒有效的是三件事: 規範有沒有對應的機械檢查、彼此有沒有衝突、以及它有多長。
把認證從 Supabase 拆出來交給 Better Auth,換到的是完全自訂的使用者模型, 付出的是資料庫再也拿不到登入身分——這個代價會一路影響到 RLS 怎麼寫。
一個 Dashboard 型專案在開工前定下的三個結構決定:關掉 SSR 的取捨、app 與 server 的 界線該用什麼判準畫、以及拿掉元件路徑前綴換來的代價。
handler 裡的步驟順序不是風格問題——權限檢查之前做的任何事,都是未授權的人可以觸發的。 這篇記固定順序的理由,以及三個會回 200 的錯:路由撞成 HTML、query 全是字串、軟刪除漏過濾。
Nuxt UI 的 Dashboard 元件把側邊欄狀態、響應式與收合行為都做掉了,剩下要自己決定的 只有幾件。這篇記三個做錯不會報錯的地方:漏了根元件、用 v-if 切版面、以及扁平化的元件命名。
快取層真正要決定的只有一件事:哪些資料的正本不在瀏覽器裡。定錯了會得到兩份會漂的真相; key 設計不一致則會讓失效機制靜默失靈——改完資料畫面沒更新,重整一次又對了。
權限系統最貴的錯誤不是規則寫錯,是預設值選錯。這篇記三件事:新使用者的預設角色、 Client 與 Server 兩層檢查各自負責什麼,以及權限定義為什麼必須只有一份。
先寫測試的價值不在紀律,在於你會親眼看到它失敗一次——沒紅過的測試有可能永遠是綠的, 而它照樣算進覆蓋率。這篇記三件事:Red 這一步在驗什麼、測試環境怎麼選、以及 mock 的界線。
端到端型別安全的關鍵不是寫更多 interface,而是讓每一種型別只有一個來源。 這篇記三個讓型別失效的方式:型別與真實資料不符、泛型漏傳導致整條查詢變成 any、 以及 migration 後沒重新產生。
Schema 變更從哪裡進來、寫入走 Client 還是 Server、函式與 View 的預設安全性。 這三件事的預設值都偏向方便,而且做錯時全部都是靜默失敗——沒有錯誤訊息, 只有影響 0 列、空陣列,或看得到不該看的資料。