docmd 0.7.1 引入了一项重大架构改进——插件系统已提取到独立的 @docmd/api 包中,为生态系统带来了插件描述符、崩溃隔离和功能执行机制。

✨ 亮点

📦 @docmd/api — 专用插件包

插件 API 接口——钩子注册、WebSocket RPC 调度和源码编辑工具——现已拥有独立的专用包:@docmd/api

npm install @docmd/api

这将插件生态系统与构建引擎解耦,允许插件作者依赖轻量的 API 合约,而无需引入整个 @docmd/core 包。

向后兼容: @docmd/api 的所有导出均从 @docmd/core 重新导出。使用 @docmd/core 导入的现有代码无需修改即可继续使用。

🛡️ 插件描述符

插件现可导出 plugin 描述符,声明其身份和功能:

export default {
  plugin: {
    name: 'my-analytics',
    version: '1.0.0',
    capabilities: ['head', 'body', 'post-build']
  },

  generateScripts: (config, opts) => { ... },
  onPostBuild: async (ctx) => { ... }
};

引擎在加载时验证描述符——无效的名称、版本或未知功能会被立即拒绝(官方插件)或发出警告(第三方包)。

迁移说明: 描述符在 0.7.x 中为可选。未提供描述符的插件会收到软弃用警告。这将在 0.8.0 中成为硬性要求

🔒 插件隔离

每个钩子调用现在都包裹在 try/catch 边界中。故障插件不会导致构建崩溃或影响其他插件。错误会被记录并收集到构建结束时显示的摘要中:

⚠️  2 plugin error(s) occurred (build completed)

🔑 功能执行

声明了功能的插件只能注册与其声明匹配的钩子。如果插件导出了未声明的钩子,引擎会跳过它并输出警告:

Plugin "analytics" exports markdownSetup but didn't declare "markdown" capability — skipped
功能 允许的钩子 阶段
init onConfigResolved 初始化
markdown markdownSetup 设置
head generateMetaTagsgenerateScripts (head) 渲染
body generateScripts (body) 渲染
build onBeforeParseonAfterParseonPageReady 构建
post-build onPostBuild 构建后
dev onDevServerReady 开发服务器
assets getAssets 输出
actions actions 交互
events events 交互
translations translations 国际化

没有描述符的旧版插件仍可完全访问所有钩子。

📝 完整更新日志

📦 架构

  • @docmd/api:将 loadPluginscreateActionDispatchercreateSourceTools 及所有插件/RPC 类型提取到 packages/api/
  • @docmd/core 重新导出:所有迁移的 API 符号均从 @docmd/core/src/index.ts 重新导出,实现无缝向后兼容。
  • 死代码清理:迁移完成后,从 @docmd/core 删除了原始的 plugin-loader.tsaction-dispatcher.tssource-tools.tstypes.ts

🔌 插件系统

  • 插件描述符plugin 导出):名称、版本和功能声明。
  • 验证(§1):对 @docmd/plugin-* 包严格执行;对第三方插件发出软警告。
  • 隔离(§2):所有同步钩子使用 safeCall() 包裹;onPostBuild 使用异步 try/catch。
  • 功能执行(§3):钩子注册受声明功能限制。
  • 扩展生命周期钩子(§4):引入 onConfigResolvedonDevServerReadyonBeforeParseonAfterParseonPageReady,处理复杂的站点集成。
  • 错误摘要:插件错误被收集并在构建结束时以计数形式显示,不会中断构建过程。

🐛 问题修复

  • 404 页面原始键名显示:修复了翻译加载失败时 404 页面可能显示 errorCode404 纯文本的问题。错误代码现已硬编码为 404
  • i18n stringMode 脚本泄漏:修复了 no-style.ejsstringMode 激活时注入 docmd-i18n-strings.js 运行时的问题。客户端语言区域运行时现在在字符串模式下被正确禁止。
  • pnpm 工作区中的插件解析:修复了从 @docmd/api 调用时 loadPlugins 无法定位 @docmd/plugin-* 包的问题——该函数现接受调用方传入的 resolvePaths 以支持 pnpm 的严格 node_modules 布局。

⚠️ 重大变更

插件 API 导入路径(推荐迁移)

插件 API 的规范包现为 @docmd/api。虽然 @docmd/core 重新导出了一切以保持向后兼容,但建议插件作者更新其导入

-import { createActionDispatcher, createSourceTools } from '@docmd/core';
+import { createActionDispatcher, createSourceTools } from '@docmd/api';
-import type { PluginModule, ActionContext, SourceTools } from '@docmd/core';
+import type { PluginModule, ActionContext, SourceTools, PluginDescriptor, Capability } from '@docmd/api';

最终用户无需操作。 这仅影响直接导入 API 工具函数的插件开发者。@docmd/core 的重新导出将无限期保留。

Threads 插件对等依赖

@docmd/plugin-threads 包现在以 @docmd/api 而非 @docmd/core 作为对等依赖。如果你手动安装 Threads(而非通过 docmd add threads),请确保依赖树中有 @docmd/api

迁移指南

最终用户:无需任何操作。npm install docmd@latest 即可。

插件作者

  1. 添加插件描述符到默认导出中(目前可选,0.8.0 将成为必需项):
    export default {
      plugin: { name: 'my-plugin', version: '1.0.0', capabilities: ['head', 'post-build'] },
      // ... 钩子
    };
    
  2. 更新导入:将 createActionDispatchercreateSourceToolsloadPlugins 及所有类型导出的导入源从 @docmd/core 改为 @docmd/api
  3. 更新对等依赖:如果你的插件使用 RPC 或源码编辑 API,请在 package.json 中将对等依赖从 @docmd/core 改为 @docmd/api

详见构建插件获取完整的更新后 API 参考。