[{"data":1,"prerenderedAt":431},["ShallowReactive",2],{"blog:\u002Fblog\u002Fai\u002Fevan-you-taiwan-2026":3,"blog:chapters":350,"blog:\u002Fblog\u002Fai\u002Fevan-you-taiwan-2026:surround":401,"blog:\u002Fblog\u002Fai\u002Fevan-you-taiwan-2026:series":412,"blog:\u002Fblog\u002Fai\u002Fevan-you-taiwan-2026:author":413,"blog:\u002Fblog\u002Fai\u002Fevan-you-taiwan-2026:related":418},{"id":4,"title":5,"author":6,"body":7,"category":333,"date":334,"description":335,"draft":336,"extension":337,"image":338,"kind":339,"meta":340,"navigation":341,"path":342,"seo":343,"series":338,"seriesOrder":338,"seriesTitle":338,"stem":344,"tags":345,"updatedAt":338,"__hash__":349},"blog\u002Fblog\u002Fai\u002Fevan-you-taiwan-2026\u002Findex.md","聽尤雨溪談 AI 時代的工具鏈：瓶頸在驗證，不在寫","charles",{"type":8,"value":9,"toc":315},"minimark",[10,14,17,20,25,28,36,44,47,50,57,61,72,75,155,171,180,183,187,190,200,206,209,213,216,219,222,275,278,282,285,293,296,299,302,305,308],[11,12,13],"p",{},"agent 改完一段程式碼只要幾十秒，接著它說「我在等測試跑完」，然後五分鐘過去了。你開了三個平行的工作區想加快進度，第三個 dev server 起來時記憶體就滿了。如果你每天都在用 coding agent，這兩個畫面應該不陌生。",[11,15,16],{},"2026 年 10 月 17 日，我在 Vue Conf Taiwan 2026 現場聽了 Evan You（尤雨溪）的演講。前半段是 Vue、Vite 與 VoidZero 的近況，後半段他把題目拉高：今天的 JavaScript 工具鏈都是為人設計的，換成 agent 來用，哪些前提要從頭想過。後半段講的幾乎就是上面那兩個畫面。",[11,18,19],{},"這篇是我聽完的整理：先記前半的重點，再花多一點篇幅談後半，最後寫我們團隊怎麼看。內容是我的轉述與摘要，不是逐字引述；版本與發布狀態我對照過官方公告，查不到公開資料的會標明是現場所述。他說還不能公開的東西，這裡只寫「他預告了」。",[21,22,24],"h2",{"id":23},"一框架在-ai-時代的處境語料紅利與-api-穩定","一、框架在 AI 時代的處境：語料紅利與 API 穩定",[11,26,27],{},"他的第一個觀察是：一個框架成為主流之後，在 AI 時代會自己持續成長，因為模型的訓練資料裡已經有大量語料。早期的模型還會把 Vue 2 和 Vue 3 的寫法混在一起，現在主流模型已經不會。他現場給的數字是 Vite 每週下載量超過兩億次（Cloudflare 2026 年 6 月的收購新聞稿引用的是超過 1.3 億），Vue 稍少，但也穩定成長。",[11,29,30,31,35],{},"第二個觀察比較反直覺：模型偏好精確、沒有歧義的 API，不在意寫起來繁瑣。Vue 過去為了開發者體驗加了很多簡寫，例如 ",[32,33,34],"code",{},"v-on"," 的縮寫，從模型的角度看，這些方便反而增加 token 用量和判斷負擔。好在 Vue 的語料夠多，這件事目前對模型不構成問題。",[11,37,38,39,43],{},"由此推出的取捨是 ",[40,41,42],"strong",{},"API 穩定優先","。訓練資料永遠落後，每改一次 API，所有用 AI 寫程式的人都會經歷一段 AI 還在寫舊寫法的陣痛期。所以框架作者現在發布重大改動要更謹慎，每一個改動都要值得那段陣痛。",[11,45,46],{},"講到這裡你可能會想，那 Vue 4 呢？以下是現場所述，我沒有找到對應的官方公告：Vue 4 目前唯一確定的事情是移除 CommonJS 的發佈檔，因為這是 breaking change，照 SemVer 只能升主版號；不會有 Vue 2 到 3 那種程度的改動，而且可能和 3.6 同時發正式版。",[11,48,49],{},"3.6 寫這篇時還在 RC 階段。它的 Vapor Mode 沿用同一套 API、逐元件選用，他現場展示的 benchmark 效能贏過 Svelte 和 Solid；響應式系統的底層換成 alien-signals，作者是 core team 成員 Johnson。據他現場的說法，Johnson 整理了一套比較各家 signals 實作行為正確性的測試，alien-signals 是唯一全部通過的實作。",[11,51,52,53,56],{},"這一節的判準是：",[40,54,55],{},"對人和對 AI 都永遠有用的只有兩件事，正確性與效能。"," 簡寫和語法糖的價值，在 agent 寫大部分程式碼之後正在下降。",[21,58,60],{"id":59},"二voidzero-加入-cloudflare-之後","二、VoidZero 加入 Cloudflare 之後",[11,62,63,64,71],{},"Cloudflare 在 ",[65,66,70],"a",{"href":67,"rel":68},"https:\u002F\u002Fvoidzero.dev\u002Fposts\u002Fvoidzero-cloudflare",[69],"nofollow","2026 年 6 月宣布收購 VoidZero","，Vite、Vitest、Rolldown、Oxc 都維持 MIT 授權。他說對開源部分完全沒有影響，最大的差別是不必再為開源工具的商業化煩惱，可以專心做開源，並且接手 JavaScript 生態裡一些沒人願意承擔的工作。",[11,73,74],{},"今年陸續發布的東西如下，版本與日期我對照過官方公告：",[76,77,78,91],"table",{},[79,80,81],"thead",{},[82,83,84,88],"tr",{},[85,86,87],"th",{},"項目",[85,89,90],{},"狀態",[92,93,94,108,121,129,142],"tbody",{},[82,95,96,105],{},[97,98,99,104],"td",{},[65,100,103],{"href":101,"rel":102},"https:\u002F\u002Fvite.dev\u002Fblog\u002Fannouncing-vite8",[69],"Vite 8","（2026-03）",[97,106,107],{},"打包改用 Rolldown、編譯用 Oxc，他說這為 Rust 化畫上句點",[82,109,110,118],{},[97,111,112,117],{},[65,113,116],{"href":114,"rel":115},"https:\u002F\u002Fvoidzero.dev\u002Fposts\u002Fannouncing-vite-plus-1-0",[69],"Vite+ 1.0","（2026-09）",[97,119,120],{},"linter、formatter、test runner、dev server、bundler 收進同一個工具，並管理 Node.js 與套件管理器版本，附本機 task cache",[82,122,123,126],{},[97,124,125],{},"Vitest 5（2026-09）",[97,127,128],{},"底層跑的是 Vite，間接拿到上面的效能提升",[82,130,131,139],{},[97,132,133,138],{},[65,134,137],{"href":135,"rel":136},"https:\u002F\u002Foxc.rs\u002Fblog\u002F2026-07-22-type-aware-linting-stable",[69],"oxlint type-aware linting","（2026-07）",[97,140,141],{},"宣告 stable",[82,143,144,152],{},[97,145,146,151],{},[65,147,150],{"href":148,"rel":149},"https:\u002F\u002Foxc.rs\u002Fblog\u002F2026-08-18-react-compiler-support",[69],"React Compiler 的 Rust 版","（2026-08，實驗性）",[97,153,154],{},"原本的 Rust 移植停滯，Oxc 團隊接手並放進 Oxc；現場所述比原版更快",[11,156,157,158,161,162,165,166,170],{},"Vite+ 管版本這件事他舉了自己的例子：換新電腦時只先裝 Vite+，進專案跑 ",[32,159,160],{},"vp install","，它會先下載該專案要求的 Node.js 和套件管理器版本再安裝依賴，切到別的倉庫也會自動換成對的版本。我們自己用 ",[32,163,164],{},"vp env"," 管版本時踩過一個「pin 了卻沒生效」的坑，寫在 ",[65,167,169],{"href":168},"\u002Fblog\u002Fnodejs\u002Fvite-plus-env","Vite+ 的 vp env：pin 了版本卻沒生效","。",[11,172,173,174,179],{},"Roadmap 上可以公開的有這幾項。Vite 的 bundle dev 解決超大型專案的問題：上萬個模組代表瀏覽器一次收上萬個請求，瓶頸在瀏覽器的網路層，不在 Vite，先 bundle 成幾十到一百多個請求就好得多。這個功能從 ",[65,175,178],{"href":176,"rel":177},"https:\u002F\u002Fvite.dev\u002Fblog\u002Fannouncing-vite8-1",[69],"Vite 8.1"," 起以實驗性的 bundled dev mode 提供。Rolldown 的 chunking 則要重新學 Webpack：純 ESM 為了維持語義正確，共用模組必須各自拆成獨立 chunk，大型專案可能切出上千個；Webpack 的做法是允許小模組在多個 chunk 裡重複一份，犧牲一點正確性換來少得多的請求數。他說當年偏好 Rollup 那種乾淨的純 ESM 產物，回頭看 Webpack 的很多取捨是有道理的，Rolldown 正在把其中一些概念引回來。",[11,181,182],{},"其他還有：第四季在 Vite 與 Rolldown 原生支援 import attributes；和一位 Atlassian 工程師合作，用 SIMD 加速 Oxc parser，現場所述驗證過可以再快三倍、lexer 部分已完成；Vite+ 會從本機 task cache 擴充到 remote cache，讓隊友和 CI 共用，這一項在 1.0 公告裡也列為之後的版本。另外他預告近期會有新消息，當時還不能透露。",[21,184,186],{"id":185},"三void把部署步驟拿掉agent-就能一次做完","三、Void：把部署步驟拿掉，agent 就能一次做完",[11,188,189],{},"Void 原本規劃為 VoidZero 的付費平台，定位接近 Vercel 的競品。加入 Cloudflare 後沒必要再做一份商業複製品，他在現場宣布框架和平台已經一起開源。以下功能都是他現場的介紹，我還沒有自己動手驗證。",[11,191,192,193,196,197,199],{},"框架本身是一個 Vite plugin，裝上之後 Vite 就變成全端應用，有自己的 pages router，可以搭配 Vue、React、Svelte、Solid，共用同一套路由與型別。它最大的特點是從程式碼推導需要的伺服器資源：程式碼裡寫 ",[32,194,195],{},"import db","，本機開發時用 SQLite 模擬；部署時它先在你的 Cloudflare 帳號裡建好 D1 資料庫，每次部署前把 migration 跑完。資料庫層強制用 Drizzle，從 TypeScript 寫的 schema 一路推導出 query、頁面 props、actions 與表單驗證的型別。",[32,198,195],{}," 這類 SDK 功能不綁 Void 自己的框架，Nuxt、SvelteKit 等以 Vite 為基礎的框架也能用。",[11,201,202,203],{},"他講了一個例子：團隊裡一位非技術背景、負責營運的成員，第一次手動設定各項資源來部署應用，花了三小時沒有成功；改用 Void 之後，一個給 agent 的 prompt 就部署出能用的應用。他的結論是：",[40,204,205],{},"把瑣碎的手動部署步驟拿走之後，agent 做事就能 one-shot。",[11,207,208],{},"平台開源的另一個用途是公司自架：部署在自己的 Cloudflare 上，每個 app 的登入自動接公司的 SSO，例如只有公司信箱能存取。這對團隊內部用 vibe coding 快速做小工具很實用，不用每做一個就重新處理驗證和存取控制。",[21,210,212],{"id":211},"四後半為-agent-重新設計工具鏈的七個原則","四、後半：為 agent 重新設計工具鏈的七個原則",[11,214,215],{},"他先描述背景。今年初 Opus 4.6 發布時，他明確感受到 agent 產出的程式碼品質已經超過大多數工程師手寫；到 Opus 5.5，他說自己大概不會再手寫程式碼了。使用方式也在變：從 IDE 裡按 tab 補完，到在 CLI 叫 agent 修 bug，到丟一份 design doc 讓 agent 連續工作十幾小時，再到一台電腦同時跑三四個 session，甚至在雲端跑幾十上百個平行 agent。",[11,217,218],{},"他也提到這對開源的衝擊。MIT 授權的專案過去不怕被拿走，因為大家信任的是持續維護，而 fork 之後重寫和維護的成本都很高。AI 讓照著現成實作重做一份的成本大幅下降，這道靠維護信任建立的護城河正在變淺。他沒有給答案，只說這讓他重新思考開源該怎麼做。",[11,220,221],{},"然後回到工具。他的大前提是：人有偏好，工具要讓人寫得開心；agent 不在乎程式碼醜不醜，只在乎一致性、寫錯時有沒有編譯器糾正、結果能不能驗證。底下是他列的原則，我按他的順序轉述。",[223,224,225,230,233,237,240,244,247,251,254,258,261,265,268,272],"steps",{},[226,227,229],"h3",{"id":228},"驗證速度決定-loop-效率","驗證速度決定 loop 效率",[11,231,232],{},"agent 的本質是一個 loop：tool call、驗證、下一步。模型本身不確定，所以每一步都需要工具驗證才能往下走。agent 寫程式其實很快，慢是慢在驗證：測試要跑五分鐘，agent 就空等五分鐘。",[226,234,236],{"id":235},"flaky-與-slow-test-要在工具層根除","flaky 與 slow test 要在工具層根除",[11,238,239],{},"測試隨機失敗時，agent 會重跑好幾遍，最後回報「這個測試有時過有時不過，原因不明」。同一個測試花了好幾倍的時間，結論還是不確定。",[226,241,243],{"id":242},"設定只留事實拿掉偏好","設定只留事實，拿掉偏好",[11,245,246],{},"Prettier 出現前，大家為分號、空格、換行吵了好幾年，最後發現都不重要。下一代工具的選項應該只剩事實，例如檔案放在哪、要不要裝某個 plugin；要不要加分號這種問題根本不該是選項。",[226,248,250],{"id":249},"codebase-understanding-as-a-service","Codebase Understanding as a Service",[11,252,253],{},"仔細看 agent 的 tool call，它還在大量用 grep 做文字搜尋。工具鏈手上有 parser 和 module graph，回答「這個函式在哪些地方被用到」「這個模組被誰引用」可以比 agent 自己找快上百倍，應該提供一級的 API 給 agent。",[226,255,257],{"id":256},"runtime-observability-不靠看畫面","Runtime observability 不靠看畫面",[11,259,260],{},"按了按鈕發生什麼事、CSS 有沒有載入，很多 agent 會起一個真的瀏覽器，用 Playwright 或 computer use 去看。工具鏈可以在頁面裡注入 JavaScript，直接把這些狀態用 API 交給 agent。",[226,262,264],{"id":263},"常駐-daemon共享-parse-結果","常駐 daemon，共享 parse 結果",[11,266,267],{},"即使 Rolldown、oxlint、Vitest 本身很快，每次從 CLI 呼叫都是從頭 parse、transform、resolve 同一批檔案。更好的模式是一個常駐行程把整個倉庫的 module graph 留在記憶體裡，lint、bundle、format 都是對同一份 graph 查詢，任務之間共享工作，做到真正的增量。",[226,269,271],{"id":270},"平行-worktree-之間共享不可變的-project-graph","平行 worktree 之間共享不可變的 project graph",[11,273,274],{},"平行 agent 多半各自開一個 worktree，起三個 Vite dev server 記憶體就不夠。如果 project graph 是不可變的，可以像 immutable data structure 那樣在 worktree 之間做 structural sharing，相同的檔案只佔一份記憶體，每個 worktree 只為自己改過的部分付出額外成本。",[11,276,277],{},"他最後說，這些原則需要拋開既有的設計思路重新架構，他正在做一個還不能公開的專案，預計今年稍晚或明年初介紹。",[21,279,281],{"id":280},"五我們怎麼看","五、我們怎麼看",[11,283,284],{},"我們每天同時跑好幾個平行的 agent session，每個各自在一個 worktree 裡工作。聽後半段的感覺是，他列的七點幾乎每一點我們都直接付過代價。",[11,286,287,288,292],{},"最直接的是驗證迴圈。我們的經驗和他說的一樣：agent 一輪改動很快，真正花時間的是等型別檢查、等測試、等 build。驗證慢不只是慢，還會改變 agent 的行為，它會開始猜「應該過了」，或者把等待時間拿去做沒被要求的事。flaky test 更糟，一個隨機失敗的測試會讓 agent 重跑、懷疑自己、最後交回一個不確定的結論，這種失效模式我們在 ",[65,289,291],{"href":290},"\u002Fblog\u002Fai\u002Fagent-failure-modes","讓 AI 寫程式時，真正會出事的四個地方"," 也寫過類似的例子。",[11,294,295],{},"worktree 的資源成本我們也撞過。平行開工區最先撐不住的是記憶體和 dev server 的連接埠，我們目前的做法是限制同時存在的工作區數量、做完就收回，屬於管理層面的止血；他說的在工作區之間共享不可變的 graph，是從工具層把成本本身拿掉，方向不同。",[11,297,298],{},"grep 和截圖這兩點，我們的感受是「agent 拿到的證據品質」問題。用文字搜尋判斷「沒有人用這個函式」，搜不到不等於不存在；用截圖判斷畫面對不對，看得到的只有渲染結果，看不到狀態。工具鏈能直接回答結構化問題、直接交出 runtime 狀態，agent 的結論才有可信的依據。",[11,300,301],{},"設定只留事實這一點，對應的是我們寫規則的方式。早期我們的規則有很多「視情況判斷」，結果每個 agent 判斷都不一樣；後來改成只寫事實，能機械檢查的就交給 gate 擋，不留給 agent 自己判斷。這和他說的「Prettier 的教訓」是同一件事：選項越少，結果越一致。",[11,303,304],{},"最後是部署 one-shot。我們把網站部署在 Cloudflare 上，部署流程裡每多一個要手動補的步驟，agent 就多一個卡住、回頭問人的地方。Void 從程式碼推導資源的做法，是把這些步驟從流程裡整個刪掉，而不是寫更長的部署說明。",[11,306,307],{},"講到這裡你可能會想，這些不都是工具作者的工作嗎？一般團隊能做什麼？能做的不少。把測試跑快、把 flaky test 修掉或隔離、把手動步驟寫成可執行的指令、把「要記得」的規則改成會失敗的檢查，這些都不需要等下一代工具鏈。我們已經把上面幾點列為接下來的工程方向，順序就照他講的：先處理驗證速度，因為其他每一點的收益都要乘上它。",[11,309,310,311,314],{},"判斷標準只有一條：",[40,312,313],{},"agent 等待驗證的時間，是不是比它寫程式的時間還長？"," 如果是，你該優化的不是 prompt。",{"title":316,"searchDepth":317,"depth":317,"links":318},"",3,[319,321,322,323,332],{"id":23,"depth":320,"text":24},2,{"id":59,"depth":320,"text":60},{"id":185,"depth":320,"text":186},{"id":211,"depth":320,"text":212,"children":324},[325,326,327,328,329,330,331],{"id":228,"depth":317,"text":229},{"id":235,"depth":317,"text":236},{"id":242,"depth":317,"text":243},{"id":249,"depth":317,"text":250},{"id":256,"depth":317,"text":257},{"id":263,"depth":317,"text":264},{"id":270,"depth":317,"text":271},{"id":280,"depth":320,"text":281},"導入 AI","2026-10-18","Evan You 在 Vue Conf Taiwan 2026 的演講，前半是 Vue、Vite 與 VoidZero 的近況，後半談 JavaScript 工具鏈該怎麼為 agent 重新設計。 這是我在現場聽完的整理，並對照我們團隊同時跑多個 agent 的經驗：後半幾乎每一點都對得上我們踩過的痛。",false,"md",null,"insight",{},true,"\u002Fblog\u002Fai\u002Fevan-you-taiwan-2026",{"title":5,"description":335},"blog\u002Fai\u002Fevan-you-taiwan-2026\u002Findex",[346,347,348],"AI","Vite","Vue","KiXvDEJRCYo_akx-BMGt1qpPxfu1tPGTINP5RwSyTaU",[351,352,353,354,356,357,360,362,363,364,366,367,369,370,371,372,373,374,376,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,399,400],{"category":333,"kind":339},{"category":333,"kind":339},{"category":333,"kind":339},{"category":355,"kind":339},"看不見的故障",{"category":355,"kind":339},{"category":358,"kind":359},"Git","reference",{"category":361,"kind":359},"Linux",{"category":361,"kind":359},{"category":361,"kind":359},{"category":365,"kind":359},"Node.js",{"category":365,"kind":359},{"category":368,"kind":339},"品質與交付",{"category":365,"kind":359},{"category":368,"kind":339},{"category":355,"kind":339},{"category":365,"kind":359},{"category":333,"kind":339},{"category":375,"kind":339},"權限與資料安全",{"category":377,"kind":339},"上線前的決策",{"category":377,"kind":339},{"category":380,"kind":359},"Nuxt",{"category":368,"kind":339},{"category":380,"kind":359},{"category":380,"kind":359},{"category":368,"kind":339},{"category":368,"kind":339},{"category":375,"kind":339},{"category":355,"kind":339},{"category":377,"kind":339},{"category":355,"kind":339},{"category":368,"kind":339},{"category":368,"kind":339},{"category":355,"kind":339},{"category":375,"kind":339},{"category":355,"kind":339},{"category":377,"kind":339},{"category":355,"kind":339},{"category":398,"kind":359},"VS Code",{"category":348,"kind":359},{"category":348,"kind":359},[402,407],{"title":403,"path":404,"stem":405,"description":406,"children":-1},"同一段 CSS 寫在註解裡零命中，當實碼就命中","\u002Fblog\u002Fai\u002Fcomment-vs-code-false-positive","blog\u002Fai\u002Fcomment-vs-code-false-positive\u002Findex","一條 AI code review 的 Major finding 指控掃描器把註解當程式碼掃。它讀起來完全合理， 呼叫端的變數名也支持它。用一次乾淨安裝做對照實驗，十分鐘就推翻了——順帶發現同一個 版本號底下躺著兩份不同的程式碼。",{"title":408,"path":409,"stem":410,"description":411,"children":-1},"綠燈是假的：五個讓檢查機制自己失效的坑","\u002Fblog\u002Fdevops\u002Ffake-green-gates","blog\u002Fdevops\u002Ffake-green-gates\u002Findex","比 bug 更貴的是「用來抓 bug 的東西壞了而沒人知道」。SIGPIPE 讓 grep 命中被讀成沒命中、 pnpm 的 Already up to date 保證錯了東西、斷言被自己的註解滿足、空輸出的 hash 塌縮成同一個值、 core.hooksPath 讓 git hook 靜默變成死檔。",[],{"name":414,"avatar":415,"bio":416,"url":417},"Charles","\u002Ficons\u002Favatar.webp","前端工程師，主要使用 Vue.js \u002F Nuxt，分享軟體開發的踩坑經驗、新技術與最佳實踐心得。","\u002F",[419,424,427],{"path":168,"title":169,"description":420,"date":421,"category":355,"tags":422},"vp env 能接手 Node.js 與套件管理器的版本，專案裡寫了 .node-version 也 pin 好了，跑出來的卻是別的版本。 原因是 vp env use 寫下的覆寫檔不只對當下的 shell 有效，還會蓋過所有專案的 pin。 附上隔離環境的重現步驟，以及這個站實際用 Vite+ 的版本與升級紀錄。","2026-10-09",[365,347,423],"Debug",{"path":404,"title":403,"description":406,"date":425,"category":333,"tags":426},"2026-08-26",[346,423],{"path":290,"title":291,"description":428,"date":429,"category":333,"tags":430},"不是幻覺，也不是寫錯語法。四個我們實際踩到的 AI 協作失效模式：把搜尋不到當成不存在、 把查得出答案的事升級給人、用 agent 當輪詢器燒掉二十多萬 token、等待迴圈匹配到自己。 每一個都附上實際的判準。","2026-08-25",[346,423],1792681767039]