启动清单(Startup Manifest)
Egg 提供了启动清单(Manifest)机制,通过缓存文件发现和模块解析结果来加速应用的冷启动。
原理
应用每次启动时,框架需要执行大量文件系统操作:
- 模块解析:数百次
fs.existsSync调用,探测.ts、.js、.mjs等后缀 - 文件发现:多次
globby.sync扫描插件、配置、扩展等目录 - tegg 模块扫描:遍历模块目录,
import()装饰器文件收集元数据
Manifest 机制在首次启动时收集这些结果,写入 .egg/manifest.json。后续启动直接读取缓存,跳过重复的文件 I/O。
性能提升
在容器冷启动场景下(无文件系统缓存),以 cnpmcore 项目实测:
| 指标 | 无 Manifest | 有 Manifest | 提升 |
|---|---|---|---|
| 应用启动 | ~980ms | ~780ms | ~20% |
| 文件加载 | ~660ms | ~490ms | ~26% |
| 加载 app.js | ~280ms | ~150ms | ~46% |
注意:在本地开发环境中,操作系统的页面缓存(page cache)会使文件 I/O 接近零开销,因此提升不明显。Manifest 主要优化的是容器冷启动、CI/CD 等无缓存场景。
使用方式
通过 CLI 管理(推荐)
egg-bin 提供了 manifest 命令来管理启动清单:
生成清单
bash
# 为生产环境生成
$ egg-bin manifest generate --env=prod
# 指定环境和作用域
$ egg-bin manifest generate --env=prod --scope=aliyun
# 指定框架
$ egg-bin manifest generate --env=prod --framework=yadan生成过程会以 metadataOnly 模式启动应用(跳过生命周期钩子,只收集元数据),然后将结果写入 .egg/manifest.json。
验证清单
bash
$ egg-bin manifest validate --env=prod输出示例:
[manifest] Manifest is valid
[manifest] version: 1
[manifest] generatedAt: 2026-03-29T12:13:18.039Z
[manifest] serverEnv: prod
[manifest] serverScope:
[manifest] resolveCache entries: 416
[manifest] fileDiscovery entries: 31
[manifest] extension entries: 1如果清单无效或不存在,命令将以非零退出码退出。
清理清单
bash
$ egg-bin manifest clean自动生成
应用正常启动后,框架会在 ready 阶段自动生成清单(通过 dumpManifest)。下次启动时如果清单有效,则自动使用。
清单失效机制
清单包含指纹信息,以下情况会自动失效:
- 锁文件变更:
pnpm-lock.yaml、package-lock.json或yarn.lock的修改时间或大小变化 - 配置目录变更:
config/目录下的文件发生变化(基于 MD5 指纹) - 环境不匹配:
serverEnv、serverScope与清单中记录的不一致 - TypeScript 状态变更:
EGG_TYPESCRIPT启用/禁用状态发生变化 - 版本不匹配:清单格式版本号不一致
清单失效时,框架会回退到正常的文件发现流程,不会影响启动。
环境变量
| 变量 | 说明 | 默认值 |
|---|---|---|
EGG_MANIFEST | 在本地环境启用清单 | false(本地环境默认不加载清单) |
本地开发环境(
serverEnv=local)默认不加载清单,因为开发时文件频繁变更,清单容易失效。设置EGG_MANIFEST=true可强制启用。
部署建议
容器化部署
在 Dockerfile 中,构建完成后生成清单:
dockerfile
# 安装依赖并构建
RUN npm install --production
RUN npm run build
# 生成启动清单
RUN npx egg-bin manifest generate --env=prod
# 启动应用(将自动使用清单)
CMD ["npm", "start"]CI/CD 流水线
在构建阶段生成清单,随制品一起部署:
bash
# 构建
npm run build
# 生成清单
npx egg-bin manifest generate --env=prod
# 验证清单
npx egg-bin manifest validate --env=prod
# 打包(包含 .egg/manifest.json)
tar -zcvf release.tgz .注意事项
- 清单与环境绑定:清单绑定了
serverEnv和serverScope(部署类型,如aliyun),不同环境或部署类型需要分别生成 - 依赖变更后需重新生成:安装或更新依赖后,锁文件变更会自动使清单失效
.egg目录:清单存储在.egg/manifest.json,建议将.egg/加入.gitignore- 回退安全:清单缺失或无效时,框架会自动回退到正常流程,不会导致启动失败
- metadataOnly 模式:
manifest generate不会启动完整的应用生命周期,不会连接数据库或外部服务
清单结构
json
{
"version": 1,
"generatedAt": "2026-03-29T12:13:18.039Z",
"invalidation": {
"lockfileFingerprint": "pnpm-lock.yaml:1711234567890:12345",
"configFingerprint": "a1b2c3d4e5f6...",
"serverEnv": "prod",
"serverScope": "",
"typescriptEnabled": true
},
"extensions": {
"tegg": { ... }
},
"resolveCache": {
"config/plugin": "config/plugin.ts",
"config/plugin.default": null
},
"fileDiscovery": {
"app/middleware": ["trace.ts", "auth.ts"]
}
}