编译器 API
当你自己的脚本或构建系统需要管理生命周期时,使用 createCompiler。Vite 和 Next 共用相同
的编译器行为,但每个创建出的实例都有自己的记录、队列和高亮器。
创建并关闭编译器
import { createCompiler } from '@amamo/mdx'
import amamo from './amamo.config.mjs'
const compiler = await createCompiler(amamo)
try {
const result = await compiler.build()
console.log(result)
} finally {
await compiler.dispose()
}创建阶段会归一化配置,并在启用高亮时初始化 Shiki。直到第一个需要原生 batch 的 build()
或 transform(),原生绑定才会被加载。
interface ICompiler {
build(): Promise<IBuildResult>
dispose(): Promise<void>
remove(file: string): Promise<number>
transform(file: string): Promise<ITransformResult>
}同一编译器上的操作会串行执行。并发的 build() 共用一次进行中的构建,增量操作在队列中等待。
build()
const result = await compiler.build()一次完整构建会:
- 按确定性顺序遍历所有集合。
- 推导 locale、slug 和 key,并拒绝重复 key。
- 读取全部源码和可选的最后修改时间。
- 复用兼容的缓存记录,或执行 Rust/Shiki 编译流水线。
- 用完整结果替换编译器的内存记录集。
- 写入变化的 manifest 和共享生成文件,再清理过期缓存。
interface IBuildResult {
cached: number
compiled: number
discovered: number
outputsWritten: number
}outputsWritten 统计字节发生变化的输出文件。没有变化的 warm build 可以返回 0,并保持所有
输出文件的修改时间不变;缓存记录写入不计入这个数字。
transform(file)
const result = await compiler.transform('/absolute/path/content/posts/hello.mdx')transform 编译一个属于集合的文件,替换它的记录,重写受影响的共享产物,并清理不在当前
编译器状态中的缓存记录。
interface ITransformResult {
cached: boolean
code: string
map: null
outputsWritten: number
record: IDocumentRecord
}code是编译后的 JavaScript 模块体。map目前始终为null。record.frontmatter包含完整的、通过校验的 frontmatter 对象。record.derived包含启用的阅读时间和最后修改时间。record.hash是源字节的 BLAKE3 digest。record.cacheKey还包含配置、平台、路径和可选修改时间元数据。record.diagnostics包含成功结果的 warning,例如warn策略下的媒体缺失。
请使用绝对路径。相对路径从进程工作目录解析,不会自动从 config.root 解析。
当共享产物必须保留所有文档时,请先运行
build()。在全新编译器上直接调用transform(), 会创建只包含该文件的状态。
remove(file)
const outputsWritten = await compiler.remove('/absolute/path/content/posts/deleted.mdx')remove 删除这个编译器已经知道的记录,更新共享产物,清理缓存,并返回变化的输出文件数量。
未知路径是 no-op,返回 0。
dispose()
await compiler.dispose()释放操作会清理编译器资源并销毁 Shiki。它是幂等的;之后再调用 build、transform 或 remove
会以 AMAMO_COMPILER_DISPOSED 拒绝。
错误与诊断
不同边界的失败形式不同:
- 非法 object schema 或其它配置数据会抛出
TypeError,消息中带AMAMO_CONFIG_*code。 - 原生解析、schema、媒体、缓存和 manifest 失败会变成名为
AmamoMdxError的错误,并带diagnostics数组。 - Shiki 初始化和未知语言失败是普通
Error。 - 文件系统、watcher 和 Next loader 失败也是普通
Error。
IDiagnostic 从 @amamo/mdx 导出:
interface IDiagnostic {
code: string
file?: string
hint?: string
message: string
range?: {
start: { line: number; column: number; offset: number }
end: { line: number; column: number; offset: number }
}
severity: 'error' | 'warning'
}这个类型为 range 和 hint 预留了位置,但目前不会填充它们。batch 会在第一篇失败文档或
第一个失败阶段停止,而不会聚合全部失败。Schema 消息可能引用提交的 frontmatter 值。
共享生成文件
构建完成后,generatedDirectory 包含:
collections.mjs:按顺序排列的{ derived, frontmatter, key, locale, slug, load }数组。collections.d.ts:集合注册表的配套声明产物。index.json:Next loader 使用的源码路径、缓存键、缓存目录和配置指纹。
注册表的 load() 会 import 原始 MDX 源码。宿主 bundler 仍需配置 Vite 插件、Next loader 或
其它兼容的 MDX transform。