Rendu à la Racine d'un Sous-domaine SPA Sans Redirection
Problème
Lors de la construction de routage basé sur des sous-domaines (par exemple, username.example.com), l'utilisation de
<Navigate to="/profile/username" replace /> de React Router modifie l'URL, ce qui va à l'encontre de l'objectif
d'avoir une URL de sous-domaine propre. De plus, le composant cible peut afficher une page blanche
s'il dépend de useParams() pour obtenir des paramètres de route qui n'existent pas à /.
Contexte / Conditions de Déclenchement
- La page de profil du sous-domaine redirige vers
/profile/npub1...au lieu de servir le contenu à/ - La page apparaît blanche (aucun contenu ne se charge) à la racine du sous-domaine
- Le composant utilise
useParams()et échoue lorsqu'il est rendu sur une route sans ces paramètres - Le worker périphérique injecte les données utilisateur dans
window.__SUBDOMAIN_USER__ou une variable globale similaire - On souhaite que
username.domain.com/se rende comme un site web personnel
Solution
1. Routeur : Rendre le Composant Directement au Lieu de Naviguer
Avant (provoque une redirection + un changement d'URL) :
<Route path="/" element={
subdomainUser
? <Navigate to={`/profile/${subdomainUser.npub}`} replace />
: <Index />
} />
Après (rend à / sans changement d'URL) :
<Route path="/" element={
subdomainUser
? <ProfilePage />
: <Index />
} />
2. Composant : Ajouter une Source de Données de Repli
Le composant doit vérifier les données injectées du sous-domaine lorsque les paramètres de route sont manquants.
Avant (vérifie uniquement les paramètres de route) :
export function ProfilePage() {
const { npub } = useParams<{ npub?: string }>();
const identifier = npub;
if (!identifier) {
return <Error message="Aucun identifiant utilisateur fourni" />;
}
// ... reste du composant
}
Après (utilise les données injectées comme solution de repli) :
import { getSubdomainUser } from '@/hooks/useSubdomainUser';
export function ProfilePage() {
const { npub } = useParams<{ npub?: string }>();
const subdomainUser = getSubdomainUser();
// Le paramètre de route a la priorité, les données du sous-domaine sont le repli
const identifier = npub || subdomainUser?.npub;
if (!identifier) {
return <Error message="Aucun identifiant utilisateur fourni" />;
}
// ... reste du composant
}
3. Worker Périphérique : Injecter les Données Utilisateur dans le HTML
Le worker périphérique (Fastly Compute, Cloudflare Workers, etc.) doit injecter les données utilisateur :
// Dans le worker périphérique gérant le sous-domaine
const userData = await fetchUserData(username);
const html = await fetchSpaHtml();
const injectedHtml = html.replace(
'</head>',
`<script>window.__DIVINE_USER__ = ${JSON.stringify(userData)};</script></head>`
);
return new Response(injectedHtml, { headers: { 'content-type': 'text/html' } });
4. Accès aux Données Côté Client
// useSubdomainUser.ts
interface SubdomainUser {
subdomain: string;
pubkey: string;
npub: string;
username?: string;
displayName?: string;
// ... autres champs
}
export function getSubdomainUser(): SubdomainUser | null {
if (typeof window === 'undefined') return null;
return (window as any).__DIVINE_USER__ || null;
}
Vérification
- Visitez
username.domain.com/- l'URL doit rester à/, pas de redirection - Le contenu du profil doit se charger correctement
- Vérifiez la console du navigateur pour l'absence d'erreurs concernant les identifiants manquants
- Vérifiez que
window.__DIVINE_USER__contient les données attendues dans les outils de développement
Exemple
Pour divine-web :
thecomedianriley.divine.video/rend ProfilePage à/- ProfilePage vérifie
useParams()en premier (vide à/) - Utilise
getSubdomainUser()?.npubcomme solution de repli à partir des données injectées - Le profil se charge sans changement d'URL
Remarques
- Ce pattern nécessite une coordination entre le worker périphérique et le code client
- Le worker périphérique doit injecter les données avant l'hydratation de la SPA
- Vérifiez toujours les paramètres de route en premier pour que les routes normales
/profile/:npubfonctionnent - Pensez au SEO : le worker périphérique doit également définir les balises meta appropriées
- Les liens sur le sous-domaine peuvent utiliser le composant
SmartLinkpour rester locaux pour le contenu du propriétaire, mais lier vers le domaine racine pour le contenu des autres utilisateurs
Références
- Routes React Router v6 : https://reactrouter.com/en/main/route/route
- Fastly Compute@Edge : https://developer.fastly.com/learning/compute/