encore-service

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Encore Service Structure

Encore 服务结构

Instructions

操作说明

Creating a Service

创建服务

Every Encore service needs an
encore.service.ts
file:
typescript
// encore.service.ts
import { Service } from "encore.dev/service";

export default new Service("my-service");
每个Encore服务都需要一个
encore.service.ts
文件:
typescript
// encore.service.ts
import { Service } from "encore.dev/service";

export default new Service("my-service");

Minimal Service Structure

最小服务结构

my-service/
├── encore.service.ts    # Service definition (required)
├── api.ts               # API endpoints
└── db.ts                # Database (if needed)
my-service/
├── encore.service.ts    # 服务定义(必填)
├── api.ts               # API 端点
└── db.ts                # 数据库(按需添加)

Application Patterns

应用模式

Single Service (Recommended Start)

单服务(推荐入门方案)

Best for new projects - start simple, split later if needed:
my-app/
├── package.json
├── encore.app
├── encore.service.ts
├── api.ts
├── db.ts
└── migrations/
    └── 001_initial.up.sql
最适合新项目——从简单结构开始,按需拆分:
my-app/
├── package.json
├── encore.app
├── encore.service.ts
├── api.ts
├── db.ts
└── migrations/
    └── 001_initial.up.sql

Multi-Service

多服务

For distributed systems with clear domain boundaries:
my-app/
├── encore.app
├── package.json
├── user/
│   ├── encore.service.ts
│   ├── api.ts
│   └── db.ts
├── order/
│   ├── encore.service.ts
│   ├── api.ts
│   └── db.ts
└── notification/
    ├── encore.service.ts
    └── api.ts
适用于具有清晰领域边界的分布式系统:
my-app/
├── encore.app
├── package.json
├── user/
│   ├── encore.service.ts
│   ├── api.ts
│   └── db.ts
├── order/
│   ├── encore.service.ts
│   ├── api.ts
│   └── db.ts
└── notification/
    ├── encore.service.ts
    └── api.ts

Large Application (System-based)

大型应用(基于系统分组)

Group related services into systems:
my-app/
├── encore.app
├── commerce/
│   ├── order/
│   │   └── encore.service.ts
│   ├── cart/
│   │   └── encore.service.ts
│   └── payment/
│       └── encore.service.ts
├── identity/
│   ├── user/
│   │   └── encore.service.ts
│   └── auth/
│       └── encore.service.ts
└── comms/
    ├── email/
    │   └── encore.service.ts
    └── push/
        └── encore.service.ts
将相关服务按系统分组:
my-app/
├── encore.app
├── commerce/
│   ├── order/
│   │   └── encore.service.ts
│   ├── cart/
│   │   └── encore.service.ts
│   └── payment/
│       └── encore.service.ts
├── identity/
│   ├── user/
│   │   └── encore.service.ts
│   └── auth/
│       └── encore.service.ts
└── comms/
    ├── email/
    │   └── encore.service.ts
    └── push/
        └── encore.service.ts

Service-to-Service Calls

服务间调用

Import other services from
~encore/clients
:
typescript
import { user } from "~encore/clients";

export const getOrderWithUser = api(
  { method: "GET", path: "/orders/:id", expose: true },
  async ({ id }): Promise<OrderWithUser> => {
    const order = await getOrder(id);
    const orderUser = await user.get({ id: order.userId });
    return { ...order, user: orderUser };
  }
);
~encore/clients
导入其他服务:
typescript
import { user } from "~encore/clients";

export const getOrderWithUser = api(
  { method: "GET", path: "/orders/:id", expose: true },
  async ({ id }): Promise<OrderWithUser> => {
    const order = await getOrder(id);
    const orderUser = await user.get({ id: order.userId });
    return { ...order, user: orderUser };
  }
);

When to Split Services

何时拆分服务

Split when you have:
SignalAction
Different scaling needsSplit (e.g., auth vs analytics)
Different deployment cyclesSplit
Clear domain boundariesSplit
Shared database tablesKeep together
Tightly coupled logicKeep together
Just organizing codeUse folders, not services
出现以下情况时可考虑拆分:
信号操作
不同的扩容需求拆分(例如:认证服务 vs 分析服务)
不同的部署周期拆分
清晰的领域边界拆分
共享数据库表保持合并
逻辑高度耦合保持合并
仅为代码整理使用文件夹,而非拆分服务

Service with Middleware

带中间件的服务

typescript
import { Service } from "encore.dev/service";
import { middleware } from "encore.dev/api";

const loggingMiddleware = middleware(
  { target: { all: true } },
  async (req, next) => {
    console.log(`Request: ${req.requestMeta?.path}`);
    return next(req);
  }
);

export default new Service("my-service", {
  middlewares: [loggingMiddleware],
});
typescript
import { Service } from "encore.dev/service";
import { middleware } from "encore.dev/api";

const loggingMiddleware = middleware(
  { target: { all: true } },
  async (req, next) => {
    console.log(`Request: ${req.requestMeta?.path}`);
    return next(req);
  }
);

export default new Service("my-service", {
  middlewares: [loggingMiddleware],
});

Guidelines

指导原则

  • Services cannot be nested within other services
  • Start with one service, split when there's a clear reason
  • Use
    ~encore/clients
    for cross-service calls (never direct imports)
  • Each service can have its own database
  • Service names should be lowercase, descriptive
  • Don't create services just for code organization - use folders instead
  • 服务不能嵌套在其他服务内部
  • 从单服务开始,有明确理由时再拆分
  • 服务间调用请使用
    ~encore/clients
    (禁止直接导入)
  • 每个服务可拥有独立数据库
  • 服务名称应使用小写、具有描述性
  • 不要仅为代码整理而创建服务——改用文件夹