构建与部署
在不同平台之间切换不需要改代码:构建时选择的 preset 决定产物形态和部署方式。
bash
npx cell build # preset node:.cell/output
npx cell build --preset cloudflare
npx cell deploy --preset fc --dry-run # 只给出计划,不上传preset 的来源依次是:--preset,cell.config.ts 的 preset,CELL_PRESET 环境变量,CI 平台识别(Workers Builds 中为 cloudflare,Vercel 上为 vercel),最后是 node。npx cell info 会显示用的是哪个以及原因。
preset
| preset | 产物 | 本地运行 | 部署 |
|---|---|---|---|
node(默认) | Node.js HTTP 服务,server/index.mjs | cell preview | 把 .cell/output 拷到任何能运行 Node.js 18+、Bun 或 Deno 的地方 |
cli | 基于 Cell DI 的命令行程序,不起 HTTP 服务 | cell preview | 分发文件或可执行文件 |
cloudflare | Worker + 静态资源 + wrangler.json | cell preview(经 Wrangler 在 workerd 中运行) | cell deploy --preset cloudflare |
fc | 阿里云函数计算 3.0 自定义运行时 | cell preview | cell deploy --preset fc |
scf | 腾讯云 SCF Web 函数 | cell preview | cell deploy --preset scf |
lambda | AWS Lambda + 函数 URL | cell preview | cell deploy --preset lambda |
vercel | Vercel Build Output API(.vercel/output) | cell preview | cell deploy --preset vercel |
产物
text
.cell/output/
├── server/index.mjs # 后端:内联了全部依赖的单个 ES 模块
├── public/ # 前端产物(有前端时)
└── manifest.json # preset、格式、目标:cell preview 和 cell deploy 读取它产物不需要项目的 node_modules。无法打包的包(原生模块、cell.config.ts 的 build.external)会拷到 server/node_modules。
| 选项 | 结果 |
|---|---|
--single | 前端内嵌进 server/index.mjs:一个文件运行整个应用 |
--compile [bun|node|deno] | 可执行文件 .cell/output/app,主机上不需要 Node.js |
-m <mode> | 额外读取 cell.<mode>.yml(构建时 production 总是生效) |
--sourcemap、--format cjs、--out-dir <dir> | source map、CommonJS 产物、其他输出目录 |
生产环境的配置
- 后端配置在服务端启动时求值。 同一份产物到处运行;各环境的值通过环境变量给出:在
cell.yml里引用("${env.DATABASE_URL}"),或直接覆盖(CELL_SERVER__PORT=8080)。见项目结构与配置。 - 不要把密钥标成 public。 配置默认只在服务端,只有 schema 标记为 public 的键和
app.public会进前端;前端的值在构建时求值并发给浏览器。 - 服务默认监听
127.0.0.1:3000。容器里设置CELL_SERVER__HOST=0.0.0.0;平台通过PORT给端口时设置CELL_SERVER__PORT='${env.PORT}'。 - 设置自己的
web.cookies.keys(cookie 和 session 的签名密钥),例如CELL_WEB__COOKIES__KEYS='["..."]'。 - 安全检查。
cell check会列出在生产环境不安全的设置(CELL_SECURITY_*警告:开发用的 cookie 密钥、过短的jwt.secret等)。生产启动时(NODE_ENV=production,cell build会把它写进服务端产物)同样会把这些警告写进日志;设置securityChecks: fail(或CELL_SECURITY_CHECKS=fail)则拒绝启动,off则不检查。 - 错误信息。 生产环境下服务端错误只返回状态文本(
Internal Server Error),错误信息和调用栈写进日志;4xx 的HttpError信息照常返回。可用web.errors.exposeMessages改变这一行为。
容器镜像
dockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npx cell build
FROM node:22-alpine
ENV NODE_ENV=production
ENV CELL_SERVER__HOST=0.0.0.0
WORKDIR /app
COPY --from=build --chown=node:node /app/.cell/output ./
USER node
EXPOSE 3000
CMD ["node", "server/index.mjs"]cell deploy
cell deploy 用 preset 构建,生成计划(要创建或更新的资源),再执行它。--dry-run 到计划为止,没有凭据也能用;--skip-build 部署已有的产物。
| preset | 凭据(环境变量) | cell.config.ts 中的平台选项 |
|---|---|---|
cloudflare | CLOUDFLARE_API_TOKEN(及 CLOUDFLARE_ACCOUNT_ID),或 npx wrangler login | 项目根目录的 wrangler.jsonc:名称、vars、绑定、routes |
fc | ALIBABA_CLOUD_ACCESS_KEY_ID、ALIBABA_CLOUD_ACCESS_KEY_SECRET | fc: { name, region, memory, cpu, timeout, concurrency, env } |
scf | TENCENTCLOUD_SECRET_ID、TENCENTCLOUD_SECRET_KEY | scf: { name, region, namespace, memory, timeout, env } |
lambda | AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY,或 AWS_PROFILE | lambda: { name, region, architecture, memory, timeout, role, env } |
vercel | VERCEL_TOKEN,或 npx vercel login | vercel: { project, scope, environment, memory, maxDuration, regions } |
ts
// cell.config.ts
import { defineConfig } from '@celljs/cli';
export default defineConfig({
preset: 'fc',
fc: { region: 'cn-shanghai', memory: 512, env: { DATABASE_URL: process.env.DATABASE_URL ?? '' } },
});函数平台(fc、scf、lambda)直接调用云 API,不安装云厂商的 SDK 或 CLI。Wrangler 和 Vercel CLI 优先用项目里安装的,否则经 npx 使用。每种失败都有错误码:CELL_DEPLOY_CREDENTIALS_MISSING、CELL_DEPLOY_UNAUTHORIZED、CELL_DEPLOY_PACKAGE_TOO_LARGE……
各平台的细节(自定义域名、运行时、代码包大小上限、部署器会创建什么)见 CLI 文档。
hooks
在工具链事件上执行 shell 命令,用于代码生成之类的步骤:
ts
export default defineConfig({
hooks: {
'build:before': 'prisma generate', // 失败会取消构建
'output:done': 'cp extra/* "$CELL_OUT_DIR/server/"',
},
});需要写代码的扩展(Vite 插件、额外的产物文件、检查项、MCP 工具)写成 toolchain 模块,见 CLI 文档。