-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DOM shuffle after SSR hydration #9185
Comments
I am extremely inexperienced with Vue build pipelines and so forth, however so far I've been able to build the diff --git a/scripts/dev.js b/scripts/dev.js
index 8342f523..dae98834 100644
--- a/scripts/dev.js
+++ b/scripts/dev.js
@@ -15,7 +15,7 @@ const require = createRequire(import.meta.url)
const __dirname = dirname(fileURLToPath(import.meta.url))
const args = minimist(process.argv.slice(2))
const target = args._[0] || 'vue'
-const format = args.f || 'global'
+const format = args.f || 'esm-browser'
const inlineDeps = args.i || args.inline
const pkg = require(`../packages/${target}/package.json`)
@@ -109,7 +109,7 @@ esbuild
define: {
__COMMIT__: `"dev"`,
__VERSION__: `"${pkg.version}"`,
- __DEV__: `true`,
+ __DEV__: `false`,
__TEST__: `false`,
__BROWSER__: String(
format !== 'cjs' && !pkg.buildOptions?.enableNonBrowserBranches Turns out if I force |
So I've done a bisection to figure which flags are causing the issue, it looks like when those two are set together it will cause the bug to happen. diff --git a/packages/compiler-core/src/parse.ts b/packages/compiler-core/src/parse.ts
index b72ad028..4d1c5316 100644
--- a/packages/compiler-core/src/parse.ts
+++ b/packages/compiler-core/src/parse.ts
@@ -77,7 +77,7 @@ export const defaultParserOptions: MergedParserOptions = {
rawText.replace(decodeRE, (_, p1) => decodeMap[p1]),
onError: defaultOnError,
onWarn: defaultOnWarn,
- comments: __DEV__
+ comments: false
}
export const enum TextModes {
diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts
index 89a00886..4926a3fb 100644
--- a/packages/runtime-core/src/hydration.ts
+++ b/packages/runtime-core/src/hydration.ts
@@ -315,7 +315,7 @@ export function createHydrationFunctions(
const forcePatchValue = (type === 'input' && dirs) || type === 'option'
// skip props & children if this is hoisted static nodes
// #5405 in dev, always hydrate children for HMR
- if (__DEV__ || forcePatchValue || patchFlag !== PatchFlags.HOISTED) {
+ if (false || forcePatchValue || patchFlag !== PatchFlags.HOISTED) {
if (dirs) {
invokeDirectiveHook(vnode, null, parentComponent, 'created')
} Not sure about the role of comments here, but since the faulty line is already mentioned in #5405 I'm gonna guess that this is a strong hint. Beyond that I'm not familiar enough with the Vue internals to interpret this correctly. |
Just to be clear on the above comment, in order to produce the bug in dev mode you need to apply the patch that forces |
Thanks for having a look. In terms of keeping the comments, this is really not the issue here: they are not needed nor wanted, merely an artifact in my app (which is obviously much larger than this example). However it seems to me than randomly shuffling DOM elements is not an expected behavior, especially without any explicit warning. If I might give my input on possible solutions:
Tell me what you think |
This is because your client and server use different versions of
<script type="importmap">
{
"imports": {
"vue": "/node_modules/vue/dist/vue.esm-browser.prod.js" // should use vue.esm-browser.js if in dev
}
} |
Could be, however this bug manifested in Nuxt initially, all I did was reproduce the use case. Should I bring the issue to them then? |
Just to be clear, what should I do different in my published example? Let's say that the documentation is far from being exhaustive on that topic. |
please provide a runnable reproduction with nuxt, let's see further. |
Sure, here it is: https://github.com/Xowap/nuxt-hydration-bug |
Indeed, after digging into the package source code, I understand that the import varies depending on whether However this is a highly surprising behavior (and another breaking change from Vue 2), I get the feeling that there should at least be some kind of warning somewhere? |
Closing this issue as it has been identified not to be a bug based on the discussion. Thank you for your contribution! |
Vue version
3.3.4
Link to minimal reproduction
https://github.com/Xowap/vue-hydration-bug
https://stackblitz.com/edit/stackblitz-starters-lgtp6t?file=app.js
Steps to reproduce
The example is straight out of the Vue SSR doc, just with a different template. Just run
example.js
and visitlocalhost:3000
.What is expected?
It should display blocks in "AAA"/"BBB"/"CCC"/"AAA"/"BBB"/"CCC" order.
What is actually happening?
The SSR renders the HTML correctly but as soon as hydration kicks the order is kind of randomized, usually "AAA"/"BBB"/"CCC"/"CCC"/"AAA"/"BBB" on my machine.
System Info
Any additional comments?
This bug popped in a complex Nuxt app, I've been able to dumb it down to this example which outlines its Vue origin. Presumably it affects all Vue 3 versions, at least those that I have tested (3.1 to 3.3 if I'm not mistaken).
To be noted as well that if you drop the
.prod
from the import map, the bug goes away, at least with this example (not sure if in the absolute).The text was updated successfully, but these errors were encountered: