I'm currently working on converting an existing Vue 3 front-end project into an SSR (Server-Side Rendering) project using Vite
, Vue 3
, Pinia
, vue-i18n
and Koa
.
However, I've run into an issue. My repository is available.
The key code is: index.html
, server-dev.ts
, server-prod.ts
, entry-client.ts
, entry-server.ts
, vite.config.ts
A similar issue is https://github.com/vitejs/vite/issues/7900
I've searched for some related articles and discussions, but due to the console error showing only a one-liner error message without specifying which component is causing the issue, I can't pinpoint the exact reason for the error.
[Vue][SSR] Suppress hydration mismatch warning
When run pnpm dev
("dev": "ts-node-esm server-dev.ts"), an error occurred
The console error is
entry-client.ts:19 [Vue warn]: Hydration node mismatch:
- Client vnode: Symbol(v-fgt)
- Server rendered DOM:
at warn2 @ runtime-core.esm-bundler.js:41 handleMismatch @ runtime-core.esm-bundler.js:4869 onMismatch @ runtime-core.esm-bundler.js:4538 hydrateNode @ runtime-core.esm-bundler.js:4615 hydrateSubTree @ runtime-core.esm-bundler.js:5723 componentUpdateFn @ runtime-core.esm-bundler.js:5743 run @ reactivity.esm-bundler.js:178 instance.update @ runtime-core.esm-bundler.js:5862 setupRenderEffect @ runtime-core.esm-bundler.js:5870 mountComponent @ runtime-core.esm-bundler.js:5660 hydrateNode @ runtime-core.esm-bundler.js:4651 hydrate2 @ runtime-core.esm-bundler.js:4529 mount @ runtime-core.esm-bundler.js:3830 app.mount @ runtime-dom.esm-bundler.js:1468 (anonymous) @ entry-client.ts:19 Promise.then (async) (anonymous) @ entry-client.ts:18
entry-client.ts:19 Hydration completed but contains mismatches.
It seems that SSR didn't take effect for the rendered HTML console error
The project I referenced is koa2-ssr-vite-vue3-ts-pinia. From this project, it can be seen that <!--ssr-outlet-->
is correctly replaced with the rendered HTML. However, in my project, <!--ssr-outlet-->
remains unchanged and is not replaced.
Here are some other related SSR projects where you can see the rendered pages in the browser preview, but my page is blank:
I use Vue 3's Teleport in the code, which seems to cause hydration mismatches
<template>
<Teleport to="body" :disabled="showAlert">
<Transition name="alert">
<div v-if="showAlert" class="mask">
...
</div>
</Transition>
</Teleport>
</template>
I also use a few native DOM operations
and the browser's fetch API
to fetch backend data:
// Set the theme, there are only two modes
// , light and dark, with light represented as ''
setKUNGalgameTheme(theme: '' | 'dark') {
this.showKUNGalgameMode = theme
document.documentElement.className = theme
},
// Fetch request function
const kunFetchRequest = async <T>(
url: string,
options: FetchOptions
): Promise<T> => {
const baseUrl = import.meta.env.VITE_API_BASE_URL
const fullUrl = `${baseUrl}${url}`
// Add the token to the request headers
const headers = {
...options.headers,
Authorization: `Bearer ${useKUNGalgameUserStore().getToken()}`,
}
const response = await fetch(fullUrl, { ...options, headers })
// If not 20X, then throw an error
if (!successResponseArray.includes(response.status)) {
// Handle errors, such as token expiration
await onRequestError(response)
throw new Error('KUNGalgame Fetch Error occurred, but no problem')
}
const data: T = await response.json()
return data
}