跳到正文

部署

主题是普通的 VuePress 2 主题,所以文档站的部署方式和任何 VuePress 站点一样:先构建, 再托管 docs/.vuepress/dist 目录。

npm install
npm run docs:build  # 先把主题构建到 lib/,再把站点构建到 docs/.vuepress/dist

docs:build 会先构建主题,所以宿主只需要这一条命令:

install:  npm ci
build:    npm run docs:build
output:   docs/.vuepress/dist

仓库根目录下的 edgeone.json 把这四项写死了,EdgeOne Pages 会自动读取, 所以控制台里不用再手填:

{
  "$schema": "https://edgeone.ai/schema/edgeone.json",
  "installCommand": "npm ci",
  "buildCommand": "npm run docs:build",
  "outputDirectory": "docs/.vuepress/dist",
  "nodeVersion": "22.20"
}

安装命令

无论用什么平台,构建都必须从仓库根目录运行,并且必须在构建站点之前先构建主题。 docs/.vuepress/config.js 从 ../../lib/node/index.js 导入主题,而 lib/ 是生成物 —— 它没有被提交。这也是 docs:build 写成 node scripts/build.mjs && vuepress build docs、而不是裸 vuepress build docs 的原因。

顺序很重要。在全新检出上单跑 vuepress build docs,在渲染任何东西之前就会失败:

[UNRESOLVED_IMPORT] Could not resolve '../../lib/node/index.js' in docs/.vuepress/config.js

重复构建是无害的 —— scripts/build.mjs 会整体替换 lib/。如果宿主需要分开的构建 命令,npm run build && npm run docs:build 等价且依然正确。

npm ci 需要 lockfile 与 package.json 同步。如果你手工改过依赖,先跑一次 npm install 并提交更新后的 package-lock.json。

静态托管

生成物是纯 HTML、CSS 与 JS,所以任意静态托管都能用:

宿主需要设置
EdgeOne Pagesinstall npm ci,build npm run docs:build,output docs/.vuepress/dist,Node 22.11.0(预装上限,原生绑定由守卫脚本补齐)
Vercel同样的命令,输出目录 docs/.vuepress/dist
Netlify同样的命令,发布目录 docs/.vuepress/dist
GitHub Pages跑 npm run docs:build,把 docs/.vuepress/dist 发布到 Pages 分支
任意 Web 服务器把 docs/.vuepress/dist 拷到站点根目录

EdgeOne Makers:必须绕开它的构建环境

EdgeOne Makers 的 Git 集成构建会在它自己的容器里跑 installCommand 与 buildCommand。 这个容器预装的 Node 只有 14.21.3 / 16.20.2 / 18.20.4 / 20.18.0 / 22.11.0,最高到 22.11.0(见 edgeone.json 文档)。

而 Vite 8 通过 rolldown 编译,rolldown 的原生二进制以 optionalDependency 形式分发, 绑定包声明 engines.node: ^20.19.0 || >=22.12.0。于是 npm ci 在 Node 22.11.0 上会 静默跳过这个 optional 依赖 —— 只留一条 EBADENGINE 警告 —— 构建阶段随即抛:

Error: Cannot find module '../rolldown-binding.linux-x64-gnu.node'
Require stack:
- node_modules/rolldown/dist/shared/binding-BY0qR5iS.mjs

这是「EdgeOne 部署一直失败」的典型形态:日志里看不出 enging 相关错误,只有一条模块找不到。

本仓库用两条互相独立的路径解决它。

路径一:在 CNB 里构建,再把产物推给 EdgeOne(推荐)

EdgeOne 预装的 Node 版本无法满足 Vite 8 的要求,那就不要用它构建。.cnb.yml 的 deploy-edgeone 流水线在 CNB 的 node:22.20 里跑构建,再用 EdgeOne CLI 把静态产物直传上去:

npx edgeone makers deploy docs/.vuepress/dist -n <项目名> -t $EDGEONE_API_TOKEN -e production

需要在仓库密钥中配置:

密钥必填说明
EDGEONE_API_TOKEN是EdgeOne Makers → API Token
EDGEONE_PROJECT_NAME否项目名,默认 vuepress-theme-github

没配 EDGEONE_API_TOKEN 时该阶段会打印提示并跳过,不会让流水线失败。

同时 .cnb.yml 里的 notify-edgeone 阶段会把 push 事件转发给 EdgeOne 的钩子地址。 CNB 原生不支持 Webhook,导入 CNB 仓库后如果不转发,EdgeOne 控制台里的 Git 集成 永远不会被触发。钩子地址由 EdgeOne 指定,不要修改。

路径二:让 EdgeOne 自己的构建也能跑通

如果你更希望用控制台的 Git 集成,本仓库也把这条路修通了。scripts/ensure-rolldown-binding.mjs 会在安装后 / 构建前检查原生绑定是否就位,缺失就按当前平台显式补装(直接安装可以绕开 optional 的 engines 跳过行为)。它同时挂在 postinstall 与 docs:build / build 上, 所以即使宿主用 --ignore-scripts 跳过 postinstall,构建前仍会被补上。

edgeone.json 已把 Node 固定到 EdgeOne 预装列表里的 22.11.0:

{
  "$schema": "https://edgeone.ai/schema/edgeone.json",
  "installCommand": "npm ci --no-audit --no-fund",
  "buildCommand": "npm run docs:build",
  "outputDirectory": "./docs/.vuepress/dist",
  "nodeVersion": "22.11.0"
}

不要写成 EdgeOne 未预装的版本(例如 22.20)。文档明确写了「使用其它版本可能导致部署失败」。

两条路径都验证过:在 Node 22.11.0 + npm 10.9.0 的容器里,npm ci && npm run docs:build 能从原来的 Cannot find module 变成构建成功、渲染 33 个页面。

会压坏静态构建的三件事

下面三种失败覆盖了绝大多数「VuePress 仓库接上宿主 Git 集成后构建失败」的情况。

1. 平台报 CNB not authorized

宿主读不到仓库。这是凭据问题,不是代码问题:私有 CNB 仓库需要用访问令牌把宿主连上 CNB (对仓库有读权限即可),或者把仓库设为公开。构建根本没真正开始,所以仓库里改不动。

2. 从 main 分支构建失败

请确认部署分支上确实有 package.json。如果宿主报 No package.json found 或 Could not read package.json,说明部署根目录指到了子目录(比如 docs),而不是仓库 根。根目录填仓库根。输出目录固定是 docs/.vuepress/dist。

3. 缺少 lib/ 导致的构建失败

docs/.vuepress/config.js 从 ../../lib/node/index.js 导入。lib/ 在 .gitignore 里,所以构建命令是裸 vuepress build docs 的宿主会因为找不到主题而失败,报 Could not resolve '../../lib/node/index.js'。

npm run docs:build 已经先构建了主题。只有把命令覆盖成 vuepress build docs 的宿主 才会踩到 —— 那里也用 npm run docs:build,或在前面加上 npm run build。

Node 版本

package.json 的 engines 声明 Node 22.11.0 或更新,CI 与推荐环境使用 node:22.20。

为什么下限是 22.11.0 而不是 VuePress 自己声明的 22.18.0:VuePress 2.0.0-rc.31 的 engines 只是一条策略下限,实际运行依赖的特性(如 import.meta.dirname)在更早的 Node 22 上就有。把下限降到 22.11.0 是为了覆盖 EdgeOne Makers 预装 Node 的上限 —— 否则平台会挑不到可用的运行时。Vite 8 与 @vueuse/core 在 22.11.0 上只会打印 EBADENGINE 警告,构建本身通过,原生绑定由 scripts/ensure-rolldown-binding.mjs 补齐。

在平台设置里指定 Node 版本,或在仓库里用 .nvmrc 固定:

22.20

SPA fallback

站点是带预渲染 HTML 的单页应用。每个生成的路由都会写出真实文件(/guide/ 变成 guide/index.html,404.html 也会生成),所以通常不需要重写规则。如果你的宿主只提供 精确的文件路径,加一条指向 /404.html 的兜底,让未知 URL 渲染主题的 404 页面。