iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
Modern Web

Vue 前端工程師視角看 Flutter Web系列 第 29

Day 29|生態系與工具鏈踩坑心得:套件成熟度盤點 + DevTools 除錯實戰

  • 分享至 

  • xImage
  •  

模組七|生態系與踩坑心得(Day 29–30)

先備:Day 21(CanvasKit 把畫面畫進 canvas)。這一篇不套三段式,因為它盤的是工具鏈,不是某個 API 的對照。

整個 UI 畫在一張 canvas 上,那 console.log 去哪了?

這是我開工前最擔心的問題。寫了十年 Vue,我的 debug 肌肉記憶全長在瀏覽器 DevTools 上:Elements 面板看結構、Console 戳狀態、Styles 面板即時改 CSS、Vue Devtools 看元件樹和 Pinia store。Flutter Web 把這一切畫進一個 <canvas>,直覺上等於把我的工具箱整個沒收。

結論先講:

比想像中好,但痛點在別處。

實測 28 天下來,我的 debug 工具箱沒有被沒收,是被換掉——換來的東西在開發期堪用,在 release build 那一關才真的開始痛。這篇把 debug 體驗和套件生態的坑一次盤完。

不過在盤之前,我得先誠實揭露這個專案的工具鏈現況,因為它會影響你怎麼看下面這些結論。

我的靜態檢查與測試現況

Flutter 端的 analysis_options.yaml 全檔是 flutter create 產生的樣板,關鍵在第 10 行:

# analysis_options.yaml:10
include: package:flutter_lints/flutter.yaml

linter:
  rules:
    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule

官方推薦的 flutter_lints 有 include 進來,但底下 rules: 區塊每一條自訂規則都還是註解狀態——我一條都沒開、一條都沒關。也就是說,本系列反覆講的「編譯期防線」,我拿到的是官方預設值,沒有加碼。

測試更誠實一點:Flutter 端有一個 test/widget_test.dart(也是樣板產生的),Vue 端零個測試檔

我把這兩件事放在最前面,是因為接下來我要說「Flutter 的工具鏈比想像中好」,而你有權知道我是在多低的標準上說這句話。

Vue 怎麼做

先確認座標系。Vue 的除錯體驗建立在一個前提上:你的 UI 就是 DOM,瀏覽器 DevTools 天生看得懂它

  • console.log 想放哪放哪,source map 讓你點回 .ts 原始行號
  • Elements 面板就是你的 UI 結構,右鍵檢查任何元素,DOM 和你的 template 幾乎一一對應
  • Styles 面板即時調 margincolor,滿意了再抄回 code——這是十年來我調版面的主要迴圈
  • Vue Devtools 瀏覽器擴充:元件樹、props、Pinia state、事件時間軸
  • production 出事:錯誤監控(Sentry 等)吃 JS source map 是業界標配,minified stack trace 還原回原始碼,生態極度成熟

套件生態同理:npm 上任何一個前端套件,預設就是為瀏覽器而生,你幾乎不用問「這個套件支不支援 Web」。

Flutter Web 怎麼做

console.log 有直接等價物,這關不痛

三個層次,都直出瀏覽器 console:

import 'dart:developer' as developer;
import 'package:flutter/foundation.dart';

Future<void> connectQuoteStream() async {
  // 1. 最粗暴:等同 console.log
  print('connectQuoteStream: start');

  // 2. 節流版:大量輸出時不會被平台丟棄,debug 專用
  debugPrint('payload size: ${payload.length}');

  // 3. 結構化:可帶分類名稱、error 物件、stack trace
  try {
    await ws.connect();
  } catch (e, st) {
    developer.log(
      'websocket connect failed',
      name: 'quotes.ws',   // console 裡可用這個名稱過濾
      error: e,
      stackTrace: st,
    );
  }
}

更重要的是:debug 模式下 Dart 編譯成 JS 時帶 source map,console 裡的輸出和錯誤可以直接點回 .dart 的原始行號。跟 Vue 點回 .ts 的體驗幾乎一致。開工前最擔心的這一關,實際上是整篇最不痛的部分。

Elements 面板的替代品:Widget Inspector

瀏覽器的 Elements 面板廢掉之後,補位的是 Flutter DevTools 的 Widget Inspectorflutter run -d chrome 起來後開 DevTools,Inspector 的 select mode 讓你點畫面上任何一塊,直接跳到 widget tree 對應節點,看它的 constraints、padding、實際 render 尺寸。體感上就是「Vue Devtools 的元件樹」而不是「Elements 面板」——它給你的是框架視角的結構,不是平台視角的 DOM。

其他照舊的:

  • IDE 中斷點:VS Code F5 直接在 Dart 下斷點 step through,跟你在 Vue 專案裡對 .ts 下斷點沒有兩樣
  • Network tab 照常可用:HTTP 請求終究是瀏覽器發的,canvas 沒收不了它

套件成熟度:pub.dev 要先看平台標籤

生態這邊的第一課:pub.dev 每個套件頁面都有平台支援標籤(Android / iOS / Web / ...),先看標籤再看 star 數。踩過的坑歸納成三類:

  1. dart:io 依賴:任何碰檔案系統、原生 socket 的套件在 Web 上直接編譯失敗。好消息是失敗在編譯期,不是 runtime——你會在 flutter build web 就知道,而不是上線後
  2. 有 Web 標籤但體驗打折:不少套件 Web 支援是「能編譯」等級,功能陽春或效能異常,issue 區搜 web 通常能提前看到災情
  3. plugin 走 JS interop 的:品質參差,官方(flutter.devdart.dev publisher)出品的可信度明顯高一級

拿我這 28 天實際用到的類別盤點一輪:HTTP 與 WebSocket 官方等級套件穩定無虞;狀態管理(Riverpod、Bloc)本來就是純 Dart,跨平台零問題;圖表類選擇比 npm 少一個量級,但因為 Flutter 本來就是畫布,自己用 CustomPaint 補的成本反而低;i18n 與日期在地化堪用但排版細節要自己驗;最慘的是富文字編輯器這種深度依賴瀏覽器原生行為的類別,Web 上的成熟度跟 npm 生態完全不能比。

跟 npm「預設支援瀏覽器」的世界相比,這是心智模型要反過來的地方:Flutter 生態預設 mobile,Web 是要主動驗證的次要平台。選套件的順序從「找 star 最多的」變成「先過濾出 Web 標籤,再看 issue 區的 Web 災情,最後才比功能」。

差異與坑

沒了的東西,誠實列

  • Elements 面板廢掉——DOM 只剩一個 <canvas>,右鍵檢查看不到任何結構。第一次做這件事的失落感很真實
  • CSS 即時調整沒了——不能在 Styles 面板改 margin 看效果再抄回 code,只能改 Dart 靠 hot reload(web hot reload 自 Flutter 3.35 起預設啟用,3.44 更把 --web-hot-reload flag 標為 deprecated,這個秒級迴圈現在是穩的)。迴圈從「秒級、免切窗」變成「秒級、要切窗」,小但持續的摩擦
  • 沒有 Vue Devtools 式的瀏覽器擴充——Widget Inspector 是獨立視窗的 DevTools,不住在瀏覽器 F12 裡。功能對得上,但「所有工具都在同一個 F12 裡」的整合感沒了,debug 時你會固定開著兩套工具切來切去

補一個容易被忽略的正面項:效能分析反而不吃虧。Flutter DevTools 自帶 Performance 面板看 frame 耗時、rebuild 次數,對照 Vue 這邊要靠 Vue Devtools 的 profiler 加瀏覽器 Performance tab 拼湊,Flutter 的訊號反而更聚焦——因為整個渲染管線都是框架自己的,它對每一幀發生什麼事有完整的話語權。

真痛點:release build 的可觀測性

這是我認定對 Vue 的真實劣勢,不是體感問題。

production 的 Flutter Web 是 minified JS(或 WASM),線上錯誤的 stack trace 近乎不可讀。要還原,得自行處理 source map 上傳——Sentry 有支援 Flutter Web,但整條鏈的成熟度、文件量、社群踩坑資料都輸 JS 生態一截。Vue 專案裡「上傳 source map 到錯誤監控」是 CI 裡一行外掛就解決的日常;Flutter Web 這邊你會花上明顯更多時間,而且 WASM 路線的工具鏈還在演進。

**線上事故的 debug 能力,是目前 Flutter Web 對 Vue 最實質的落差之一。**選型時如果你的產品對線上可觀測性要求高,這條要記進成本。

但 agent 工作流繞掉了一大半

回扣本系列的獨家論點:我全程用 AI agent 開發,而 agent 的回饋迴圈吃的是 flutter analyze、編譯錯誤、test 輸出——它根本不靠 console 手戳,也不開 DevTools

這代表上面列的「沒了的東西」,對 agent 工作流的傷害遠小於對人工開發的傷害。人類失去 Elements 面板會難受;agent 從來沒用過。反而 Dart 強型別讓錯誤集中在編譯期爆,正好餵進 agent 最擅長消化的訊號通道。人工 debug 的劣勢,被 agent 迴圈部分繞掉了——這是我在 Day 1 不敢肯定、28 天後可以肯定的事。

而這條迴圈在 Flutter 3.44 又往前推了一段:Agentic Hot Reload。Dart MCP server 會自動找到並連上正在執行的 Dart/Flutter app,agent 不需要任何手動設定,就能改完 code 直接觸發熱重載。同一版還把 MCP 的 tool 定義做了合併,agent 工作流的 token 成本跟著降,另外也強化了在 package 依賴裡搜尋的能力(不必開放整個本機 pub cache)。

意義不在「AI 會寫 code」——那件事早就成立——而在於 agent 的訊號來源第一次從編譯期擴張到執行期:它改完可以自己看正在跑的 app,再決定下一輪要改什麼。上面那句「agent 不開 DevTools」因此要補一個但書:它不開 DevTools,但它現在有另一條自己的管道連進 running app。這個轉變對前端比對 mobile 更有感,因為我們本來就活在瀏覽器的即時回饋裡。

當然「部分」兩個字要誠實:release build 可觀測性的痛,agent 繞不掉,線上事故終究是人要面對。Agentic Hot Reload 改善的是開發期迴圈,不是 production 的黑盒子。

小結與下一篇

一句話:開發期的 debug 體驗補得回來(Widget Inspector + source map + IDE 斷點),生態要習慣「Web 是次要平台」的預設,而 release 可觀測性是真實落差——但 agent 工作流讓前兩者的痛感大幅降級。

明天 Day 30,系列最後一篇。一個不信 Flutter Web 的 Vue 老手,30 天實測完的總結:學習地圖全回顧、Day 1 那棵決策樹要不要修、以及給 Vue 人的具體行動建議。

參考資料

如果你卡在語法

深入原理


上一篇
Day 28|SEO 導向專案該不該選 Flutter Web?決策框架
下一篇
Day 30|總結:Vue 前端跨入 Flutter Web 的完整學習地圖與建議
系列文
Vue 前端工程師視角看 Flutter Web30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言