惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
Google DeepMind News
Google DeepMind News
云风的 BLOG
云风的 BLOG
WordPress大学
WordPress大学
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research
T
Tailwind CSS Blog
I
InfoQ
小众软件
小众软件
Recent Announcements
Recent Announcements
博客园 - 【当耐特】
The GitHub Blog
The GitHub Blog
大猫的无限游戏
大猫的无限游戏
美团技术团队
T
The Blog of Author Tim Ferriss
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
MongoDB | Blog
MongoDB | Blog
V
V2EX
J
Java Code Geeks
有赞技术团队
有赞技术团队
博客园 - 聂微东
B
Blog RSS Feed
博客园 - 司徒正美

V2EX

我用 AI 写代码,但终端管理反而成了累赘——于是我做了 codux [调研] 各位在公司都用什么 ide 和 agent 写代码? 老运维 share 一个运维平台 看到有公司考核 token 指标,很好奇大家上个月的 AI 账单是多少 GLM-Coding 调用持续报错: z.ai 的 Lite 套餐几乎无法使用,官方 Pro/Max 是否稳定? 现在还有什么渠道可以稳定安全地使用 Claude 吗? 上海漕河泾内推,本组有 2 个 hc,一个后端,一个前端,预算都是 20k 左右,不打卡,氛围好 如果 V2EX 上有一组不永久保存聊天记录(比如只保存 7 天或者 24 小时)的聊天室,那么会开启哪些有用或者有趣的可能? gemini cli 貌似挂了,一直返回 403 第一次在自媒体上赚到钱 收集了最近在使用的低价 GPT, Gemini,邮箱等 AI 会员的小店合集 讨论个大实话:现在企业还在说 AI 编程提效 20%, 30%的,真的太落后,没用懂 AI。因为包括很多前沿公司,已经狂奔到提效 200%-500%的情况 [招聘][远程][币安] 前端/后端/QA/iOS/Android 至少 3 年以上经验 目前有大量 HC 欢迎投递 Chatgpt Pro 用量用不完的可以开这些设置 面试的时候好像遇到钓鱼了,给各位避个坑 cursor 年续费 22 号到期, 自动续费是否还是老的计次套餐呢 被两件破事毁掉的一下午,琐碎的内耗消磨人的精力 使用 Planet 存储 Codex 的会话或者重要信息 如果业务部门领导不要你开发功能,而是要求你教会它用 claude code 开发功能,你会怎么做? 分享一个 MacOS 接绿联 CM818 USB 转 DP 转接器使用感受 我的 HR 朋友 10 年老 Java ,非全大专,大家帮忙看看简历 开源了一个 AI 口语练习工具,音素级发音评分,完全免费可自部署 V2EX 上有哪些你觉得很有趣、印象深刻的妹纸? 字节为啥不出个国内版 Vercel? 有在大马的朋友吗? 问个运营商问题 你们在有领导的公司大群发过的最大胆的消息是什么 公司裁员,目前没有工作。想试试摆摊,做一个移动鲜啤打酒车 我的硬盘 Memblaze Pblaze 5 Linux 下不识别,给 Linux 内核提交了补丁, AI 说有望被合并 只有我一个人觉得 codex 不好用?
今天发布了 Incremark 0.3.0:双引擎架构 + 完整插件生态, A...
1244943563 · 2026-01-08 · via V2EX

Incremark 0.3.0 发布:双引擎架构 + 完整插件生态,AI 流式渲染的终极方案

距离上次发帖已经过了一段时间,这段时间我一直在打磨 incremark ,今天正式发布 0.3.0 版本。这次更新的核心是双引擎架构——你可以在极速的 marked 和稳定的 micromark 之间自由切换,同时享受完整的插件生态。

先说结论

md 来源:本地随机抽取的 38 个文件,最大只有 18kb ,文件更大的时候,这个差距只会随指数拉大,没有专门写测试 markdown 文件,就拉了文档中的一些 md 以及使用 cursor 时候生成的一些文档。可查看文档看详细数据 详细数据

对比方案 平均优势 最大差距
vs Streamdown 6.1 倍 16.4x
vs ant-design-x 7.2 倍 18.9x
vs markstream-vue 28.3 倍 65.6x

基于 38 个真实 markdown 文档( 6,484 行,128.55 KB )的基准测试结果。

在线体验:

为什么要做双引擎?

上次发帖后收到很多反馈,主要集中在两个方向:

  1. "能不能更快?" —— 性能党
  2. "能不能支持 xxx 语法?" —— 功能党

这两个需求看似矛盾,但我找到了一个优雅的解决方案:双引擎架构

Marked 引擎(默认)—— 极速派

// 默认使用 marked ,可以省略
<IncremarkContent 
  :content="content" 
  :is-finished="isFinished"
  :incremark-options="{ engine: 'marked' }"
/>

特点:

  • 🚀 极速:针对流式场景深度优化
  • 🔧 自研扩展:我们为 marked 补齐了脚注、数学公式、自定义容器、内联 HTML 解析
  • Tree-shaking 友好:只打包你用到的功能

Micromark 引擎 —— 稳定派

<IncremarkContent 
  :content="content" 
  :is-finished="isFinished"
  :incremark-options="{ engine: 'micromark' }"
/>

特点:

  • 严格 CommonMark:100% 规范兼容
  • 🔌 丰富生态:直接使用 micromark/mdast 社区的所有插件
  • 🛡️ 稳定可靠:久经考验的解析器

Tree-shaking 优化

为了打包体积,我们做了 tree-shaking 优化:

// 默认只打包 marked (极速模式)
import { createIncremarkParser } from '@incremark/core'
const parser = createIncremarkParser({ gfm: true })

// 如果需要 micromark ,单独导入
import { MicromarkAstBuilder } from '@incremark/core/engines/micromark'
const parser = createIncremarkParser({
  astBuilder: MicromarkAstBuilder,
  gfm: true
})

这样你的项目只会打包你实际使用的引擎,不用担心 bundle 体积问题。

我们为 Marked 做了什么增强?

原生 marked 不支持很多 AI 场景常用的语法,我们通过自研扩展补齐了这些能力:

功能 原生 Marked Incremark Marked Streamdown
脚注 ✅ 完整 GFM 脚注
数学公式 $...$$$...$$ ⚠️ 部分
自定义容器 :::tip:::warning
内联 HTML 解析 ⚠️ 基础 ✅ 完整 HTML 树 ⚠️ 基础

这解释了为什么在某些基准测试中 Incremark 看起来"更慢"——因为我们在做更多的事情

文件 Incremark Streamdown 说明
footnotes.md 1.7 ms 0.2 ms Streamdown 跳过了脚注解析
FOOTNOTE_FIX_SUMMARY.md 22.7 ms 0.5 ms 同上

这是功能差异,不是性能问题。 Streamdown 跳过不支持的语法所以看起来更快,而 Incremark 完整解析了所有内容。

完整基准测试数据

为了让大家心里有底,我把 38 个测试文件的完整数据都放出来:

文件 行数 大小 Incremark Streamdown ant-design-x markstream-vue
introduction.md 34 1.57 KB 5.6 ms 4.5 ms 12.8 ms 57.5 ms
quick-start.md 71 3.14 KB 12.8 ms 26.7 ms 37.9 ms 214.2 ms
concepts.md 91 4.38 KB 12.0 ms 50.5 ms 51.5 ms 287.5 ms
comparison.md 109 5.39 KB 20.5 ms 94.9 ms 85.2 ms 418.9 ms
OPTIMIZATION_SUMMARY.md 391 8.90 KB 19.1 ms 208.4 ms 340.3 ms 1685.7 ms
BLOCK_TRANSFORMER.md 489 9.24 KB 75.7 ms 320.9 ms 619.9 ms 2268.7 ms
test-md-01.md 916 17.67 KB 87.7 ms 1441.1 ms 1656.9 ms 7927.9 ms

规律很明显:文档越长,Incremark 的优势越大。 这就是 O(n) vs O(n²) 的威力。

核心架构一览

┌─────────────────────────────────────────────────────────────────┐
│                      IncremarkContent                           │
│  (声明式组件,处理 content/stream 输入)                          │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│                      IncremarkParser                            │
│  ┌─────────────────────────────────────────────────────────────┐
│  │              双引擎 AST 构建器                                │
│  │  ┌──────────────────┐    ┌──────────────────┐               │
│  │  │  MarkedAstBuilder│    │MicromarkAstBuilder│              │
│  │  │  (默认,极速)     │    │ (稳定,严格)      │               │
│  │  └──────────────────┘    └──────────────────┘               │
│  └─────────────────────────────────────────────────────────────┘
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│                     BlockTransformer                            │
│  (打字机效果,字符级增量渲染)                                     │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │
│  │     Vue      │  │    React     │  │    Svelte    │          │
│  │    组件库     │  │    组件库     │  │    组件库    │          │
│  └──────────────┘  └──────────────┘  └──────────────┘          │
└─────────────────────────────────────────────────────────────────┘

最简使用方式

我们推荐使用 IncremarkContent 组件,这是最简单的方式:

<script setup>
import { ref } from 'vue'
import { IncremarkContent } from '@incremark/vue'

const content = ref('')
const isFinished = ref(false)

// 处理 AI 流式输出
async function handleStream(stream) {
  content.value = ''
  isFinished.value = false
  
  for await (const chunk of stream) {
    content.value += chunk
  }
  
  isFinished.value = true
}
</script>

<template>
  <IncremarkContent 
    :content="content" 
    :is-finished="isFinished"
    :incremark-options="{ gfm: true, math: true }"
  />
</template>

新增 Svelte 支持

应社区要求,我们新增了 Svelte 5 支持:

pnpm add @incremark/svelte
<script lang="ts">
import { IncremarkContent } from '@incremark/svelte'

let content = $state('')
let isFinished = $state(false)
</script>

<IncremarkContent {content} {isFinished} />

致 V2EX 社区

说实话,这个项目的 star 大部分应该都是 V2EX 的朋友们贡献的。上次发帖后收到了很多有价值的反馈:

  • @Leon6868 提的淡入动画 → 已实现 effect: 'fade-in'
  • @weareoutman 提的 memo render → 我们的 BlockTransformer 就是干这个的
  • 还有很多关于性能、兼容性的讨论

感谢大家的支持和反馈,让这个项目越来越好。

资源链接


如果觉得有用,欢迎 star ⭐️

有任何问题或建议,欢迎在评论区讨论,或者直接提 issue 。