Retour
Publié le Sep 2, 2024, mis à jour le Sep 6, 2024

Utiliser new Date() dans Nuxt

À un moment donné du développement de votre application JavaScript Nuxt, vous souhaiterez utiliser l'objet Date via son constructeur new Date() pour obtenir la date ou l'heure actuelle.

const now = new Date()

Ce faisant, vous obtiendrez une erreur de décalage d'hydratation (hydration mismatch). En effet, new Date() est exécuté côté serveur lors de la génération de la page, puis côté client lors de l'hydratation de la page. Les deux dates étant séparées de quelques millisecondes, Nuxt détecte une différence dans leur valeur respective et retourne un avertissement de décalage d'hydratation dans la console.

<script setup>
const now = new Date()
</script>

<template>
  <div>{{ now }}</div>
</template>

Solution

La solution la plus simple et efficace consiste à envelopper new Date() dans la fonction Nuxt useState().

<script setup>
const now = useState(() => new Date())
console.log(now.value)
</script>

<template>
  <div>{{ now }}</div>
</template>

La valeur de now est maintenant calculée côté serveur, puis envoyée au client via la variable payload1 de Nuxt.

Pour en savoir plus : useState composable - Nuxt docs

Autres pistes

Suivant le contexte, il existe d'autres façons de gérer ou de contourner ce problème. Il faudra alors garder à l'esprit que la date retournée par new Date() est différente côté serveur et côté client.

  • En utilisant le composant Nuxt <ClientOnly>2
<script setup>
const now = new Date()
</script>

<template>
  <ClientOnly>
    <h1>{{ now }}</h1>
  </ClientOnly>
</template>
  • En rajoutant le suffixe .client.vue au fichier de la page3 ou du composant4, pour que celui-ci ne soit exécuté que côté client.
  • En utilisant le crochet onMounted() proposé par Vue.js5, qui n'est pas exécuté côté serveur.
<script setup>
const now = ref()
onMounted(() => {
  now.value = new Date()
})
</script>
  • Ou inversement, calculer la variable côté serveur seulement, en utilisant l'objet import.meta.server6 de Nuxt. ⚠ now.value sera undefined côté client !
<script setup>
const now = ref()
if (import.meta.server) {
  now.value = new Date()
}
</script>
  • Depuis Vue v3.5, il est possible d'utiliser l'attribut data-allow-mismatch pour effacer l'avertissment de décalage d'hydratation dans la console7.

Footnotes

  1. 1. NuxtApp payload - Nuxt docs
  2. 2. <ClientOnly> - Nuxt docs
  3. 3. Client-only Pages - Nuxt docs
  4. 4. Client-only Components - Nuxt docs
  5. 5. onMounted - Vue.js docs
  6. 6. Import meta - Nuxt docs
  7. 7. data-allow-mismatch - Vue.js docs