
Last updated: May 28, 2026
TL;DR:Quire(53,992 行、1,620 KB 的 Dart 程式碼)於 2014 年誕生,前後端皆採用 Dart;我們選擇 DQuery 與 Bootjack,而非 AngularDART 或 Polymer.dart,藉此換取更細膩的 DOM 掌控力。當年的幾項核心決策——整套技術堆疊使用強型別、前後端共用資料模型、伺服器採用事件迴圈、JS 輸出進行 tree shaking——時至 2026 年依然站得住腳。
Quire 不是第一個用 Dart 寫成的網頁應用程式,也不會是最後一個,但它或許是第一個如此重度仰賴 Dart 的應用程式——前端、後端都一樣。

它是一款以樹狀圖為核心、用起來很有趣的任務管理工具。整個專案有 53992 行、1620KB 的 Dart 程式碼,並搭配幾個社群開源函式庫。
在投入這個專案之前,我們是一群熱愛 Dart 的開發者,外界稱為 Rikulo 團隊。我們曾發表多個 Dart 函式庫,涵蓋 UI 框架、UI 元件庫、網頁伺服器、訊息伺服器、資料庫客戶端等。
2011 年 Dart 剛問世時,我們就對它的未來價值感到興奮,並立刻在幾個小型專案裡試用 Dart。後來,我們進一步嘗試以 Dart 為主力打造一整套應用程式。在此想與大家分享一些經驗,希望能為各位的 Dart 開發旅程提供一些參考。
選擇 Dart 的理由非常多,對我們而言,最關鍵的幾項是:
當然,選擇 Dart 也有一些缺點:
有了強型別的支援,用 Dart 開發遠比 JavaScript 來得可靠。同時,Dart 比 Java 精簡得多,有時候(例如使用函式運算式)甚至比原生 JavaScript 還精簡。整體來說,使用 Dart 的體驗相當舒服,只是有幾點仍需留意:
在 Dart VM 進駐 Chrome 之前,你勢必得把成品編譯成 JavaScript 才能交付。雖然能編譯為 JavaScript 的語言不計其數,但 Dart 仍憑藉幾項額外優勢脫穎而出。
Dart 在伺服器端從來不是 Dart 社群裡的熱門話題,但我們認為 Dart 是後端程式語言的有力候選,原因如下:
Quire 大約匯入 30 個函式庫,其中 10 個來自社群,其餘則由 Dart 團隊釋出。Dart 老手或許會猜測其中也包含 AngularDART 與 Polymer.dart,但其實這兩者都不在我們的清單上。
我們沒有採用 AngularDART,理由是:
我們同樣沒有採用 Polymer.dart,原因是:
我們前端技術堆疊的基石是 DQuery 與 Bootjack,兩者皆為 Rikulo 團隊釋出的開源專案:
我們以這樣的方式建構應用程式堆疊,藉此沿用我們在 JavaScript 世界累積下來的知識與技能。
Stream 是我們以純 Dart 撰寫的網頁伺服器,內建路由、過濾器、伺服器端 MVC 等能力。Stream 與事件迴圈模型契合得天衣無縫,撰寫請求處理器就只是把一連串非阻塞程序串接起來,比起傳統的多執行緒模型,不只更具生產力,過程也更愉快。我們同時透過 nginx 來擴充網頁服務並處理 HTTPS,再把實際請求轉交給 Stream。在這樣的架構下,我們可以個別啟動或停用 Dart VM、升級伺服器,而不會中斷使用者的操作。
我們在使用 Dart 的過程中累積了愉快的經驗,也期待 Dart 社群帶來更多精彩的進展。最後,如果你好奇 Dart 究竟能做到什麼程度,歡迎來玩玩我們的應用程式 Quire。它是免費的!

從這篇文章寫成至今,Dart 語言與 Quire 的程式庫都有了長足的演進。Dart 2.0(健全的型別系統)於 2018 年登場,Dart 3.0(null safety、records、patterns)於 2023 年問世,Flutter 也徹底改變了跨平台 UI 的版圖。但上述記錄下來的核心架構決策,其禁得起時間考驗的程度,遠比你預期得高。
前後端共用強型別,至今依然回本。 強型別系統能在編譯期攔下的執行期錯誤,今日仍是同樣的執行期錯誤。JavaScript 透過 TypeScript 走到了一半,但能做到端對端完全型別化的堆疊仍屬罕見。Simon 當年提到的那類錯誤(無數細小的失誤),到了今天仍然是無型別堆疊在正式環境中所出的同一類錯誤。
前後端共用資料模型,至今仍能省下工作量。 那種「兩套模型各自漂移」的問題(一份在 JS、一份在 Python,悄無聲息地偏離),在 2026 年依然存在,與 2014 年如出一轍;解方(端對端使用同一種語言)也同樣沒有變。TypeScript-on-Node 的團隊建構 Quire 風格的架構,正是出於同樣的理由。
對網頁伺服器而言,事件迴圈仍勝過多執行緒。 Node、Deno、Bun,以及 Dart 自家的 Stream 模式,全都站在同一邊。這個論點每隔幾年就被重新討論一次,最後仍回到同一個結論。
Tree shaking 的重要性只增不減。 2014 年,Dart 的 tree-shaking 編譯器是顯著的優勢;到了 2026 年,這在任何以 JS 為輸出目標的建置管線中都已是基本盤。Webpack、Rollup、esbuild、Vite 全都支援。觀念站得住腳,工具則一路追上。
2014 年對 ShadowDOM 的疑慮,多半已不復存在。 Polymer.dart 已被棄用,Web Components 也走向成熟。Simon 當年提出不使用 Polymer 的理由(樣式注入、與框架共存),後來都被瀏覽器平台逐一解決。但更普遍的原則(不要把正在試水溫的框架放在正式應用程式的核心)到了 2026 年依然適用,無論當下「正夯」的框架是哪一個。
替一個會運作多年的應用程式挑選語言堆疊,是少數一旦做下去就難以回頭的工程決策。團隊踩雷時,最常出現以下四種模式。
1. 預設選擇社群最大的語言。 JavaScript 確實擁有最龐大的社群,但「最大」並不等於「最契合你的問題」。一個強型別、工具完善但社群較小的語言,表現可以勝過一個龐雜卻保證薄弱的生態系。社群規模當然重要,但它絕不是唯一的考量。
2. 選擇前後端使用不同語言的堆疊。 每一份重複的資料模型,都是一顆未爆彈。後端用 Ruby、前端用 JS 的團隊,會永遠背著這份代價。能在前後端共用同一種語言(Dart、TypeScript、Kotlin)的團隊,等於避開整類錯誤。
3. 在新技術尚未穩定前就搶先採用。 Quire 團隊在 2014 年沒有採用 AngularDART 與 Polymer.dart,因為當時兩者在架構上都還有未解的問題。後來 AngularDART 大幅轉向,Polymer 被棄用。更普遍的原則是:在把應用程式核心壓在某個框架上之前,先讓它在大型正式環境中證明自己。這個原則到 2026 年仍然適用,無論當下「正夯」的框架是哪一個。
4. 為了搶短期速度而捨棄型別系統。 無型別語言在開發第一週的感覺確實比較快。但到了第六個月,省下來的時間早已加倍償還在除錯上。曾在規模化情境下同時體驗過無型別與型別化堆疊的工程團隊,幾乎沒有人會主動倒退回去。
Quire 團隊在 2014 年押注 Dart,事後看來相當合理——並不是因為 Dart 後來稱霸(它沒有),而是因為當初評估時所依據的條件(強型別、前後端共用、事件迴圈、tree shaking)在接下來的十年裡逐漸成為業界共識。真正歷久彌新的,並非那些具體工具的選擇,而是背後的工程原則。每當要在不確定中挑選語言時,這個道理多半成立:請依據十年後仍能說得通的原則來選,而不是憑今日可量的人氣。
前後端皆採用 Dart。整個應用程式約有 54,000 行 Dart 程式碼,匯入約 30 個函式庫。
因為強型別、類別式繼承模型,以及前後端共用同一種語言。Dart 也比 JavaScript 更早提供幾個現代特性。
團隊希望對 DOM 有比 AngularDART 的繫結機制更細膩的掌控,而且 Quire 的架構設計與 Angular 的邏輯不合。Polymer.dart 則是因為當時的 ShadowDOM 與 Bootstrap 這類以選擇器為主的框架相衝突而被排除。Polymer 後來被棄用,也驗證了這個決定。
兩者都是 Rikulo 團隊(也就是 Quire 的工程團隊)釋出的開源函式庫。DQuery 是 jQuery 對 Dart 的部分移植,聚焦於事件委派;Bootjack 則是 Bootstrap 3 的完整移植,CSS 與 API 幾乎完全一致。
它是 Quire 以純 Dart 撰寫的網頁伺服器,採用事件迴圈模型運作,並內建路由、過濾器與伺服器端 MVC。Quire 將 Stream 部署在 nginx 之後,由 nginx 負責擴充與 HTTPS。