encore-frontend

Par encoredev · skills

Connectez des applications React/Next.js à des backends Encore.ts.

npx skills add https://github.com/encoredev/skills --skill encore-frontend

Intégration Frontend avec Encore

Instructions

Encore fournit des outils pour connecter vos applications frontend à vos API backend.

Générer un Client TypeScript

# Générer un client pour le développement local
encore gen client --output=./frontend/src/client.ts --env=local

# Générer un client pour un environnement déployé
encore gen client --output=./frontend/src/client.ts --env=staging

Cela génère un client entièrement typé basé sur vos définitions d'API.

Utiliser le Client Généré

// frontend/src/client.ts est auto-généré
import Client from "./client";

const client = new Client("http://localhost:4000");

// Appels API entièrement typés
const user = await client.user.getUser({ id: "123" });
console.log(user.email);

const newUser = await client.user.createUser({
  email: "new@example.com",
  name: "New User",
});

Exemple 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 avec 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>
  );
}

Composants Serveur 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>
  );
}

Configuration CORS

Configurez CORS dans votre fichier encore.app :

{
    "id": "my-app",
    "global_cors": {
        "allow_origins_with_credentials": [
            "http://localhost:3000",
            "https://myapp.com",
            "https://*.myapp.com"
        ]
    }
}

Options CORS

Option Description
allow_origins_without_credentials Origines autorisées pour les requêtes sans identifiants (défaut : ["*"])
allow_origins_with_credentials Origines autorisées pour les requêtes avec identifiants (cookies, headers d'auth)
allow_headers Headers de requête supplémentaires à autoriser
expose_headers Headers de réponse supplémentaires à exposer
debug Activer la journalisation de débogage CORS

Authentification depuis le Frontend

Pour les requêtes authentifiées, transmettez le header Authorization :

// Utiliser fetch
const response = await fetch("http://localhost:4000/profile", {
  headers: {
    "Authorization": `Bearer ${token}`,
  },
});

// Ou inclure les identifiants pour l'auth basée sur les cookies
const response = await fetch("http://localhost:4000/profile", {
  credentials: "include",
});

Avec TanStack Query, configurez un fetcher par défaut :

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();
      },
    },
  },
});

Utiliser Fetch Brut

Si vous préférez ne pas utiliser le client généré :

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();
}

Variables d'Environnement

# .env.local (Next.js)
NEXT_PUBLIC_API_URL=http://localhost:4000

# .env (Vite)
VITE_API_URL=http://localhost:4000

Recommandations

  • Utilisez encore gen client pour générer des clients API typés
  • Régénérez le client quand votre API change
  • Configurez CORS dans encore.app pour les domaines de production
  • Utilisez allow_origins_with_credentials pour les requêtes authentifiées
  • Incluez le header Authorization pour l'auth basée sur les tokens
  • Utilisez credentials: "include" pour l'auth basée sur les cookies
  • Utilisez les variables d'environnement pour les URLs d'API (différentes par environnement)
  • Le client généré gère les erreurs et les types automatiquement

Skills similaires