3.3 KiB
Milkdown 自定义节点上下文经验
更新日期:2026-04-30
背景
知识库正文区域打开后白屏,控制台报错:
MilkdownError: Context "nodes" not found, do you forget to inject it?
调用栈指向 KnowledgeBaseContent 打开知识库工具后的正文渲染链路。实际故障点不在知识库数据加载,而在 MarkdownEditor 挂载 Crepe/Milkdown 时注册自定义节点插件。
根因
Milkdown 的 $nodeSchema() 返回的是一组插件:
schema.ctx:注入节点 schema factory 所需的上下文schema.node:读取schema.ctx,再把节点写入 Milkdown 的nodesCtx
因此如果手动拆开注册,顺序必须是:
schema.ctx,
schema.node,
view,
本次两个自定义插件曾写成 node 在 ctx 前:
markdownImageBlockSchema.nodeassetEmbedSchema.node
当 Milkdown 初始化 schema 时,node 插件会先尝试读取尚未注入的 ctx,导致初始化链路异常;知识库正文默认开启 enableAssetEmbeds,因此会稳定走到这条路径。
修复思路
最小修复只调整插件注册顺序,不扩大重构:
export const markdownImageBlockPlugins = [
markdownImageBlockSchema.ctx,
markdownImageBlockSchema.node,
markdownImageBlockView,
].flat();
export const assetEmbedPlugins = [
remarkAssetEmbed,
assetEmbedSchema.ctx,
assetEmbedSchema.node,
assetEmbedView,
].flat();
这样保持了现有 Markdown 图片和素材嵌入能力,不改变知识库编辑器的外部 API。
验证
本次做了三类轻量验证:
pnpm nx run drawnix:typecheck
- 类型检查通过
- 用 JSDOM 直接创建 Crepe + 自定义
$nodeSchema插件,确认ctx -> node -> view顺序可正常初始化 - 在本地
localhost:7200打开知识库,控制台未再出现Context "nodes"错误
.npmrc 中缺少 NPM_TOKEN 只会产生 pnpm warning,不影响类型检查结论。
经验
1. 不要随手拆散组合插件
Milkdown 的 $nodeSchema()、$remark() 这类 helper 通常返回带依赖顺序的插件组合。能整体 .use(schema) 时优先整体使用;必须拆开时,要确认每个子插件的上下文依赖。
2. 自定义节点注册顺序要固定
推荐约定:
remarkPlugin,
nodeSchema.ctx,
nodeSchema.node,
nodeView,
inputRules,
commands,
其中 ctx 永远在读取它的 node、view、command 之前。
3. 编辑器白屏优先查插件链
遇到 Milkdown/Crepe 白屏时,排查顺序:
- 是否重复注册同名 node/mark
$nodeSchema.ctx是否在$nodeSchema.node前view是否等待 schema ready 后才读取 node type- 是否存在多份
@milkdown/core或@milkdown/ctx - 是否在 editor created 前调用
editorViewCtx
4. 同名扩展要单独立项
当前自定义 image-block 与 Crepe 内置 ImageBlock 存在同名扩展关系。最小修复只处理初始化顺序;后续若继续治理,建议单独评估:
- 扩展内置
imageBlockSchema - 或关闭
CrepeFeature.ImageBlock后由自定义插件完整接管
这类变更会影响图片上传、caption、resize、素材库插图等体验,不应混入白屏热修。
一句话结论
Milkdown 自定义节点不是普通数组拼接,ctx 是 schema 初始化的地基;先注入上下文,再注册节点,最后挂 view。✅