mcpField
E
encore-frontend

encore-frontend

github.com/encoredev开发30777 次安装2 天前更新
代码仓库

关于 encore-frontend

encore-frontend 指导使用 Encore API 定义生成 TypeScript 客户端,并在 React、TanStack Query 和 Next.js 中调用后端。适合连接 Encore 后端的前端开发者,也涵盖 CORS 与认证配置。

主要功能

  1. 01生成带类型的 TypeScript 客户端
  2. 02提供 React 调用示例
  3. 03提供 TanStack Query 示例
  4. 04支持 Next.js 服务端组件
  5. 05说明 CORS 与认证配置

适用场景

  1. 01为本地或部署环境生成 API 客户端
  2. 02在 React 页面获取后端数据
  3. 03在 Next.js 服务端组件调用 API
  4. 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