如果 Markdown 和 React 生了个孩子,那它一定叫 Code Hike。
一、什么是 Code Hike?
Code Hike 是一个开源库,它的核心使命极其清晰:在 Markdown 的写作体验和 React 的表现力之间架一座桥。
当你写技术博客、文档、教程的时候,通常会面临一个两难选择:
- 纯 Markdown:写得爽,但排版受限,代码块千篇一律,交互为零。
- 纯 React:表现力无限,但写内容要写 JSX,内容与样式耦合,维护噩梦。
Code Hike 的思路是------小孩子才做选择,成年人全都要。它通过在 Markdown 中注入轻量级的"装饰语法",将内容结构化,然后在 React 组件层自由渲染。
bash
npx create-next-app -e https://github.com/code-hike/v1-starter
一句话定位:Code Hike = MDX 插件 + 代码高亮引擎 + 注解系统 + 布局工具集。
项目由 Rodrigo Pombo (pomber) 创建,入选了 GitHub Accelerator 首批扶持项目 ,并获得 Meta、Vercel、Speakeasy 等公司赞助,目前采用 MIT 协议 开源。
二、核心设计理念:内容与呈现彻底分离
Code Hike 的设计哲学可以概括为一句话:
Markdown 负责"是什么",React 负责"怎么呈现"。
2.1 传统 MDX 的问题
传统 MDX 允许你在 Markdown 中嵌入 React 组件,这确实增强了表现力,但它把内容和呈现混在了一起:
mdx
# 我的博客
<Callout type="warning">
注意:以下内容需要 Node.js 18+
</Callout>
<CodeBlock title="hello.js" lineNumbers>
```js
console.log("hello")
```
这种写法的痛点很明显:每次换样式就要改内容文件;非技术作者看到 JSX 就头大;同一份内容在不同平台(博客、文档站、Slide)要写不同的组件。
2.2 Code Hike 的做法
Code Hike 引入了一个关键概念------装饰器(Decorators) 。你在 Markdown 元素前加一个 !name 标记,Code Hike 的 MDX 插件会把这些元素解析成结构化的 Block 对象,然后作为 props 传给 React 组件。
你写在 Markdown 里的:
md
## !!steps 初始化项目
首先安装依赖
## !!steps 配置插件
在 next.config 中添加 Code Hike
## !!steps 开始写作
创建你的第一篇 .mdx 文件
Code Hike 帮你转换成的数据结构:
js
{
steps: [
{ title: "初始化项目", children: <p>首先安装依赖</p> },
{ title: "配置插件", children: <p>在 next.config 中添加 Code Hike</p> },
{ title: "开始写作", children: <p>创建你的第一篇 .mdx 文件</p> },
]
}
你的 React 组件可以这样渲染:
tsx
export function Tutorial({ steps }) {
return (
<div>
{steps.map((step, i) => (
<StepCard key={i} number={i + 1} title={step.title}>
{step.children}
</StepCard>
))}
</div>
)
}
内容和呈现完美解耦------同一份 Markdown 可以用完全不同的 React 组件渲染成博客、文档页、Slide、甚至视频脚本。
三、Block 系统:给 Markdown 加上"类型系统"
Block 是 Code Hike 最核心的抽象,它给"无结构"的 Markdown 注入了结构。
3.1 装饰语法一览
| 装饰器 | 用途 | 示例 |
|---|---|---|
!name |
标记单个元素 | ## !intro 简介 |
!!name |
收集为数组 | ## !!steps 第一步 |
不加 ! |
普通内容 | 传给 children |
支持的被装饰元素:
- 标题 (
##、###等):!name后的文字作为title - 图片 :
→ 提取alt、url、title - 代码块 :```````js !code main.js ````→ 提取
lang、meta、value - 段落 :
!author Tolkien→ 段落文本作为值
3.2 嵌套 Block
利用标题层级天然实现嵌套:
md
<MyComponent>
魔戒的力量
## !master
至尊魔戒
### !!rings 精灵
三枚戒指
### !!rings 矮人
七枚戒指
### !!rings 人类
九枚戒指
</MyComponent>
解析结果:
js
{
master: {
title: "至尊魔戒",
children: <p>至尊魔戒</p>,
rings: [
{ title: "精灵", children: <p>三枚戒指</p> },
{ title: "矮人", children: <p>七枚戒指</p> },
{ title: "人类", children: <p>九枚戒指</p> },
]
}
}
3.3 类型安全:Zod Schema 验证
Code Hike 强烈推荐配合 Zod 做 Schema 校验,这是它区别于其他 Markdown 方案的一个亮点:
tsx
import { z } from "zod"
import { Block, CodeBlock, ImageBlock, parseProps } from "codehike/blocks"
const Schema = Block.extend({
author: z.string(),
cover: ImageBlock.optional(),
code: CodeBlock,
steps: z.array(Block),
})
export function MyPage(props: unknown) {
const data = parseProps(props, Schema)
// data 现在有完整的 TypeScript 类型推导!
// data.author → string
// data.code → { lang, meta, value }
// data.steps → { title, children }[]
}
这意味着:你的 Markdown 内容是类型安全的。结构不符合 Schema?编译阶段直接报错,零运行时意外。
3.4 根级 Block
如果不想包裹组件,可以直接在 .md 文件中使用装饰器,然后用 parseRoot 解析:
tsx
import { parseRoot } from "codehike/blocks"
import Content from "./content.md"
const Schema = Block.extend({
features: z.array(Block),
})
export default function Page() {
const data = parseRoot(Content, Schema)
return <FeatureList features={data.features} />
}
四、代码块系统:不止于高亮
如果说 Block 系统是 Code Hike 的骨架,那代码块系统就是它的灵魂。
4.1 自研高亮引擎:Lighter
Code Hike 没有使用 Shiki 或 Prism,而是自己写了一个高亮引擎------lighter。
为什么造轮子?核心原因是 Code Hike 的注解系统需要对 token 级别的精细控制。Shiki 的 transformer 机制操作的是 AST,而 Code Hike 的注解是 React 组件------粒度不同、理念不同。
内置 22 种主题:
dark-plus github-dark github-light dracula monokai nord one-dark-pro solarized-dark solarized-light min-dark min-light material-* 系列等。
还支持 CSS 变量驱动的明暗主题 (github-from-css、material-from-css)和自定义主题(可通过 Theme Editor 在线编辑)。
支持 211 种语言:从 Assembly 到 Zig,从 GraphQL 到文言文,覆盖面相当广。
4.2 注解系统(Annotations):在代码里"画重点"
这是 Code Hike 最具差异化的功能。你可以通过代码注释给代码块添加注解,然后用 React 组件来渲染注解效果。
基本语法:
js
// !name(起始行:结束行) query参数
// !name[起始列:结束列] query参数
两种注解类型:
| 类型 | 作用范围 | 语法 | 场景 |
|---|---|---|---|
| 块注解 (Block) | 多行代码 | // !highlight(1:3) |
高亮一个函数 |
| 行内注解 (Inline) | 行内 token | // !mark[5:9] |
标记一个变量 |
4.2.1 示例:高亮标记
js
// !mark(2:3)
function calculate(input) {
const result = process(input) // ← 这两行被标记
return result * 2 // ←
}
4.2.2 示例:正则匹配
不用手动数行号列号,直接用正则:
js
// !border[/ipsum/g] orange
const lorem = ipsum == null ? ipsum : 1
dolor = lorem - sit(dolor)
所有匹配 ipsum 的 token 都会被打上橙色边框。
4.2.3 示例:start/end 标记
js
const lorem = ipsum == null ? 0 : 1
// !highlight(start)
dolor = lorem - sit(dolor)
let amet = lorem ? consectetur(ipsum) : 3
// !highlight(end)
不用数行号,用标记对来圈定范围。
4.3 Handler 机制:把注解渲染成任意 UI
注解本身只是"元数据",真正让它们活起来的是 AnnotationHandler。
tsx
import { Pre, RawCode, highlight } from "codehike/code"
import type { AnnotationHandler } from "codehike/code"
const markHandler: AnnotationHandler = {
name: "mark",
Inline: ({ annotation, children }) => (
<span className="bg-yellow-200 rounded px-0.5">{children}</span>
),
}
export async function Code({ codeblock }: { codeblock: RawCode }) {
const highlighted = await highlight(codeblock, "github-dark")
return <Pre code={highlighted} handlers={[markHandler]} />
}
Handler 可以自定义的渲染层面:
| 组件 | 作用 |
|---|---|
Block |
渲染被注解包裹的代码块(适合折叠、callout) |
Inline |
渲染被注解标记的 token(适合高亮、tooltip) |
Line |
自定义每一行的渲染(适合行号、缩进指示) |
Token |
自定义每个 token 的渲染 |
AnnotatedLine |
自定义被注解行的渲染 |
AnnotatedToken |
自定义被注解 token 的渲染 |
Pre / PreWithRef |
自定义整个 <pre> 元素 |
4.4 注解变换(Transform)
你可以在 handler 中定义 transform 函数,在渲染前修改注解。这非常强大------一个注解可以拆成多个,行内注解可以转成块注解:
tsx
const callout: AnnotationHandler = {
name: "callout",
transform: (annotation: InlineAnnotation) => {
// 把行内注解转成块注解
return {
...annotation,
fromLineNumber: annotation.lineNumber,
toLineNumber: annotation.lineNumber,
data: { column: (annotation.fromColumn + annotation.toColumn) / 2 },
}
},
Block: ({ annotation, children }) => (
<>
{children}
<CalloutBubble column={annotation.data.column}>
{annotation.query}
</CalloutBubble>
</>
),
}
4.5 内置注解模式(Copy-Paste 即用)
Code Hike 的文档提供了大量可直接复用的注解实现:
| 注解 | 效果 | 复杂度 |
|---|---|---|
| mark | 高亮标记 token | ⭐ |
| border | 边框框住代码区域 | ⭐ |
| collapse | 折叠/展开代码块 | ⭐⭐ |
| callout | 代码旁的气泡注释 | ⭐⭐⭐ |
| tooltip | 悬浮显示 MDX 内容 | ⭐⭐⭐ |
| fold | 折叠特定匹配内容 | ⭐⭐⭐ |
| word-wrap | 自动换行 | ⭐ |
| line-numbers | 行号显示 | ⭐ |
| diff | diff 效果 | ⭐⭐ |
4.6 代码导入指令
直接从文件导入代码,避免复制粘贴:
md
```js
!from ./src/hello.js
```
代码块内容会被 ./src/hello.js 的文件内容替换,从此告别"示例代码与源码不同步"的痛点。
五、安装与配置
5.1 快速开始
bash
npx create-next-app -e https://github.com/code-hike/v1-starter
5.2 手动安装
bash
npm install codehike
在 next.config.mjs 中配置 MDX 插件:
js
import { remarkCodeHike, recmaCodeHike } from "codehike/mdx"
/** @type {import('codehike/mdx').CodeHikeConfig} */
const chConfig = {
components: { code: "Code" },
// 如果不支持 RSC,在此处指定主题:
// syntaxHighlighting: {
// theme: "github-dark",
// },
}
const mdxOptions = {
remarkPlugins: [[remarkCodeHike, chConfig]],
recmaPlugins: [[recmaCodeHike, chConfig]],
jsx: true,
}
5.3 框架兼容性
| 框架 | 支持程度 | 备注 |
|---|---|---|
| Next.js + Fumadocs | ✅ 最佳 | 推荐组合,完美支持 RSC |
| Next.js (App Router) | ✅ 完整 | 官方 Starter 使用的方案 |
| Nextra 3 | ✅ 可用 | 有官方模板 |
| Docusaurus | ✅ 可用 | 有官方模板 |
| Remotion | ✅ 可用 | 可用 Code Hike 做代码演示视频 |
| Astro | ❌ 不支持 |
六、Scrollycoding:杀手级布局
Scrollycoding 是 Code Hike 最具代表性的布局模式------滚动讲解与代码同步,广泛用于技术教程和代码 walkthrough。
基本结构:右侧固定代码块,左侧内容随滚动切换。每滚动到一个 Section,代码高亮/注解也随之切换。
mdx
<Scrollycoding>
## !!steps 初始化
项目初始化的第一步...
## !!steps 路由
接下来配置路由...
## !!steps 数据层
然后设置数据获取...
</Scrollycoding>
结合 Block 系统 + 代码注解,Scrollycoding 可以做到:
- 滚动到某一步时,自动高亮对应代码行
- 代码中嵌入 callout 气球注释
- 折叠非相关的代码区域
- 自适应移动端(stack 布局切换)
正是这种交互让 Code Hike 从一众 Markdown 工具中脱颖而出------它不是"更好看的代码块",而是把文档变成了一个交互式应用。
七、竞品对比
| 特性 | Code Hike | Shiki | Markdoc | MDX |
|---|---|---|---|---|
| 代码高亮 | ✅ 自研 Lighter | ✅ TextMate 引擎 | 需外部集成 | 需外部集成 |
| 代码注解 | ✅ 一等公民 | ⚠️ Transformer | ❌ | ❌ |
| 内容结构化 | ✅ Block 系统 | ❌ | ✅ Tags | ⚠️ 手动 |
| 类型安全 | ✅ Zod Schema | ❌ | ⚠️ | ❌ |
| 交互式布局 | ✅ Scrollycoding | ❌ | ❌ | ⚠️ 手动 |
| 文件导入 | ✅ !from |
❌ | ❌ | ❌ |
| 框架耦合 | React 专属 | 无耦合 | 无耦合 | React 专属 |
Code Hike 的真正优势 不在于"我能做",而在于"我做得极其顺手"。Shiki 也能做代码注解------但要写大量 transformer 代码;MDX 也能做结构化内容------但要手动组织组件树。Code Hike 把这些模式做了标准化封装,让它们成为一种"理所当然"的使用方式。
八、生态与应用场景
8.1 谁在用 / 适合谁
| 场景 | 为什么适合 |
|---|---|
| 大型文档站 | Block 系统让设计师和写作者并行工作,内容与 UI 分离 |
| 技术教程/Blog | Scrollycoding + 代码注解是技术写作的"黄金搭档" |
| API 参考文档 | 克隆 Shopify API Reference 就是例子 |
| 视频脚本/课程 | 配合 Remotion 生成代码演示视频 |
| Landing Page | 结构化的内容可以在不同页面用不同组件渲染 |
8.2 成功案例
- Shopify API Reference 克隆版:用 Code Hike 重现了 Shopify 精美的 API 文档 UI
- SwiftUI Tutorials 克隆版:复刻了 Apple 的 SwiftUI 交互式教程体验
- Code Hike 自身文档站 :codehike.org 全站用 Code Hike 构建
8.3 赞助商矩阵
Meta(Facebook 开源赞助)、Vercel(部署平台)、Speakeasy(API 工具)、ui.dev(前端培训)------这说明 Code Hike 不仅技术过硬,商业生态也在稳步成型。
九、总结与思考
为什么 Code Hike 值得关注?
-
它解决了一个真实且普遍的痛点:技术人员想写出好内容,但工具链要么太简陋(纯 Markdown),要么太繁琐(手写 React 组件)。Code Hike 找到了那条"刚刚好"的分界线。
-
注解系统是真正的差异化 :在代码注释中写
!mark然后自动渲染成高亮------这种体验一旦用了就回不去。它把"写代码注解"变成了写作流程的自然延伸,而不是额外的"排版工作"。 -
类型安全的内容系统:Zod Schema 验证让 Markdown 内容有了"类型约束"。这在多人协作的大型文档项目中意义重大------CI 里就能发现内容结构问题。
-
生态定位精准:不做框架(Docusaurus/Nextra 已经够好了),不做高亮器(但自己写了一个来支撑注解),只做"内容结构化 + 代码表现力"这一层。API 设计克制而优雅。
踩坑点与局限
- React 专属:这对 React 生态来说是优势,对 Vue/Svelte 用户是硬伤。
- Astro 不支持:Astro 的 MDX 处理方式与 Code Hike 的 remark/recma 插件链不兼容。
- 学习曲线:Block 概念 + Schema 定义 + Handler 编写,初学者需要一点上手时间。
- 文档建设中:v1.1.0 刚发布(2026.03),部分功能(如 Component Blocks)标记为 "Coming soon"。
一句话
Code Hike 不是另一个 Markdown 渲染器,它是 Markdown 的类型系统 + React 的渲染管线。如果你在做技术内容网站,它应该是你工具箱里的首选武器。
附录:关键链接
- GitHub 仓库 :https://github.com/code-hike/codehike
- 官方文档 :https://codehike.org/docs
- 在线体验 :StackBlitz Starter
- 主题编辑器 :https://themes.codehike.org/editor
- 示例仓库 :https://github.com/code-hike/examples
- Remotion 集成 :https://codehike.org/blog/remotion
- 高亮引擎 :https://github.com/code-hike/lighter