Appearance
init-vitepress 在 Node 16.14.2 项目中的兼容策略
归类:开发工具 / AI 技能 / VitePress 发生时间:2026-03-31 状态:✅ 技能定义已收敛到单一源,并补齐 Node 16 兼容策略
一、当前结论
mds skills 不是把 init-vitepress 的实现硬编码在 mds-cli 里执行逻辑,而是:
- 优先从远端技能仓库拉取 skill 内容
- 网络不可用时,回退到
mds-cli内置 snapshot
这意味着:
- 技能定义的单一事实来源 应该是
mdsfe-agent-workflows - mds-cli 负责分发、安装、snapshot 回退和本地命令入口
- 如果要优化
init-vitepress的行为,优先修改远端技能仓库中的对应 skill,再把mds-clisnapshot 同步回来
一句话记住就是:
text
改技能语义,先改 agent-workflows;
改安装器、分发器、目标目录解析,再改 mds-cli。二、为什么不能只改 mds-cli
如果只改 mds-cli 内置 snapshot,会有两个问题:
- 在线拉取远端 skill 的用户仍会拿到旧版
init-vitepress - 远端 canonical source 和本地 fallback snapshot 会逐渐漂移
所以更稳的顺序是:
- 修改
mdsfe-agent-workflows中skills/<locale>/init-vitepress/ - 如有联动的 Node 兼容策略,同时修改
node-env-guide - 推送远端仓库
- 回到
mds-cli执行npm run skills:sync - 只有当你需要更新 CLI 内置 fallback 或发版时,才继续改动 / 发布
mds-cli
三、Node 16.14.2 为什么容易踩坑
init-vitepress 在老项目里最常见的坑不是“文档内容有问题”,而是下面三类环境错配:
1. 安装了只支持 Node 18+ 的 VitePress / Vite 主线
新版本 VitePress 已经依赖较新的 Vite 主线,而 Vite 5 的 engines.node 要求是:
text
^18.0.0 || >=20.0.0这意味着把新版 VitePress 直接塞进 Node 16 项目,哪怕加了 --ignore-engines,后面也很容易在依赖解析、esbuild 二进制、运行时加载阶段继续出错。
四、推荐的三条落地路径
路径 A:现代主线
适用场景:
- 文档运行环境已经是 Node 18+
- 或者团队已经统一升级到了 Node 18+
推荐做法:
- 安装
vitepress@^1 - 配置文件优先用
docs/.vitepress/config.mjs - 直接使用
vitepress dev/build/preview
路径 B:Node 16 兼容主线
适用场景:
- 项目必须稳定停留在 Node
16.14.2 - 团队暂时不想额外维护 docs 子运行时
推荐做法:
- 显式固定
vitepress@0.22.4 - 不要默认升级到最新 VitePress 主线
- 配置文件优先使用
docs/.vitepress/config.mjs或config.js - 避免默认生成
config.ts
这样做的原因很直接:
vitepress@0.22.4声明engines.node >=14.0.0- 它更适合作为老项目的兼容文档线
路径 C:双运行时隔离
适用场景:
- 业务代码必须继续跑在 Node 16
- 但文档站允许单独跑在 Node 18+
推荐做法:
- 文档命令通过包装脚本执行
- 包装脚本里显式加载
nvm.sh或团队标准版本管理器 - 再执行
nvm exec 18 npx vitepress ...
五、为什么不要把裸 nvm exec 写进 package.json
这是截图里最容易被忽略、但真实非常高频的问题。
很多人会这样写:
json
{
"scripts": {
"docs:build": "nvm exec 18 vitepress build docs"
}
}看起来合理,但实际经常失败,因为:
npm run/yarn run默认通过/bin/sh执行/bin/sh往往不会自动加载~/.nvm/nvm.sh- 于是脚本在终端里手工跑得通,在包管理器脚本里却失败
更稳的做法是显式包装:
bash
#!/usr/bin/env bash
set -e
if [ -s "${NVM_DIR:-$HOME/.nvm}/nvm.sh" ]; then
. "${NVM_DIR:-$HOME/.nvm}/nvm.sh"
exec nvm exec 18 npx vitepress "$@"
fi
exec npx vitepress "$@"然后让 package.json 调这个包装脚本,而不是直接写裸 nvm exec。
六、为什么默认更推荐 config.mjs
另一个很常见的问题是:
- 老项目是 CJS 生态
- 周边脚手架、测试器或构建器会把
config.ts当成 CJS 或混合模块处理 - 最后导致 VitePress 需要的 ESM 配置链路不稳定
因此在 init-vitepress 里,默认优先:
text
docs/.vitepress/config.mjs只有当仓库已经证明自己的 ESM TypeScript 配置链路稳定时,才去生成 config.ts。
七、现在这类技能应该怎么维护
推荐维护流程:
text
1. 修改 agent-workflows 中的 canonical skill
2. 推送远端
3. 在 mds-cli 中执行 npm run skills:sync
4. 如需更新 fallback snapshot 或正式发版,再处理 mds-cli这样可以同时保证:
- 在线拉取 skill 的用户拿到最新规则
mds-cli的本地 snapshot 不落后太多- 技能定义不会分裂成两份长期漂移
八、可直接复用的对外说明
可以直接复用下面这段说明:
text
init-vitepress 的技能定义真源在 agent-workflows,不在 mds-cli 业务代码里。
如果要优化技能语义或兼容性,应该先改远端 skill,再同步 mds-cli snapshot。
对于 Node 16.14.2 项目,默认不要安装最新 VitePress 主线。
优先固定兼容版本线,或者把文档运行时单独隔离到 Node 18+。
另外,不要把裸 nvm exec 写进 package.json,应该通过显式包装脚本加载 nvm。九、预防建议
- 不要把
mds-clisnapshot 当成技能定义真源。 - 对 Node 16 项目,先做版本分流,再决定装哪条 VitePress 线。
- 除非项目已经证明 ESM TypeScript 配置稳定,否则不要默认生成
config.ts。 - 对需要
nvm exec的场景,优先使用包装脚本,而不是内联到package.json。