モデル / データセット
Simon-He95/markstream-vue avatar
Simon-He95/markstream-vue

markstream-vue 2.0.11 検討メモ: 生成途中の Markdown を描画する Vue 3 レンダラ

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.

スター 3,009フォーク 182VueMIT

ひと目でわかる

これは何?
LLM のトークンストリームのように刻々と書き換わる Markdown を、確定前の状態のまま破綻させずに描画することに特化した Vue 3 向けレンダラ。完成済み文書の変換を担う marked / markdown-it とは用途が分かれる。2.0 でコードブロック実行時が変わった点を含めて整理する。
誰に向いている?
採用を検討すべきなのは、Vue 3 / Nuxt / VitePress 上で LLM のトークンが届くたびに本文が書き換わる画面を持ち、その途中状態をユーザーに見せ続ける必要があるチーム。逆に、完成済みの Markdown 文書を一度だけ HTML に変換する用途や、サーバー側で静的生成を完結させたい構成では、marked や markdown-it で足りる。
商用利用できる?
できます。MIT は寛容なライセンスで、著作権表示とライセンス表示を残せば、使用・改変・販売が可能です。
今もメンテナンスされている?
されています。最後のコミットは 3 日前です。
何の言語で書かれている?
主に Vue です(GitHub の言語統計による)。

回答はプロジェクトの GitHub データ(最終同期:2026年9月15日)と当サイトの分析に基づくもので、法的助言ではありません。

オープンソース詳細解説

完成済み Markdown ではなく「書き換わっている最中」を描く

marked、markdown-it、react-markdown は、入力がすでに確定した Markdown 文書であることを前提にしている。パースして HTML を返し、それで仕事は終わる。問題は、LLM の出力が 1 トークンずつ届く場面だ。チャット UI に流し込まれる文字列は、毎フレームごとに末尾が伸びる。しかもその時点では見出しの記号が片方しか出ていない、コードフェンスが閉じていない、表の区切り行がまだ来ていない、といった壊れた状態が普通に発生する。確定前の文字列を通常のパーサに渡すと、閉じていないフェンスは後続の全文を飲み込み、途中の強調記法は生のアスタリスクとして画面に残る。Markstream が対象にしているのはこの状態で、README は用途を「Use Markstream when the Markdown is still changing while the user is reading it」と一行で切っている。読者が読んでいる最中に入力が変わり続ける、という条件が境界線だ。向いているのは AI チャット、LLM のトークンストリーム、SSE や WebSocket の出力表示、長い AI 応答の逐次表示、モバイルの WebView 上での描画。逆に、CMS の記事本文や README のレンダリングのように入力が固定された場面では、この種の仕組みは不要な複雑さになる。

パッケージ分割と、レンダラが受け取る 2 つの入力

リポジトリは単一のライブラリではなく、フレームワークごとのパッケージ群として構成されている。Vue 3 / Nuxt / VitePress が markstream-vue、React / Next.js / Remix が markstream-react、Svelte 5 が markstream-svelte、Angular standalone が markstream-angular、Vue 2.6 / 2.7 が markstream-vue2、Octane が markstream-octane。これとは別に、フレームワーク非依存の層として stream-markdown-parser(パースのみ)と markstream-core(ストリーミング制御のユーティリティ)が公開されている。つまり描画のロジックとパースのロジックが分離されており、任意の JS/TS アプリからパーサだけを呼ぶ道が用意されている。Vue 側の最小構成は README のサンプルが示すとおりで、MarkdownRender をデフォルトインポートし、markstream-vue/index.css を読み込む。テンプレートでは mode="chat"、:content に流れてくる文字列、:final にストリームが終わったかどうかの真偽値を渡す。この final が設計の要で、ストリーム中は閉じていないフェンスや途中の記法を「まだ完成していないもの」として扱い、final が真になった時点で確定した Markdown として描画し直す、という責務の切り分けが読み取れる。content と final という 2 つの入力だけで状態が表現されるため、呼び出し側は差分を計算する必要がない。

導入コマンドと、2.0 で消えたコードブロック実行時

Vue 3 系の導入手順は README に明記されている。pnpm add markstream-vue で本体を入れ、強化されたコードブロックと差分表示が必要な場合に限り stream-diffs を追加の peer として入れる。ここは任意であり、必須ではないと読める。注意が必要なのはバージョンの分岐だ。2.x は npm の latest タグで安定版として公開されており、1.x 系は markstream-vue@1 および legacy タグで保守が続いている。1.x のプレリリースは legacy-next タグに置かれている。2.0 では Monaco と stream-markdown のコードブロック実行時が削除された。README はこの変更を明示したうえで、アップグレード前に migration-2-0 のガイドを読むよう指示している。つまり 1.x でコードブロックの高度な表示に依存していたアプリは、2.x に上げるだけでは同じ画面にならない。移行ガイドを先に確認し、必要なら stream-diffs を足す、という順序になる。2.x の安定面として README が挙げているのは MarkdownRender、ストリーミング内容の描画、パース済みノードの描画、safe HTML ポリシー、そして任意の Mermaid / KaTeX だ。

低ジッター更新と、重いブロックの段階的描画

説明文が挙げる特徴のうち、実装上の判断が透けて見えるのは low-jitter updates と progressive heavy blocks の 2 つだ。トークンが届くたびに全文を再パースして DOM を丸ごと差し替える方式だと、読者の目には行が跳ねる。カーソル位置が動き、スクロールが揺れる。Markstream はこの跳ねを抑える方向で更新を設計していると説明されており、加えて Mermaid の図や KaTeX の数式のような描画コストの高いブロックを、ストリームの途中で無理に完成させず段階的に扱う。ここは文書化が薄い領域でもある。README と公開ドキュメントは機能の存在を示すが、どの程度のトークン到着間隔でどの程度の跳ねが残るのか、といった定量的な記述は与えられた資料からは確認できない。Mermaid や KaTeX を多用する画面では、この部分が体感品質を左右するため、採用判断の前に自分のデータで確かめる価値がある。safe HTML ポリシーについても、方針が存在することは読み取れるが、具体的にどのタグと属性が許可されるかの一覧は資料からは分からない。

marked / markdown-it との違いは速度ではなく前提

比較対象として README が名指ししているのは vue-stream-markdown、Streamdown、react-markdown、そして marked / markdown-it だ。このうち marked と markdown-it との差は性能ではなく入力の前提にある。両者は確定した Markdown 文字列を受け取り、HTML を返す。呼び出し側がストリームの途中経過を渡せば、壊れた記法がそのまま出力に現れる。Markstream はその途中経過を第一級の入力として扱い、final が偽の間は未完成状態として描画する。したがって、すでに完成した文書を変換するだけの用途では marked や markdown-it のほうが単純で、依存も少ない。react-markdown との比較も同じ軸で、React 側には markstream-react という対応パッケージが用意されている。README はこれらの比較ページへのリンクを並べているが、各比較の結論そのものは与えられた資料には含まれていない。判断するなら、リンク先の比較を自分で読み、自分のストリーム特性に当てはめる作業が要る。

向かない場面と、確認できない部分

この種のレンダラが不要になる条件ははっきりしている。入力が確定してから描画する画面、たとえばサーバー側で静的生成を完結させる構成や、ユーザーが送信し終えたテキストだけを表示する画面では、ストリーム対応の機構は使われないまま依存だけが増える。もうひとつの境界はフレームワークだ。Vue 2.6 / 2.7 を使っている場合は markstream-vue ではなく markstream-vue2 を選ぶ必要があり、パッケージ名が違う。Angular も standalone 向けと明記されているため、従来の NgModule 構成での動作は資料からは判断できない。加えて、公開されている情報からは確認できない事項がいくつかある。テストの網羅範囲、Mermaid と KaTeX を含めたときのバンドルサイズの実測、長時間ストリームでのメモリ挙動、そして 2.x 系のリリース間で API がどの程度動きうるか。README は 2.x を stable と表現しているが、これは npm のタグ付けと削除された実行時に関する記述であって、API の凍結を意味する保証ではない。これらは導入前に自分の環境で確かめるしかない。

ライセンスと保守コストの見積もり

ライセンスは MIT で、リポジトリの license ファイルと npm のライセンス表記が一致している。MIT は商用利用を含めて広く使える条件だが、具体的な義務の解釈は案件ごとに異なるため、ここでは法的助言はしない。実務上の論点はライセンスよりも保守のほうだ。パッケージが markstream-vue、markstream-react、markstream-svelte、markstream-angular、markstream-octane、markstream-vue2、stream-markdown-parser、markstream-core と分かれており、2.0.11 のリリースは複数パッケージで同日に並んでいる。つまりバージョンはそろえて運用される前提で、フレームワークをまたぐ構成を取ると追従対象がその分だけ増える。1.x と 2.x が並行して保守されている現状では、どちらの線に乗るかを最初に決めておかないと、後からコードブロック実行時の差分を埋める作業が発生する。upgrade のコストは migration-2-0 のガイドを読むことで事前に見積もれる。

編集部の結論

採用を検討すべきなのは、Vue 3 / Nuxt / VitePress 上で LLM のトークンが届くたびに本文が書き換わる画面を持ち、その途中状態をユーザーに見せ続ける必要があるチーム。逆に、完成済みの Markdown 文書を一度だけ HTML に変換する用途や、サーバー側で静的生成を完結させたい構成では、marked や markdown-it で足りる。導入前に確認すべきは 3 点ある。第一に、1.x から上げる場合は 2.0 で削除されたコードブロック実行時の影響範囲を migration-2-0 のガイドで洗い出すこと。第二に、強化されたコードブロックが必要なら stream-diffs を追加の peer として入れること。第三に、Mermaid と KaTeX を含む重いブロックの遅延描画が自分のレイアウトでどう振る舞うかを、共有テストページと同じ条件で先に確かめること。

公式情報源

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. Simon-He95/markstream-vue on GitHub
コミュニティノート

コミュニティノート