當你需要在 TypeScript 專案中加入持久化執行(durable execution)時使用——建立可重試的 Webhook 處理器、能在崩潰後繼續執行的背景任務、排程工作,或是跨越單一請求的長時間工作流程。涵蓋 Inngest SDK 安裝、客戶端設定、環境變數、serve 端點(Next.js、Express、Hono、Fastify)、connect-as-worker 模式以及本機開發伺服器。
Inngest 設定
這個技能會從頭開始在 TypeScript 專案中設定 Inngest,涵蓋安裝、客戶端設定、連線模式以及本機開發。
這些技能專注於 TypeScript。 若使用 Python 或 Go,請參考 Inngest 文件 以取得語言專屬指引。核心概念在所有語言中皆適用。
前置需求
- Node.js 18+(建議使用 Node.js 22.4+ 以支援 WebSocket)
- TypeScript 專案
- 套件管理工具(npm、yarn、pnpm 或 bun)
步驟 1:安裝 Inngest SDK
在專案中安裝 inngest npm 套件:
npm install inngest
# 或
yarn add inngest
# 或
pnpm add inngest
# 或
bun add inngest
步驟 2:建立 Inngest 客戶端
建立一個共用的客戶端檔案,以便在整個程式碼庫中匯入:
// src/inngest/client.ts
import { Inngest } from "inngest";
export const inngest = new Inngest({
id: "my-app" // 應用程式的唯一識別碼(使用連字號的 slug)
});
// 重要:v4 預設為 Cloud 模式。本機開發請設定 INNGEST_DEV=1 環境變數。
// 若未設定,serve 端點會回傳 500(「在 Cloud 模式下但未提供 signing key」)。
// 正式環境需設定 INNGEST_SIGNING_KEY(Cloud 模式必要)。
主要設定選項
id(必要):應用程式的唯一識別碼。使用連字號 slug,例如"my-app"或"user-service"eventKey:用於傳送事件的 Event Key(建議使用INNGEST_EVENT_KEY環境變數)env:分支環境的環境名稱isDev:強制 Dev 模式(true)或 Cloud 模式(false)。v4 預設為 Cloud 模式,因此本機開發需設定INNGEST_DEV=1環境變數。切勿在原始碼中寫死isDev: true——這會在正式環境中無聲地失效。請一律使用環境變數。signingKey:正式環境的簽署金鑰(建議使用INNGEST_SIGNING_KEY環境變數)。v4 中已從serve()移至客戶端signingKeyFallback:用於金鑰輪替的備用簽署金鑰(建議使用INNGEST_SIGNING_KEY_FALLBACK環境變數)baseUrl:自訂的 Inngest API 基礎 URL(建議使用INNGEST_BASE_URL環境變數)logger:自訂的 logger 實例(例如 winston、pino)——可在函式上下文中啟用loggermiddleware:中介軟體陣列(請參閱 inngest-middleware 技能)
使用 eventType() 的型別事件
import { Inngest, eventType } from "inngest";
import { z } from "zod";
const signupCompleted = eventType("user/signup.completed", {
schema: z.object({
userId: z.string(),
email: z.string(),
plan: z.enum(["free", "pro"])
})
});
const orderPlaced = eventType("order/placed", {
schema: z.object({
orderId: z.string(),
amount: z.number()
})
});
export const inngest = new Inngest({ id: "my-app" });
// 將事件型別作為觸發器以獲得完整的型別安全:
inngest.createFunction(
{ id: "handle-signup", triggers: [signupCompleted] },
async ({ event }) => {
event.data.userId; /* 型別為 string */
}
);
// 傳送事件時使用事件型別:
await inngest.send(
signupCompleted.create({
userId: "user_123",
email: "user@example.com",
plan: "pro"
})
);
環境變數設定
在 .env 檔案或部署環境中設定這些環境變數:
# 正式環境必要
INNGEST_EVENT_KEY=your-event-key-here
INNGEST_SIGNING_KEY=your-signing-key-here
# 本機開發時強制 Dev 模式
INNGEST_DEV=1
# 選用 - 自訂開發伺服器 URL(預設:http://localhost:8288)
INNGEST_BASE_URL=http://localhost:8288
⚠️ 常見陷阱:切勿在原始碼中寫死金鑰。請一律使用環境變數來設定 INNGEST_EVENT_KEY 和 INNGEST_SIGNING_KEY。
關鍵:啟用 Dev 模式以進行本機開發
在建立 serve 端點或連線 worker 之前,請確認 Dev 模式已啟用。 若未啟用,Inngest 會預設為 Cloud 模式,導致端點回傳 500 錯誤。
在 .env 檔案(或 package.json 中的開發腳本)中加入:
INNGEST_DEV=1
或在 package.json 腳本中:
{
"scripts": {
"dev": "INNGEST_DEV=1 tsx --watch src/server.ts"
}
}
缺少 INNGEST_DEV 的症狀:
- GET
/api/inngest回傳{"code":"internal_server_error"} - 伺服器日誌:「在 Cloud 模式下但未提供 signing key」
- 開發伺服器無法與應用程式同步
步驟 3:選擇連線模式
Inngest 支援兩種連線模式:
模式 A:Serve 端點(HTTP)
最適合無伺服器平台(Vercel、Lambda 等)和現有 API。
模式 B:Connect(WebSocket)
最適合容器執行環境(Kubernetes、Docker)和長時間執行的程序。
步驟 4A:提供 Serve 端點(HTTP 模式)
建立一個 API 端點,將函式暴露給 Inngest:
// 適用於 Next.js App Router:src/app/api/inngest/route.ts
import { serve } from "inngest/next";
import { inngest } from "../../../inngest/client";
import { myFunction } from "../../../inngest/functions";
export const { GET, POST, PUT } = serve({
client: inngest,
functions: [myFunction]
});
// 適用於 Next.js Pages Router:pages/api/inngest.ts
import { serve } from "inngest/next";
import { inngest } from "../../inngest/client";
import { myFunction } from "../../inngest/functions";
export default serve({
client: inngest,
functions: [myFunction]
});
// 適用於 Express.js
import express from "express";
import { serve } from "inngest/express";
import { inngest } from "./inngest/client";
import { myFunction } from "./inngest/functions";
const app = express();
app.use(express.json({ limit: "10mb" })); // Inngest 必要,增加限制以支援較大的函式狀態
app.use(
"/api/inngest",
serve({
client: inngest,
functions: [myFunction]
})
);
🔧 框架專屬注意事項:
- Express:必須使用
express.json({ limit: "10mb" })中介軟體以支援較大的函式狀態。 - Fastify:使用
inngest/fastify提供的fastifyPlugin - Cloudflare Workers:使用
inngest/cloudflare - AWS Lambda:使用
inngest/lambda - 其他框架請參閱
serve參考文件:https://www.inngest.com/docs-markdown/learn/serving-inngest-functions
⚠️ v4 變更: signingKey、signingKeyFallback 和 baseUrl 等選項現在是在 Inngest 客戶端建構函式中設定,而非 serve()。serve() 函式僅接受 client、functions 和 streaming。
⚠️ 常見陷阱:請一律使用 /api/inngest 作為端點路徑。這樣可以啟用自動探索。如果必須使用其他路徑,則需要使用 -u 標記手動設定探索。
步驟 4B:以 Worker 連線(WebSocket 模式)
適用於維持持久連線的長時間執行應用程式:
// src/worker.ts
import { connect } from "inngest/connect";
import { inngest } from "./inngest/client";
import { myFunction } from "./inngest/functions";
(async () => {
const connection = await connect({
apps: [{ client: inngest, functions: [myFunction] }],
instanceId: process.env.HOSTNAME, // 唯一的 worker 識別碼
maxWorkerConcurrency: 10 // 最大並行步驟數
});
console.log("Worker 已連線:", connection.state);
// 優雅關機處理
await connection.closed;
console.log("Worker 已關閉");
})();
Connect 模式的需求:
- Node.js 22.4+(或 Deno 1.4+、Bun 1.1+)以支援 WebSocket
- 長時間執行的伺服器環境(非無伺服器)
- 正式環境需要
INNGEST_SIGNING_KEY和INNGEST_EVENT_KEY - 在正式環境中,在
Inngest客戶端上設定appVersion參數以支援滾動部署
v4 Connect 變更:
- Worker 執行緒隔離預設啟用——WebSocket 連線在 worker 執行緒中執行,以防止事件迴圈飢餓。設定
isolateExecution: false以使用單一程序(或INNGEST_CONNECT_ISOLATE_EXECUTION=false) rewriteGatewayEndpoint回呼已被gatewayUrl字串選項取代(或INNGEST_CONNECT_GATEWAY_URL環境變數)
步驟 5:使用 Apps 組織
隨著系統成長,將函式組織成邏輯上的 apps:
// 使用者服務
const userService = new Inngest({ id: "user-service" });
// 付款服務
const paymentService = new Inngest({ id: "payment-service" });
// 電子郵件服務
const emailService = new Inngest({ id: "email-service" });
每個 app 在 Inngest 儀表板中都會有自己的區塊,並且可以獨立部署。使用描述性、連字號的 ID,並與你的服務架構相符。
⚠️ 常見陷阱:變更 app 的 id 會在 Inngest 中建立一個新的 app。請保持 ID 在部署之間的一致性。
步驟 6:使用 inngest-cli 進行本機開發
啟動 Inngest 開發伺服器以進行本機開發:
# 自動探索常見連接埠/端點上的應用程式
npx --ignore-scripts=false inngest-cli@latest dev
# 手動指定應用程式的 URL
npx --ignore-scripts=false inngest-cli@latest dev -u http://localhost:3000/api/inngest
# 自訂開發伺服器連接埠
npx --ignore-scripts=false inngest-cli@latest dev -p 9999
# 停用自動探索
npx --ignore-scripts=false inngest-cli@latest dev --no-discovery -u http://localhost:3000/api/inngest
# 多個應用程式
npx --ignore-scripts=false inngest-cli@latest dev -u http://localhost:3000/api/inngest -u http://localhost:4000/api/inngest
開發伺服器預設會在 http://localhost:8288 提供服務。
設定檔(選用)
針對複雜設定,建立 inngest.json:
{
"sdk-url": [
"http://localhost:3000/api/inngest",
"http://localhost:4000/api/inngest"
],
"port": 8289,
"no-discovery": true
}
環境專屬設定
本機開發
INNGEST_DEV=1
# Dev 模式不需要金鑰
正式環境
INNGEST_EVENT_KEY=evt_your_production_event_key
INNGEST_SIGNING_KEY=signkey_your_production_signing_key
自訂開發伺服器連接埠
INNGEST_DEV=1
INNGEST_BASE_URL=http://localhost:9999
如果你的應用程式執行在非標準連接埠(非 3000),請使用 -u 標記指定 URL,以確保開發伺服器可以連線到它。
常見問題與解決方案
連接埠衝突:如果連接埠 8288 已被佔用,請使用 -p 9999 指定不同的連接埠。
自動探索無法運作:使用手動 URL 指定:-u http://localhost:YOUR_PORT/api/inngest。如果使用 --no-discovery 標記,則 -u 標記是必要的——開發伺服器將無法找到你的應用程式。
函式未顯示在開發伺服器中:你的應用程式必須向開發伺服器註冊。當你的 serve 端點收到來自開發伺服器的第一個請求時,這會自動發生。如果註冊未發生:(1) 確認已設定 INNGEST_DEV=1,(2) 確認開發伺服器可以連線到你的應用程式 URL,(3) 嘗試在開發伺服器執行時重新啟動你的應用程式。
簽章驗證錯誤:確保在正式環境中正確設定 INNGEST_SIGNING_KEY
WebSocket 連線問題:確認 Node.js 版本為 22.4+ 以使用 connect 模式
Docker 開發:當開發伺服器在 Docker 中執行時,應用程式 URL 請使用 host.docker.internal
後續步驟
- 使用
inngest.createFunction()建立你的第一個 Inngest 函式 - 使用開發伺服器的「Invoke」按鈕測試函式
- 使用
inngest.send()傳送事件以觸發函式 - 使用適當的環境變數部署到正式環境
- 參閱 inngest-middleware 以了解如何加入日誌、錯誤追蹤和其他橫切關注點
- 在 Inngest 儀表板中監控函式
開發伺服器會在函式變更時自動重新載入,使開發快速且迭代。




