FortAwesome / vue-fontawesome

Font Awesome Vue component
https://fontawesome.com
MIT License
2.39k stars 133 forks source link

Nuxt 3: Hydration mismatch when using SSR #394

Open christophheich opened 2 years ago

christophheich commented 2 years ago

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):

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",
inomata137 commented 2 years ago

same here nuxt@3.0.0-rc.9 @fortawesome/vue-fontawesome@3.0.1

danspratling commented 2 years ago

Also getting this issue!

robmadole commented 2 years ago

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

genu commented 2 years ago

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>
sweetpalma commented 2 years ago

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

nuxt@3.0.0-rc.9
@fortawesome/vue-fontawesome@3.0.1
Marcoru97 commented 2 years ago

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

mkoe-unitb commented 1 year ago

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

codeofsumit commented 1 year ago

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

noook commented 1 year ago

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.

luisjoserivera commented 1 year ago
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

anrolmar commented 1 year ago

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:

Val-istar-Guo commented 1 year ago
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

cryptic-dev commented 9 months ago

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

thanks alot

EnelKyss commented 8 months ago

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

d-low commented 6 months ago

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',
  ],
},
Kuruyia commented 1 month ago

I know that this is a Nuxt-related issue, but because it is so high up in search results, here's the equivalent configuration for plain Vite/SSR (tested with VuePress 2.0.0-rc.17, Vue 3.5.10 and Vite v5.4.8):

export default defineConfig({
  ssr: {
    noExternal: ['@fortawesome/vue-fontawesome'],
  },
})