S'il y a bien un concept qui génère encore des sueurs froides lors des audits de sécurité d'applications Next.js en 2026, c'est l'incompréhension fondamentale de la directive "use server".
Je vois trop souvent des développeurs (même seniors) ajouter "use server" en haut de leurs fichiers de services ou d'utilitaires BDD, pensant que cela signifie : "S'il te plaît Next.js, garde ce code sur le serveur pour qu'il soit sécurisé".
C'est l'inverse.
En écrivant "use server", vous ne sécurisez pas votre code. Vous créez un endpoint API public. Pour être un architecte Next.js compétent, il faut distinguer la Porte du Mur.
1. "use server" : La Porte (L'Exposition)
La directive "use server" marque une fonction comme étant une Server Action.
Concrètement, qu'est-ce que le compilateur fait ? Il prend votre fonction, génère une référence unique, et crée un endpoint HTTP accessible publiquement. Il permet au client (le navigateur) d'appeler cette fonction via une requête POST RPC (Remote Procedure Call).
C'est une déclaration d'intention publique.
Si vous mettez "use server" en haut d'un fichier db.ts qui contient des fonctions de suppression d'utilisateurs sans vérification d'authentification stricte à l'intérieur même de la fonction, vous venez littéralement d'offrir une API d'administration au monde entier.
La règle d'or : Utilisez "use server" uniquement pour les points d'entrée (les contrôleurs) qui doivent être appelés par l'UI (soumission de formulaire, boutons).
2. "server-only" : Le Mur (La Protection)
Si vous voulez vous assurer qu'un fichier (ex: users.data.ts, secrets.ts) ne fuite jamais dans le bundle client, vous ne devez pas utiliser "use server". Vous devez utiliser le package server-only.
import 'server-only';
export const getSecretKey = () => process.env.SECRET_KEY;
Ceci est une "poison pill" (pilule empoisonnée). Si un développeur de votre équipe tente par erreur d'importer ce fichier dans un Client Component ("use client"), le build va crasher immédiatement.
C'est une sécurité Build-time. Elle protège votre architecture contre l'erreur humaine. Elle garantit que vos clés API privées et votre logique lourde (ORM) restent dans le coffre-fort du serveur, invisibles pour le client.
3. L'Architecture idéale : Le "Sandwich" Sécurisé
Comment combiner les deux pour une architecture robuste ? J'utilise le pattern "Gateway" :
La Couche Privée (DAL - Data Access Layer) : Vos fichiers de données (users.data.ts) contiennent la logique métier brute et l'accès BDD. Ils importent 'server-only'. Ils sont invisibles pour le client.
La Couche Publique (Actions) : Vos fichiers d'actions (actions.ts) contiennent "use server". Ils servent de Douane. Ils ne contiennent pas de logique métier complexe, ils orchestrent :
Validation des entrées (Zod).
Vérification de l'Authentification/Autorisation.
Appel à la couche privée.
La Couche Client (UI) : Votre UI (RegisterForm.tsx) utilise "use client" et appelle les fonctions de la couche publique.
Conclusion
Arrêtez de saupoudrer "use server" partout en espérant que ça optimise votre code.
L'ingénierie web, c'est savoir fermer les portes autant que de savoir les ouvrir.