进阶 www.prisma.io 2026-10-12 01:56:59 · 26 阅读

第1章 部署你的第一个应用

第1章:部署你的第一个应用

使用 Prisma Composer,将一个 TypeScript 应用从终端直接部署到 Prisma Compute 上的实时 URL。你可以从零开始,也可以基于已有应用进行部署。

Prisma Compute 专为 TypeScript 应用提供无服务器托管(serverless hosting)。它将你的应用直接部署在 Prisma Postgres 数据库旁边,从而保持应用与数据之间最短的交互路径。应用通过 Prisma Composer 声明并部署:你用 TypeScript 描述应用的服务,一条命令即可在 Compute 上将其运行起来。读完本页,你将获得一个实时 URL。

根据当前状况选择起点:

- 从零开始:声明一个新应用并在本地运行,然后部署。 - 已有应用:为现有服务器代码添加声明,然后部署。

两条路径最终汇聚于相同的部署步骤,因为 Composer 对每个应用的处理方式一致。已部署的应用即成为一个项目;不带标志的部署默认指向生产环境,而使用 `--stage ` 则会将整个应用作为一个独立副本部署为同一项目的预览分支。本地运行不与平台交互,因此仅在部署时需要凭证。关于平台的资源模型,请参阅 Compute 文档。

前置条件

开始前,请确保你具备以下条件:

- Node.js 22.18 或更高版本。Composer 将你的 TypeScript 入口文件直接交给 Node,而直接运行 `.ts` 文件需要 22.18.0 或更高版本。在旧版本上,Composer 命令会在 `ERR_UNKNOWN_FILE_EXTENSION` 处停止。 - Bun。Prisma Compute 使用 Bun 运行已部署的应用,因此你的服务器代码需针对 Bun 编写,且 `bun build` 生成部署所需的自包含入口文件。 - Prisma Data Platform 账户(免费创建)。仅在部署步骤需要该账户;本地开发无需账户。

1. 使用 Composer 声明应用

Composer 应用由两部分组成:你的服务器代码 + 一个小声明,用于说明每个服务的名称、构建方式及依赖项。请选择符合你起点的路径。

从零开始

按照 Composer 入门指南第 1 步设置项目:安装 `@prisma/composer` 和 `@prisma/composer-prisma-cloud`,将 `prisma` 安装为开发依赖,并添加 `tsconfig.json`。无需手动锁定 `effect`:Composer 会自动锁定它;只有在另一依赖项提升(hoist)了不同版本的 `effect` 导致 `prisma.config.ts` 报错时,才需使用“当 prisma.config.ts 因 effect 版本冲突失败”章节中的覆盖方案。随后,一个最小的单服务应用由四个文件组成。

服务器是普通的 Bun 代码。唯一一行 Composer 特有的代码是从 `service.port()` 读取端口;绑定 `0.0.0.0`,因为 Compute 将外部 HTTP 路由到 VM,仅绑定回环地址将导致无法访问:

```typescript // src/server.ts import service from "./service.ts";

Bun.serve({ port: service.port(), hostname: "0.0.0.0", fetch: () => new Response("Hello from Prisma Compute"), }); ```

服务声明命名服务并指向构建输出:

```typescript // src/service.ts import node from "@prisma/composer/node"; import { compute } from "@prisma/composer-prisma-cloud";

export default compute({ name: "web", deps: {}, build: node({ module: import.meta.url, entry: "../dist/server.mjs" }), }); ```

根模块即应用本身:它负责提供(provision)服务。旁边的部署配置位于 `prisma.config.ts` 的 `composer` 部分,仅供 CLI 读取:

```typescript // module.ts import { module } from "@prisma/composer"; import webService from "./src/service.ts";

export default module("my-app", ({ provision }) => { provision(webService); }); ```

```typescript // prisma.config.ts import { defineConfig as composer } from "@prisma/composer/config"; import { nodeBuild } from "@prisma/composer/node/control"; import { prismaCloud, prismaState } from "@prisma/composer-prisma-cloud/control"; import { definePrismaConfig } from "prisma/config";

export default definePrismaConfig({ composer: composer({ extensions: [prismaCloud({ region: "us-east-1" }), nodeBuild()], state: prismaState(), }), }); ```

区域是首次部署创建项目的位置。选择“已知限制”中列出的任一区域,或者省略它并在部署时设置 `PRISMA_REGION`;已存在的项目将保持其原有区域。

你掌控构建过程;Composer 只负责组装你构建好的产物。添加一个生成每个服务自包含文件的构建脚本:

```json // package.json { "scripts": { "build": "bun build src/server.ts --target=bun --outfile dist/server.mjs" } } ```

现在在你的机器上运行应用。此步骤不涉及任何账户或凭证:

```bash bun run build bunx prisma dev module.ts ```

`dev` 命令打印服务的本地 URL;使用 `curl` 测试即可得到 "Hello from Prisma Compute"。关于本地数据库、存储和日志工作流,请参阅“本地开发”章节。

从此以后,应用通过声明来扩展:`deps: { db: rawPostgres() }` 为服务提供 Prisma Postgres 数据库(或来自 `@prisma/composer-prisma-cloud/orm` 的由 Prisma ORM 类型定义的 `postgres(contract)`),`bucket()` 提供对象存储,第二个具有类型化契约的服务将跨服务调用转化为经过检查的函数调用。当应用在本地运行时,请继续到“部署”部分。

携带已有应用

移植应用并不意味着重写。你的服务器代码保持不变,你的构建过程保持不变,只需为其添加声明。以下步骤将一个双服务应用(基于 Postgres 的笔记 API 和基于 S3 凭证的上传服务)移植为一个拥有自己数据库和存储桶的 Composer 应用。对于 Next.js 服务,请改用带有 `output: "standalone"` 的 `nextjs` 构建适配器;“移植现有应用”章节涵盖了该变体。

1. 安装 Composer 包:与从零开始路径的第 1 步相同:安装 `@prisma/composer` 和 `@prisma/composer-prisma-cloud`,并将 `prisma` 安装为开发依赖。Composer 会为你锁定 `effect`;如果你的现有依赖项锁定了不同版本的 `effect`,请使用“当 prisma.config.ts 因 effect 版本冲突失败”章节中的覆盖方案。 2. 声明每个服务:在每个服务器旁边添加 `service.ts`,命名服务、声明其消费的依赖项,并指向构建输出。Postgres 连接变为 `rawPostgres()`;S3 凭证变为 `bucket()`:

```typescript // src/api/service.ts import node from "@prisma/composer/node"; import { compute, rawPostgres } from "@prisma/composer-prisma-cloud";

export default compute({ name: "api", deps: { db: rawPostgres() }, build: node({ module: import.meta.url, entry: "../../dist/api.mjs" }), }); ```

```typescript // src/files/service.ts import node from "@prisma/composer/node"; import { bucket, compute } from "@prisma/composer-prisma-cloud";

export default compute({ name: "files", deps: { store: bucket() }, build: node({ module: import.meta.url, entry: "../../dist/files.mjs" }), }); ```

3. 在一个模块中提供所有资源:根模块拥有资源并将其连接到服务;旁边的部署配置与从零开始路径相同:

```typescript // module.ts import { module } from "@prisma/composer"; import { bucket, rawPostgres } from "@prisma/composer-prisma-cloud"; import apiService from "./src/api/service.ts"; import filesService from "./src/files/service.ts";

export default module("my-app", ({ provision }) => { const db = provision(rawPostgres({ name: "database" })); const store = provision(bucket({ name: "uploads" })); provision(apiService, { deps: { db } }); provision(filesService, { deps: { store } }); }); ```

4. 移植环境读取:这是对你服务器代码的唯一修改,使每个环境无需手动配置即可工作: - 端口:使用 `service.port()` 替代 `process.env.PORT`,并绑定 `0.0.0.0`。 - 依赖值:使用 `service.load()` 替代连接字符串和凭证环境变量。Postgres 依赖项为你提供当前客户端可用的 `db.url`;存储桶提供标准 S3 集合。 - 其他项(标志、区域、外部 URL、第三方凭证)变为服务的输入模式(input schema)。

修改后的服务器代码示例:

```typescript // src/api/server.ts (修改的行) import { SQL } from "bun"; import service from "./service.ts";

// 之前: new SQL({ url: process.env.DATABASE_URL }) const { db } = service.load(); const sql = new SQL({ url: db.url, max: 1, idleTimeout: 10, prepare: false });

Bun.serve({ port: service.port(), hostname: "0.0.0.0", fetch: handler }); ```

```typescript // src/files/server.ts (修改的行) import service from "./service.ts";

// 之前: 从四个 S3_* 环境变量读取 endpoint, bucket, 和 keys const { store } = service.load(); const s3 = new Bun.S3Client({ endpoint: store.url, bucket: store.bucket, accessKeyId: store.accessKeyId, secretAccessKey: store.secretAccessKey, }); ```

5. 本地构建并验证:你的构建必须为每个服务生成一个自包含入口文件;如果已实现则保留现有构建,否则每个服务使用一行 `bun build --target=bun`。然后在本地运行完整声明:

```bash bun run build bunx prisma dev module.ts ```

`dev` 会提供一个本地 Postgres 和一个带有可用凭证的本地临时存储桶,每个服务在启动输出中都会显示本地 URL,因此你可以在接触平台之前端到端地测试数据库和上传路径。然后继续到“部署”:相同的部署命令将在服务旁边提供真实的数据库和存储桶。

2. 部署

登录一次。这是唯一需要交互的步骤,因为它会打开浏览器:

```bash bunx prisma auth login ```

会话存储在你的机器上,后续所有命令(包括编码代理在你的目录中运行的命令)都会读取它。随时使用 `auth whoami` 确认状态。在 CI 或无头环境中,请设置 `PRISMA_SERVICE_TOKEN` 和 `PRISMA_WORKSPACE_ID`;详见“部署”章节。

`deploy` 不会替你构建,因此先构建再部署:

```bash bun run build bunx prisma deploy module.ts ```

CLI 会根据根模块名称在项目创建区域(来自 `prismaCloud({ region })` 或 `PRISMA_REGION`;若未指定,首次部署将因 `project "" does not exist yet and no deploy region is configured` 而停止),在 Compute 上提供服务,在 Prisma Postgres 上创建数据库,连接依赖项并启动一切。项目名称在工作区中标识该应用:重新部署将复用该模块创建的项目;如果同名项目的托管状态无法被 CLI 验证,命令将因 `HostedStateBootstrapError` 停止。此时可使用 `--name ` 以另一名称部署。

3. 验证部署

部署完成后,CLI 会打印生成的内容:每个服务、其变成的平台资源及其公共 URL:

```text my-app └─ web compute-service cps_abc123 https://xyz.ewr.prisma.build ```

请求打印的 URL 以确认应用响应:

```bash curl https://xyz.ewr.prisma.build ```

你也可以在 Console 中检查所有内容:项目、分支、服务、部署和域名。

4. 发布变更与环境

重新部署是幂等的:再次构建,再次部署,平台应用差异而非重建一切。这包括删除:从模块中删除一个 provision,下次部署将删除该资源;详见“删除资源”。生产环境和预览环境通过阶段(stages)分离:

```bash bunx prisma deploy module.ts # 生产 bunx prisma deploy module.ts --stage staging # 持久预发环境 bunx prisma deploy module.ts --stage pr-42 # 每个 PR 一个环境 ```

阶段是应用的完整、隔离副本:拥有自己的服务、数据库和配置,仅与生产共享代码。在平台术语中,它是同一项目的预览分支。销毁阶段需要带有 service-token 凭证的控制 API,或在 Console 中删除分支;详见“销毁”。“部署”章节完整涵盖了 CI、部署状态和销毁。

交给你的代理

你可以让编码代理完成工作。对于拥有独立凭证、权限策略和审批流程的代理,请参阅“注册你的代理”。对于最简单路径,自己登录一次(步骤 2)。浏览器登录是代理无法替你完成的一步。之后,任何在你环境中运行的程序(包括你的代理)都会继承该会话。`@prisma/composer` 包附带一个代理技能,教导代理安装版本的 API;`npx prisma@latest init` 设置项目以确保技能在升级中保持同步。将此粘贴到你的代理中并填空:

```text 将 [你想构建的内容] 构建为 Prisma Composer 应用,并使用 `npx prisma@latest` 部署到 Prisma Compute。

注意事项: - 安装 @prisma/composer 后,安装其代理技能以使用真实 API:`npx prisma skills sync`(技能随包提供;运行 `npx prisma skills list` 确认)。 - 部署前运行 `npx prisma auth whoami`;如果未登录,停止并要求我运行 `npx prisma auth login`(它会打开浏览器)。 - Composer 需要 Node.js 22.18 或更高版本,服务器代码针对 Bun 编写。使用 `service.port()` 读取端口并绑定 0.0.0.0。对于 Next.js 服务,使用 nextjs 构建适配器并设置 `output: "standalone"`。 - Composer 不构建;为每个服务生成一个自包含入口文件(例如 `bun build --target=bun`),然后在本地使用 `npx prisma dev module.ts` 运行并验证每个服务的本地 URL 响应。 - 使用 `npx prisma deploy module.ts` 部署,并用 curl 验证打印的公共 URL。 - 为服务提供数据库时,声明 `deps: { db: rawPostgres() }`(从 @prisma/composer-prisma-cloud 导入)并从注入的 `db.url` 构建客户端;不要从 process.env 读取连接字符串。对于由 Prisma ORM 类型定义的数据库,改用 @prisma/composer-prisma-cloud/orm 中的 `postgres(contract)`。 - 新项目需要区域:在 prisma.config.ts 的 `composer` 部分设置 `prismaCloud({ region: "us-east-1" })`(或其他区域),或在首次部署前设置 PRISMA_REGION。 - 当前文档:https://www.prisma.io/docs/composer.md 和 https://www.prisma.io/docs/prisma-compute/deploy.md ```

示例:

```text 将带有 /todos 端点的 Bun API 构建为 Prisma Composer 应用,该端点由内存列表支持,并使用 `npx prisma@latest` 部署到 Prisma Compute。 ```

下一步

- Composer 入门:双服务版本,服务间具有类型化契约。 - 数据库:为服务提供 Prisma Postgres 数据库,可以是原始的或由 Prisma ORM 契约类型定义的。 - 部署:阶段、CI、部署状态和销毁。 - 本地开发:在机器上使用你部署的运行时运行应用、数据库和存储。

编辑 GitHub:在 Prisma 上免费启动带有 Postgres 的 TypeScript 应用

从空目录到在 Prisma Compute 上带有 Prisma Postgres 数据库的实时 TypeScript 应用,列出免费计划的限制。

注册你的代理

为编码代理提供其自身的 Prisma 凭证和你控制的权限策略,使其在敏感 API 操作前询问你,并记录其发出的每个请求。

评论 (0)