星號還沒配對,字還在吐:一題 Markdown 流式解析面試題,把前端圈問醒了
一道關於大模型流式輸出 Markdown 如何避免標籤截斷的面試題,在開發者社羣流傳,本文以問答體拆解全量重渲染為何不夠,以及延遲渲染、代碼塊上下文與 remend 三條思路。
做 AI 對話頁的工程師,大概都遇過同一個畫面:模型邊吐字,頁面邊渲染,前面一段還好好的,突然星號變成了純文字,程式碼塊閃了一下又重排。這件事平常只活在開發者的除錯現場,但 2026 年 9 月 7 日,一篇掛著面試官口吻的技術長文在掘金流傳開來,把這個日常瑣事變成了一道正式考題:「Markdown 流式解析如何避免標籤截斷?直接重新讓 marked 全部渲染,行不行?」
這篇長文的作者署名「秋天的一陣風」,十天左右累積了數十則收藏與轉發。它吸引人的地方不在於給出多新奇的框架,而在於把一個多數人憑感覺回答的問題,拆成一條能被追問、也能被驗證的思路。本文以問答體整理這場討論的幾個關鍵環節,順便看看它為什麼剛好卡在這個時間點發酵。
Q1:這題在問什麼?面試現場長什麼樣子?
按原文還原的對話,開場通常很平淡。面試官問大模型流式輸出 Markdown,前端怎麼解析渲染;候選人答用 marked 或 markdown-it,每來一個 chunk 就把累積字串全量 parse 一遍,再把 HTML 寫進 DOM。
追問從第二句開始。如果流式過程中,鏈結寫到一半斷住,或者粗體停在還沒配對的狀態,解析結果和 DOM 會怎麼變?整篇重 parse,就能消掉閃爍嗎?
作者的判斷很直接:前半句能交差,後半句一追,差距就出來了。答案是「不行」。全量重渲染解決的是更新頻率,沒有解決「當前字串是不是一份可穩定解析的 Markdown」。
這個區分是整篇討論的地基。很多人把流式渲染的問題理解成效能問題,重畫太多次所以閃;但真正的病根在於,串流在任意時刻都可能停在「只開了頭、還沒閉合」的狀態,而 Markdown 的語法恰恰依賴成對標記才能穩定產出節點。
Q2:為什麼「等配對」這麼難?
把幾種常見語法並排看,原因就很清楚。粗體要湊齊兩組星號,行內程式碼要湊齊兩個反引號,圍欄程式碼塊要等到結尾的三個反引號,鏈結要等到右括號。解析器看到開頭而看不到結尾時,只能把星號、反引號、半截 URL 當普通字元處理,或者產出一個下一秒就會被推翻的中間結構。
更麻煩的是串流側的特性。前端拿到的是不斷變長的 buffer,在某一幀裡,你無法根據「後面會不會補上閉合符」做決定。閉合符可能在下一個 chunk 就到,也可能要再等幾十個 token。使用者看到的於是是:先當純文字,突然變成程式碼塊,再整段重排。閃爍就是這樣長出來的。
這類情境題在這兩年的前端面試裡越來越常見。先前流出的美團 Agent 一面面經裡,同樣是把考題藏進「如果讓你設計」的追問裡。差別在於美團那場問的是行程規劃 Agent,這篇問的是更貼近每一個 AI 對話頁的渲染細節。
Q3:第一條路,延遲渲染是什麼意思?
原文給出的工程手段有三層,第一層叫延遲渲染。做法是維護一個 buffer,每個 chunk 進來先累積,然後檢查末尾是否存在未閉合語法:圍欄符號出現次數是奇數、星號不成對、方括號還沒配對到完整鏈結,這些都算。
若尾巴未閉合,只把前面已完整的前綴交給解析器,碎片繼續留在緩衝區,等後續 chunk 補齊閉合後再放出。使用者從此看不到「先當文字、再變程式碼塊」的跳變。
用一句話概括它的定位:延遲渲染解決的是「什麼時候把哪一段送進解析器」,是後續所有進階方案的基礎。
Q4:程式碼塊為什麼是重災區?
只靠延遲渲染還不夠。對話場景裡,圍欄程式碼塊往往是閃爍最嚴重的地方,原因是語法角色的錯位。程式碼內容經常出現星號、底線、井號、大於符號,這些在正文裡是 Markdown 標記,在程式碼裡只是普通字元。若結束圍欄還沒到,解析器仍按正文規則掃描,就會把註解、正則、列表符號誤解析成標題、強調、引用。結構一旦錯亂,等閉合到齊後又要整段糾正,閃爍加倍明顯。
原文給的解法是在詞法層維護一個狀態標記,例如 inCodeBlock。狀態為否時按正常規則處理,遇到三個反引號就轉為是;狀態為是時,後續字元一律按純文字輸出,暫時關閉正文語法,直到再次遇到三個反引號才轉回。這是一種上下文鎖定,實作成本低,對穩定性的幫助卻不小。
Q5:有沒有反過來的做法?先畫再修?
有。延遲渲染選擇「先不畫」,另一條路是「先畫,但先把字串修到可解析」。原文點名了 Vercel 在 streamdown 專案中拆出的 remend,做的正是後者:在送進解析器之前,把未閉合的語法主動補全,讓每一幀的字串都是一份結構完整的 Markdown。
兩條路的取捨頗值得玩味。延遲渲染換來穩定,代價是內容會晚幾幀才出現;remend 換來即時,代價是渲染的內容可能和模型最終輸出有些微出入。對強調「逐字打出來」體驗的產品來說,這個取捨本身就是產品決策,而不是純技術判斷。
Q6:為什麼這篇文章剛好在這個時候被傳開?
時間點不是偶然。AI 對話頁如今幾乎是所有應用的標配介面,「模型邊吐字邊渲染 Markdown」從加分項變成了基本盤。當一個技術點從少數產品的功能變成整個行業的公共介面,圍繞它的面試題、原始碼解析、方案比較就會自然長出來。這篇長文能被轉發,靠的正是它把一個大家都踩過、卻很少講清楚的坑,講成了一條有先後順序的思路:先理解成對標記的根因,再用延遲渲染控制送審時機,用上下文鎖定處理程式碼塊,最後視產品需求決定要不要先修再畫。
對正在準備面試的人來說,這篇文章的價值或許不在於背下三個方案名詞,而在於示範了一種回答姿勢:先指出全量重渲染解決了什麼、沒解決什麼,再沿著病根往下走。面試官問的從來不是「你會不會用 marked」,而是當答案被追問第二句、第三句時,你手上的地圖還剩多少。
至於那個開場問題的標準答案,繞了一圈其實回到了最樸素的一句:先問字串完整了沒,再問要怎麼畫。
主題