vue-fontawesome icon indicating copy to clipboard operation
vue-fontawesome copied to clipboard

Nuxt 3: Hydration mismatch when using SSR

Open christophheich opened this issue 2 years ago • 16 comments

Describe the bug When using Nuxt 3 with the <font-awesome-icon> component while using SSR it causes a hydration node mismatch.

import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
nuxtApp.vueApp.component('font-awesome-icon', FontAwesomeIcon);

Error:

[Vue warn]: Hydration node mismatch:
- Client vnode: svg 
- Server rendered DOM: <!---->  
  at <FontAwesomeIcon icon= Array(2)0: "fal"1: "box-open"length: 2[[Prototype]]: Array(0)at: ƒ at()concat: ƒ concat()constructor: ƒ Array()copyWithin: ƒ copyWithin()entries: ƒ entries()every: ƒ every()fill: ƒ fill()filter: ƒ filter()find: ƒ find()findIndex: ƒ findIndex()findLast: ƒ findLast()findLastIndex: ƒ findLastIndex()flat: ƒ flat()flatMap: ƒ flatMap()forEach: ƒ forEach()includes: ƒ includes()indexOf: ƒ indexOf()join: ƒ join()keys: ƒ keys()lastIndexOf: ƒ lastIndexOf()length: 0map: ƒ map()pop: ƒ pop()push: ƒ push()reduce: ƒ reduce()reduceRight: ƒ reduceRight()reverse: ƒ reverse()shift: ƒ shift()slice: ƒ slice()some: ƒ some()sort: ƒ sort()splice: ƒ splice()toLocaleString: ƒ toLocaleString()toString: ƒ toString()unshift: ƒ unshift()values: ƒ values()Symbol(Symbol.iterator): ƒ values()Symbol(Symbol.unscopables): {at: true, copyWithin: true, entries: true, fill: true, find: true, …}[[Prototype]]: Object class="fa-xl text-white" aria-hidden="true" > 
  at <Index onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <Anonymous key="/" routeProps= Object pageKey="/" > 
  at <BaseTransition mode="out-in" appear=false persisted=false  ... > 
  at <Transition name="page" mode="out-in" > 
  at <RouterView name=undefined route=undefined > 
  at <NuxtPage> 
  at <App key=1 > 
  at <NuxtRoot>
(anonymous) @ instrument.ts:123

Expected behavior Using the component should not cause a node mismatch.

Desktop (please complete the following information):

  • Browser Chrome
  • Version 104.0.5112.102

Additional context Wrapping the <font-awesome-icon> component with <client-only> temporary fixes this issue.

Package.json

    "@fortawesome/fontawesome-svg-core": "^6.1.2",
    "@fortawesome/free-brands-svg-icons": "^6.1.2",
    "@fortawesome/pro-light-svg-icons": "^6.1.2",
    "@fortawesome/pro-regular-svg-icons": "^6.1.2",
    "@fortawesome/pro-solid-svg-icons": "^6.1.2",
    "@fortawesome/pro-thin-svg-icons": "^6.1.2",
    "@fortawesome/vue-fontawesome": "^3.0.1",
    "nuxt": "^3.0.0-rc.8",
    "vue": "^3.2.37",

christophheich avatar Aug 27 '22 08:08 christophheich

same here [email protected] @fortawesome/[email protected]

inomata137 avatar Sep 04 '22 11:09 inomata137

Also getting this issue!

danspratling avatar Sep 14 '22 21:09 danspratling

We'll take a look when we get a chance.

robmadole avatar Sep 20 '22 19:09 robmadole

As a workaround, you can force a icons to render client side only by wrapping it in another component. When this issue is fixed, you can just remove the <ClientOnly> wrapper:

<ClientOnly>
  <FaIcon v-bind="$attrs" />
</ClientOnly>

genu avatar Sep 20 '22 20:09 genu

I second this: issue persists on the following package configuration:

[email protected]
@fortawesome/[email protected]

sweetpalma avatar Sep 25 '22 18:09 sweetpalma

I found this comment: https://github.com/nuxt/nuxt/discussions/16014#discussioncomment-2477885 Fixed the issue for me 👍

Marcoru97 avatar Oct 02 '22 00:10 Marcoru97

For me the hydration warnings was solved by an fix for an other problem i had: https://github.com/FortAwesome/vue-fontawesome/issues/447#issuecomment-1476257130

mkoe-unitb avatar Mar 20 '23 13:03 mkoe-unitb

I can confirm this is still an issue with the latest version of nuxt and fontawesome pro

codeofsumit avatar Jun 07 '23 15:06 codeofsumit

The links above should fix the issue so let's have it clear here (instead of visiting another link):

// nuxt.config.ts
build: {
  transpile: [
    '@fortawesome/fontawesome-svg-core',
    '@fortawesome/pro-solid-svg-
    '@fortawesome/pro-regular-svg-icons',
    '@fortawesome/pro-light-svg-icons',
    '@fortawesome/free-brands-svg-icons'
  ]
}

However, I believe this is something doable with nuxt hooks in a nuxt-plugin. I started working on a nuxt module for vue-fontawesome and hoped to do something slightly better but the current plugin is actually good enough and mine didn't bring a lot more features / easiness so I dropped it.

This should just be documented on the installation with Nuxt section of FontAwesome.

noook avatar Jun 08 '23 13:06 noook

build: {
  transpile: [
    '@fortawesome/fontawesome-svg-core',
    '@fortawesome/pro-solid-svg-
    '@fortawesome/pro-regular-svg-icons',
    '@fortawesome/pro-light-svg-icons',
    '@fortawesome/free-brands-svg-icons'
  ]
}

The transpile should include "@fortawesome/vue-fontawesome" too. At least on my side

luisjoserivera avatar Aug 12 '23 13:08 luisjoserivera

This is my nuxt.config.ts:

build: { transpile: [ "@fortawesome/fontawesome-svg-core", "@fortawesome/pro-solid-svg-icons", "@fortawesome/pro-regular-svg-icons", "@fortawesome/pro-light-svg-icons", "@fortawesome/vue-fontawesome", ], }, css: [ "~/assets/styles/main.scss", "@fortawesome/fontawesome-svg-core/styles.css", ],

and the error is still there:

[Vue warn]: Hydration node mismatch:

  • Client vnode: svg
  • Server rendered DOM: "Some text" (text) at <FontAwesomeIcon icon="fa-solid fa-spinner" >

anrolmar avatar Oct 11 '23 20:10 anrolmar

build: {
  transpile: [
    '@fortawesome/fontawesome-svg-core',
    '@fortawesome/pro-solid-svg-
    '@fortawesome/pro-regular-svg-icons',
    '@fortawesome/pro-light-svg-icons',
    '@fortawesome/free-brands-svg-icons'
  ]
}

The transpile should include "@fortawesome/vue-fontawesome" too. At least on my side

this fix my issue

nuxt: 3.8.1

Val-istar-Guo avatar Nov 11 '23 09:11 Val-istar-Guo

I found this comment: nuxt/nuxt#16014 (comment) Fixed the issue for me 👍

thanks alot

cryptic-dev avatar Feb 20 '24 21:02 cryptic-dev

still issue for laravel 10 with vite (inertiajs - vue3 - ssr)

EnelKyss avatar Feb 27 '24 16:02 EnelKyss

If you're curious, like I was, about why we need to transpile @fortawesome/vue-fontawesome in order to avoid this SSR hydration mismatch, it's because the module field in the package.json file from @fortawesome/vue-fontawesome specifies index.es.js as the entry point (link) but package.json doesn't specify "type": "module" so Node treats this file as a CommonJS module. But index.es.js actually uses ESM syntax, so Node fails to load it and thus the <FontAwesomeIcon> component fails to render on the server since it's not defined.

The Nuxt documentation does an excellent job documenting this problem:

https://nuxt.com/docs/guide/concepts/esm#what-kinds-of-problems-can-there-be

So until @fortawesome/vue-fontawesome is updated to correct this issue, simply configure Nuxt to transpile @fortawesome/vue-fontawesome:

build: {
  transpile: [
    '@fortawesome/vue-fontawesome',
  ],
},

d-low avatar May 03 '24 12:05 d-low