markstream-vue:把「還在變動的 Markdown」當成渲染前提
Multi-framework streaming Markdown renderers for AI apps: Vue/Nuxt, React/Next.js, Svelte, and Angular, with Mermaid, KaTeX, stream-diffs code blocks, safe HTML, and low-jitter updates.
秒懂
- 它是什麼?
- Markstream 系列把串流中的 Markdown 視為一等公民,而不是把完整文件渲染器硬套在 token 流上。本文聚焦 Vue 3 套件 markstream-vue,說明它解決什麼、機制長什麼樣、2.0 升上去要付什麼代價,以及什麼情況下你根本不該用它。
- 適合誰用?
- 如果你的 Vue 3、Nuxt 或 VitePress 介面要邊收 token 邊顯示 Markdown,markstream-vue 值得進到評估清單;如果你只是把已經定稿的 Markdown 字串丟上畫面,marked 或 markdown-it 更省事,也不需要多一層串流狀態。要留在 1.x 的專案請明確鎖 markstream-vue@1,升級前先讀 1.x 到 2.0 的遷移指南,因為 2.0 移除了 Monaco 與 stream-markdown 這兩個程式碼區塊執行期,改用選配的 stream-diffs peer。
- 可以商用嗎?
- 可以。MIT 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
- 還在維護嗎?
- 有在維護。儲存庫最近一次提交在 3 天前。
- 用什麼語言寫的?
- 主要是 Vue(依據 GitHub 的語言統計)。
以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。
開源專案深度解析
串流中的 Markdown 不是「比較慢的 Markdown」
多數 Markdown 函式庫的輸入假設是:字串已經完整,解析、渲染、結束。marked、markdown-it、react-markdown 都是這個模型。README 把界線畫得很直白:完成品用它們,還在變動的內容才用 Markstream。
差別在於中間狀態。模型吐出 ``` 之後還沒吐語言標記,吐了 | 還沒吐完表格分隔列,吐了 $ 還沒收尾成 KaTeX 區塊。這些片段若走完整文件解析器,每一次增量都會被重新解讀成不同結構,畫面就會跳。Markstream 要處理的是「使用者正在讀的同時,內容仍在被改寫」這個狀態。
目標讀者因此相當明確:做 AI 聊天介面、SSE 或 WebSocket 輸出、長回覆、行動端 WebView 的 Vue 開發者。不是寫部落格產生器的人。
為什麼是套件家族,而不是一個渲染器
倉庫同時發布 markstream-vue、markstream-react、markstream-octane、markstream-svelte、markstream-angular、markstream-vue2,另外還有 markstream-core 與 stream-markdown-parser。README 的分工說明是:解析邏輯放進 stream-markdown-parser,串流控制工具放進 markstream-core,各框架套件負責把結果接到自己的渲染層。
這個切法有實際好處。若你的團隊同時有 Vue 與 React 前端,解析行為可以一致,不必各自調參數。但代價是版本對齊:近期 release 清單裡 markstream-vue、markstream-vue2、markstream-svelte 各自發出 2.0.11,跨套件的版本同步得自己盯。
Vue 2.6 與 2.7 被獨立成 markstream-vue2,而不是塞進同一個套件,這對還在維護舊專案的人是好事,但也意味著 Vue 2 那條線的更新節奏與 Vue 3 不同。
最小可跑的接法:一個元件、兩個 prop
Vue 3 的安裝指令是 pnpm add markstream-vue。README 給的元件範例裡,從套件匯入預設的 MarkdownRender,並且必須另外匯入 markstream-vue/index.css,樣式不是自動注入的。
使用面上只有兩個關鍵 prop:content 放目前累積的文字,final 放「串流是否結束」的布林值。範例同時示範了 mode="chat",也就是聊天情境的渲染模式。這種把「是否完成」顯式傳進去的設計,等於把串流狀態的所有權交回給呼叫端:元件不猜、不輪詢,只根據你給的 final 決定要不要收尾。
程式碼區塊的強化是另一件事。2.x 把 stream-diffs 列為選配 peer,只有在需要增強程式碼與 diff 區塊時才安裝。也就是說,基本渲染不需要它,diff 顯示是額外依賴。
2.0 是一次減法,減掉的是執行期
README 的 Stability 段落寫得很清楚:2.x 移除了 Monaco 與 stream-markdown 這兩個程式碼區塊執行期,需要增強程式碼區塊介面時改裝選配的 stream-diffs peer。
這是典型的體積換功能。把編輯器等級的執行期從核心拿掉,主套件的負擔下降,但原本依賴 Monaco 做程式碼高亮或互動的專案,升級時會直接踩空。README 明確要求升級前先讀 1.x 到 2.0 的遷移指南,理由是程式碼區塊執行期有變動。
維護者沒有把 1.x 砍掉。markstream-vue@1 指向維護中的 1.x 線,legacy 標籤保留同一條線,legacy-next 放 1.x 的預先版。對不能立刻改程式碼區塊實作的團隊,這是一條實際可用的退路,而不是口頭承諾。
要注意的是:2.x 的穩定介面被列為 MarkdownRender、串流內容渲染、預先解析節點渲染、安全 HTML 政策,以及選配的 Mermaid 與 KaTeX。這份清單之外的東西,穩定性沒有同樣的保證。
不完整語法、Mermaid 與 KaTeX 的漸進處理
README 把 Mermaid、KaTeX 與串流程式碼區塊並列為主要場景,並提到 progressive heavy blocks(重量級區塊漸進處理)。從這段描述可以推得設計意圖:圖表與數學式這類需要額外執行期的區塊,不應該在 token 還沒收尾時就急著完整渲染,否則每個增量都會觸發一次重算。
但這裡必須說清楚:README 沒有給出漸進處理的具體演算法、觸發時機或門檻值,也沒有提供任何延遲或抖動的量化數據。專案宣稱低抖動更新,我沒有安裝或執行過,無法驗證實際表現。若抖動量是你選型的關鍵指標,請用官方 playground 與 test 頁面自行量測,那是專案自己提供的可重現環境。
安全 HTML 政策同樣被列在穩定介面中,但 README 只給了名稱,沒有展開允許清單與過濾規則。要放使用者產生的內容進去的話,這部分得自己去看文件。
什麼時候它會變成錯的工具
第一種情況是內容根本不會變。如果 Markdown 是從檔案、CMS 或資料庫讀出來就定稿,串流狀態機只是多餘的中間層,marked 或 markdown-it 直接處理更單純,相依也更少。
第二種情況是你需要完整的 CommonMark 相容性或成熟的插件生態。README 自己把完成品導向那幾個函式庫,這個分工是專案主動劃的,不是外部批評。
第三種情況是你在非清單上的框架。Markstream 覆蓋 Vue 3、Vue 2、React、Svelte 5、Angular standalone 與 Octane。若你用 Svelte 4,README 對 Svelte 的安裝指令寫的是 pnpm add markstream-svelte svelte@^5,把 Svelte 5 寫成必要條件。
第四種是版本鎖定。若你的產品線已經深度綁定 1.x 的 Monaco 程式碼區塊行為,2.0 的移除會讓升級變成一次重寫,而不是換版本號。
與 marked、markdown-it、react-markdown 的實際差異
這三個函式庫的輸入契約是完整字串。它們的解析器可以假設文件有頭有尾,因此能一次算出正確的樹狀結構。你拿 token 流餵它們,等於每次增量都重新解析一份「目前為止看起來像什麼」的文件,結構會反覆變動。
Markstream 把「尚未完成」放進模型本身:呼叫端用 final 告訴元件串流是否結束,元件在未結束期間維持穩定的部分狀態。這是架構層級的差別,不是效能調校的差別。
README 另外列了與 vue-stream-markdown、Streamdown 的比較頁面。我沒有讀過那些頁面的內容,無法轉述它們的論點,只能說專案自己認為這兩個是同類競品,值得一起評估。
選型問題因此可以簡化成一句:你的 Markdown 在使用者閱讀期間會不會繼續變?會,就往 Markstream 這邊看;不會,就別引入串流狀態。
授權、維護成本與升級前該確認的事
授權是 MIT,套件層級也標示相同授權。MIT 允許商用與修改,但這不是法律意見,實際條款請自行閱讀倉庫中的 license 檔案。
維護面上,倉庫未封存,最近一次推送時間為 2026-09-09,同一天發出 markstream-vue、markstream-vue2、markstream-svelte 的 2.0.11。三個套件同日發版,說明這條線目前是同步維護的。
升級成本的主要來源是 2.0 的執行期移除,而不是 API 變動。專案提供了遷移指南,路徑在官方文件的 guide/migration-2-0。要留在 1.x 的指令是 pnpm add markstream-vue@1。
進到專案前值得先確認三件事:你的程式碼區塊是否依賴 Monaco 或 stream-markdown;你的渲染內容是否需要安全 HTML 政策的細節;你的框架版本是否落在支援清單內。這三項在 README 裡都有明確指向,但都沒有展開細節。
編輯結論
如果你的 Vue 3、Nuxt 或 VitePress 介面要邊收 token 邊顯示 Markdown,markstream-vue 值得進到評估清單;如果你只是把已經定稿的 Markdown 字串丟上畫面,marked 或 markdown-it 更省事,也不需要多一層串流狀態。要留在 1.x 的專案請明確鎖 markstream-vue@1,升級前先讀 1.x 到 2.0 的遷移指南,因為 2.0 移除了 Monaco 與 stream-markdown 這兩個程式碼區塊執行期,改用選配的 stream-diffs peer。
社群筆記