关于 encore-frontend
encore-frontend 指导使用 Encore API 定义生成 TypeScript 客户端,并在 React、TanStack Query 和 Next.js 中调用后端。适合连接 Encore 后端的前端开发者,也涵盖 CORS 与认证配置。
主要功能
- 01生成带类型的 TypeScript 客户端
- 02提供 React 调用示例
- 03提供 TanStack Query 示例
- 04支持 Next.js 服务端组件
- 05说明 CORS 与认证配置
适用场景
- 01为本地或部署环境生成 API 客户端
- 02在 React 页面获取后端数据
- 03在 Next.js 服务端组件调用 API
- 04配置跨域及认证请求
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ encoredev/ skills --skill encore-frontend安装后在 Claude Code 中输入/encore-frontend确认已加载。
详细介绍
使用 Encore 进行前端集成
说明
Encore 提供用于将前端应用连接到后端 API 的工具。
生成 TypeScript 客户端
# Generate client for local development
encore gen client --output=./frontend/src/client.ts --env=local
# Generate client for a deployed environment
encore gen client --output=./frontend/src/client.ts --env=staging
这会根据你的 API 定义生成一个完全类型化的客户端。
使用生成的客户端
// frontend/src/client.ts is auto-generated
import Client from "./client";
const client = new Client("http://localhost:4000");
// Fully typed API calls
const user = await client.user.getUser({ id: "123" });
console.log(user.email);
const newUser = await client.user.createUser({
email: "[email protected]",
name: "New User",
});
React 示例
// frontend/src/components/UserProfile.tsx
import { useState, useEffect } from "react";
import Client from "../client";
const client = new Client(import.meta.env.VITE_API_URL);
export function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
client.user.getUser({ id: userId })
.then(setUser)
.catch(setError)
.finally(() => setLoading(false));
}, [userId]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
将 React 与 TanStack Query 配合使用
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import Client from "../client";
const client = new Client(import.meta.env.VITE_API_URL);
export function UserProfile({ userId }: { userId: string }) {
const { data: user, isLoading, error } = useQuery({
queryKey: ["user", userId],
queryFn: () => client.user.getUser({ id: userId }),
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{user.name}</div>;
}
export function CreateUserForm() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: (data: { email: string; name: string }) =>
client.user.createUser(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["users"] });
},
});
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
mutation.mutate({
email: formData.get("email") as string,
name: formData.get("name") as string,
});
};
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" required />
<input name="name" required />
<button type="submit" disabled={mutation.isPending}>
{mutation.isPending ? "Creating..." : "Create User"}
</button>
</form>
);
}
Next.js 服务端组件
// app/users/[id]/page.tsx
import Client from "@/lib/client";
const client = new Client(process.env.API_URL);
export default async function UserPage({ params }: { params: { id: string } }) {
const user = await client.user.getUser({ id: params.id });
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
CORS 配置
在 encore.app 文件中配置 CORS:
{
"id": "my-app",
"global_cors": {
"allow_origins_with_credentials": [
"http://localhost:3000",
"https://myapp.com",
"https://*.myapp.com"
]
}
}
CORS 选项
| 选项 | 说明 |
|---|---|
allow_origins_without_credentials | 允许无凭据请求的源(默认值:["*"]) |
allow_origins_with_credentials | 允许携带凭据(Cookie、身份验证标头)的请求的源 |
allow_headers | 允许的其他请求标头 |
expose_headers | 暴露的其他响应标头 |
debug | 启用 CORS 调试日志 |
从前端进行身份验证
对于经过身份验证的请求,请传递 Authorization 标头:
// Using fetch
const response = await fetch("http://localhost:4000/profile", {
headers: {
"Authorization": `Bearer ${token}`,
},
});
// Or include credentials for cookie-based auth
const response = await fetch("http://localhost:4000/profile", {
credentials: "include",
});
使用 TanStack Query 时,可配置默认的 fetcher:
const queryClient = new QueryClient({
defaultOptions: {
queries: {
queryFn: async ({ queryKey }) => {
const response = await fetch(queryKey[0] as string, {
headers: { Authorization: `Bearer ${getToken()}` },
});
if (!response.ok) throw new Error("Request failed");
return response.json();
},
},
},
});
使用原生 Fetch
如果你不想使用生成的客户端:
async function getUser(id: string) {
const response = await fetch(`http://localhost:4000/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
return response.json();
}
async function createUser(email: string, name: string) {
const response = await fetch("http://localhost:4000/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, name }),
});
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
return response.json();
}
环境变量
# .env.local (Next.js)
NEXT_PUBLIC_API_URL=http://localhost:4000
# .env (Vite)
VITE_API_URL=http://localhost:4000
指南
- 使用
encore gen client生成类型化 API 客户端 - API 发生变化时,重新生成客户端
- 在
encore.app中为生产环境域名配置 CORS - 对经过身份验证的请求使用
allow_origins_with_credentials - 使用基于令牌的身份验证时,包含
Authorization标头 - 使用基于 Cookie 的身份验证时,设置
credentials: "include" - 使用环境变量配置 API URL(不同环境使用不同的 URL)
- 生成的客户端会自动处理错误和类型
评论
支持 Markdown