Ajouter une carte à Next.js
Une carte est une chose côté client. Elle mesure un élément du DOM, crée un contexte WebGL et
récupère des tuiles au fil du déplacement. Rien de tout cela ne peut se produire pendant le rendu
d'un Server Component, et c'est pourquoi la plupart des guides de cartographie pour Next.js
commencent par un import dynamic() et ssr: false.
Vous n'en avez pas besoin. Les deux approches ci-dessous intègrent la frontière client dans le composant, donc une page Server Component affiche la carte directement.
Installation
Deux façons de commencer, et les onglets ci-dessous restent synchronisés sur toute la page.
Registre copie le composant dans votre projet comme arrive n'importe quel composant shadcn.
Le fichier vous appartient, il suit vos jetons de design, et les contrôles et fenêtres de MapLibre
sont restylés dessus. Il faut un projet avec un components.json.
Paquet installe @unmap/next et importe <Map> depuis celui-ci. Rien n'est copié : le
composant évolue donc avec le SDK, et il fonctionne dans tout projet Next.js, avec ou sans shadcn.
npx @unmap/cli add mapnpm i @unmap/next maplibre-glLa page
// app/page.tsx
import { Map } from "@/components/ui/map";
export default function Page() {
return (
<main className="h-dvh">
<Map
apiKey={process.env.NEXT_PUBLIC_UNMAP_KEY!}
center={[-114.07, 51.05]}
zoom={11}
className="h-full"
/>
</main>
);
}// app/page.tsx
import { Map } from "@unmap/next";
export default function Page() {
return (
<main style={{ height: "100dvh" }}>
<Map
apiKey={process.env.NEXT_PUBLIC_UNMAP_KEY!}
center={[-114.07, 51.05]}
zoom={11}
containerStyle={{ height: "100%" }}
/>
</main>
);
}Voilà toute l'intégration. app/page.tsx reste un Server Component : il ne dit jamais
"use client" et il n'est pas enveloppé dans dynamic().
La feuille de style, sur la voie du paquet seulement
Le composant copié importe lui-même la feuille de style de MapLibre : la voie du registre n'a donc
rien à faire ici. @unmap/next vous en laisse la charge, parce qu'un paquet qui injecte du CSS
global est un paquet dont vous ne maîtrisez plus la cascade. Importez-la une fois dans la mise en
page racine.
// app/layout.tsx
import type { ReactNode } from "react";
import "maplibre-gl/dist/maplibre-gl.css";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="fr">
<body>{children}</body>
</html>
);
}Pourquoi pas de « use client » dans votre page
Les deux composants sont marqués comme frontières client : importer l'un dans un Server Component revient donc à importer n'importe quel autre composant client. Next rend la page environnante sur le serveur, envoie la carte comme îlot client et la monte dans le navigateur.
Cette frontière a une conséquence qu'il vaut la peine de connaître. Les fonctions ne peuvent pas la
traverser, donc un rappel comme onReady doit être passé depuis un composant client :
// app/map-with-marker.tsx
"use client";
import { Map } from "@unmap/next";
import { maplibregl } from "@unmap/sdk";
export default function MapWithMarker() {
return (
<Map
apiKey={process.env.NEXT_PUBLIC_UNMAP_KEY!}
center={[-114.07, 51.05]}
zoom={11}
onReady={(map) => {
new maplibregl.Marker().setLngLat([-114.07, 51.05]).addTo(map);
}}
/>
);
}Sur la voie du registre, vous n'écririez pas cela du tout : marker-popup fournit <Marker> comme
enfant de <Map>, sans aucun rappel.
Où vit la clé
Les variables NEXT_PUBLIC_ sont insérées dans le paquet navigateur, ce qui est correct ici et
mérite d'être dit clairement : une clé utilisée par une carte dans un navigateur est lisible par
quiconque charge la page. C'est vrai chez tous les fournisseurs de cartes. Restreignez la clé à vos
origines de production dans le tableau de bord plutôt que de tenter de la cacher.
# .env.local
NEXT_PUBLIC_UNMAP_KEY=um_live_...Les appels côté serveur sont différents. Un route handler qui géocode une adresse devrait lire une
clé non restreinte depuis une simple variable UNMAP_API_KEY, jamais depuis une variable
NEXT_PUBLIC_.
Problèmes courants
La carte est une boîte vide. Le conteneur n'a pas de hauteur. Les deux composants remplissent leur parent et retombent sur un minimum de 320 px : donnez donc une vraie hauteur au parent.
Aucun bouton de zoom ni attribution, sur la voie du paquet. L'import de la feuille de style manque dans la mise en page. Le composant copié s'en charge pour vous.
Une prop de type fonction déclenche une erreur de frontière. Elle est passée depuis un Server
Component. Déplacez cette partie dans un fichier commençant par "use client", comme ci-dessus.
Pour aller plus loin
- Ajouter une carte à React pour le même travail hors de Next.js
- Composants pour le géocodeur, le panneau d'itinéraire et les marqueurs
- Démarrage rapide pour la version en balise script