Ajouter une carte à Nuxt

Nuxt rend d'abord sur le serveur, et une carte ne le peut pas. La réponse habituelle consiste à entourer de <ClientOnly> tout ce qui touche à MapLibre. @unmap/nuxt resserre cela : les composables peuvent être importés pendant le SSR, donc seul l'élément qui monte le canevas a besoin d'être protégé, et le module place votre clé sur la configuration d'exécution, là où elle doit être.

Installation

Module enregistre @unmap/nuxt, qui importe automatiquement les composables dans chaque composant et publie la clé dans la configuration d'exécution publique.

Registre copie un UnmapMap.vue dans votre projet via shadcn-vue. Avec shadcn-nuxt, il est importé automatiquement sous <UiUnmapMap> et il suit vos jetons de design.

npx nuxi module add @unmap/nuxt

Définir la clé

Le module lit unmap.key dans nuxt.config.ts, et NUXT_PUBLIC_UNMAP_KEY a priorité à l'exécution. Préférez la variable d'environnement : elle garde la clé hors du dépôt et permet à la préproduction et à la production de différer sans reconstruction.

# .env
NUXT_PUBLIC_UNMAP_KEY=um_live_...

Cette valeur atteint le navigateur, ce qui est correct pour une clé de carte et mérite d'être dit clairement : une clé utilisée par une carte dans un navigateur est lisible par quiconque charge la page, chez tous les fournisseurs. Restreignez-la à vos origines de production dans le tableau de bord plutôt que de tenter de la cacher.

La page

useUnmap est importé automatiquement par le module : la ligne d'import ci-dessous est donc facultative. Elle est écrite parce qu'un import explicite reste du Nuxt valide, et parce que c'est la ligne qui dit au lecteur d'où vient le composable.

<script setup lang="ts">
import { useUnmap } from "@unmap/vue";
 
const config = useRuntimeConfig();
const { mapContainer } = useUnmap({
  key: config.public.unmap.key,
  center: [-114.07, 51.05],
  zoom: 11,
});
</script>
 
<template>
  <ClientOnly>
    <div ref="mapContainer" style="height: 100dvh" />
  </ClientOnly>
</template>

<ClientOnly> entoure le conteneur, pas le script. Le composable lui-même est sûr en SSR : il crée la carte dans onMounted derrière une garde typeof window et importe le paquet maplibre-gl paresseusement, donc rien ne touche au DOM sur le serveur. Entourer aussi l'élément évite une erreur d'hydratation sur les attributs du conteneur.

Ce qui est vérifié ici et ce qui ne l'est pas

Les extraits de cette page sont compilés avec les vrais types des paquets, et config.public.unmap est vérifié avec la forme que le module publie réellement. Deux choses ne le sont pas : les templates Vue, qui demandent le service de langage Vue plutôt que tsc, et les fonctions intégrées de Nuxt, qui sont remplacées par des déclarations locales. Une faute dans une liaison :prop vous parviendra donc plutôt qu'à un test.

Cela vaut la peine d'être su avant de copier un template en entier depuis n'importe où, y compris cette page.

Problèmes courants

window is not defined à la construction. Quelque chose a importé maplibre-gl au niveau du module. Importez-le dans onMounted, ou laissez le composable le faire pour vous.

Une erreur d'hydratation sur le conteneur de carte. L'élément a été rendu sur le serveur puis modifié sur le client. <ClientOnly> autour du conteneur corrige cela.

La clé est vide et chaque tuile renvoie 401. NUXT_PUBLIC_UNMAP_KEY n'était pas définie dans l'environnement qui a construit ou servi l'application. Le module réduit à une chaîne vide au lieu de lever une erreur, donc la panne apparaît à la première requête et non au démarrage.

Pour aller plus loin