From 39482e483c4ead62062474e21467a9018a0951f0 Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Sun, 5 Nov 2023 14:06:54 +0530 Subject: [PATCH] feat: add `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__` flag --- packages/global.d.ts | 1 + packages/runtime-core/src/featureFlags.ts | 5 +++++ packages/runtime-core/src/hydration.ts | 20 +++++++++++++------- packages/vue/README.md | 1 + rollup.config.js | 3 +++ scripts/dev.js | 3 ++- scripts/usage-size.ts | 1 + vitest.config.ts | 1 + 8 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/global.d.ts b/packages/global.d.ts index 97405129be9..d2c17395020 100644 --- a/packages/global.d.ts +++ b/packages/global.d.ts @@ -17,6 +17,7 @@ declare var __COMPAT__: boolean declare var __FEATURE_OPTIONS_API__: boolean declare var __FEATURE_PROD_DEVTOOLS__: boolean declare var __FEATURE_SUSPENSE__: boolean +declare var __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: boolean // for tests declare namespace jest { diff --git a/packages/runtime-core/src/featureFlags.ts b/packages/runtime-core/src/featureFlags.ts index e878407bcc8..267e69eef5c 100644 --- a/packages/runtime-core/src/featureFlags.ts +++ b/packages/runtime-core/src/featureFlags.ts @@ -20,6 +20,11 @@ export function initFeatureFlags() { getGlobalThis().__VUE_PROD_DEVTOOLS__ = false } + if (typeof __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__ !== 'boolean') { + __DEV__ && needWarn.push(`__VUE_PROD_HYDRATION_MISMATCH_DETAILS__`) + getGlobalThis().__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = false + } + if (__DEV__ && needWarn.length) { const multi = needWarn.length > 1 console.warn( diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts index 4e91cb3d1cb..2abcd864503 100644 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@ -68,7 +68,7 @@ export function createHydrationFunctions( const hydrate: RootHydrateFunction = (vnode, container) => { if (!container.hasChildNodes()) { - __DEV__ && + ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) && warn( `Attempting to hydrate existing markup but container is empty. ` + `Performing full mount instead.` @@ -131,7 +131,7 @@ export function createHydrationFunctions( } else { if ((node as Text).data !== vnode.children) { hasMismatch = true - __DEV__ && + ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) && warn( `Hydration text mismatch:` + `\n- Server rendered: ${JSON.stringify( @@ -298,7 +298,7 @@ export function createHydrationFunctions( rendererInternals, hydrateNode ) - } else if (__DEV__) { + } else if (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) { warn('Invalid HostVNode type:', type, `(${typeof type})`) } } @@ -426,7 +426,10 @@ export function createHydrationFunctions( let hasWarned = false while (next) { hasMismatch = true - if (__DEV__ && !hasWarned) { + if ( + (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) && + !hasWarned + ) { warn( `Hydration children mismatch in <${vnode.type as string}>: ` + `server rendered element contains more child nodes than client vdom.` @@ -441,7 +444,7 @@ export function createHydrationFunctions( } else if (shapeFlag & ShapeFlags.TEXT_CHILDREN) { if (el.textContent !== vnode.children) { hasMismatch = true - __DEV__ && + ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) && warn( `Hydration text content mismatch in <${ vnode.type as string @@ -486,7 +489,10 @@ export function createHydrationFunctions( continue } else { hasMismatch = true - if (__DEV__ && !hasWarned) { + if ( + (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) && + !hasWarned + ) { warn( `Hydration children mismatch in <${container.tagName.toLowerCase()}>: ` + `server rendered element contains fewer child nodes than client vdom.` @@ -555,7 +561,7 @@ export function createHydrationFunctions( isFragment: boolean ): Node | null => { hasMismatch = true - __DEV__ && + ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) && warn( `Hydration node mismatch:\n- Client vnode:`, vnode.type, diff --git a/packages/vue/README.md b/packages/vue/README.md index a98bd997487..c41162cc1c6 100644 --- a/packages/vue/README.md +++ b/packages/vue/README.md @@ -37,6 +37,7 @@ Starting with 3.0.0-rc.3, `esm-bundler` builds now exposes global feature flags - `__VUE_OPTIONS_API__` (enable/disable Options API support, default: `true`) - `__VUE_PROD_DEVTOOLS__` (enable/disable devtools support in production, default: `false`) +- `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__` (enable/disable detailed warnings for hydration mismatches in production, default: `false`) The build will work without configuring these flags, however it is **strongly recommended** to properly configure them in order to get proper tree-shaking in the final bundle. To configure these flags: diff --git a/rollup.config.js b/rollup.config.js index d8dfc98a391..82bee690f88 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -157,6 +157,9 @@ function createConfig(format, output, plugins = []) { : `true`, __FEATURE_PROD_DEVTOOLS__: isBundlerESMBuild ? `__VUE_PROD_DEVTOOLS__` + : `false`, + __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: isBundlerESMBuild + ? `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__` : `false` } diff --git a/scripts/dev.js b/scripts/dev.js index 8342f5237b7..273cf4f435b 100644 --- a/scripts/dev.js +++ b/scripts/dev.js @@ -122,7 +122,8 @@ esbuild __COMPAT__: String(target === 'vue-compat'), __FEATURE_SUSPENSE__: `true`, __FEATURE_OPTIONS_API__: `true`, - __FEATURE_PROD_DEVTOOLS__: `false` + __FEATURE_PROD_DEVTOOLS__: `false`, + __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: `false` } }) .then(ctx => ctx.watch()) diff --git a/scripts/usage-size.ts b/scripts/usage-size.ts index 1a1013b7847..31ee85daebb 100644 --- a/scripts/usage-size.ts +++ b/scripts/usage-size.ts @@ -71,6 +71,7 @@ async function generateBundle(preset: Preset) { replace({ 'process.env.NODE_ENV': '"production"', __VUE_PROD_DEVTOOLS__: 'false', + __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false', __VUE_OPTIONS_API__: 'true', preventAssignment: true }) diff --git a/vitest.config.ts b/vitest.config.ts index e5d5f59345f..ced861a0373 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -15,6 +15,7 @@ export default defineConfig({ __FEATURE_OPTIONS_API__: true, __FEATURE_SUSPENSE__: true, __FEATURE_PROD_DEVTOOLS__: false, + __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: false, __COMPAT__: true }, resolve: {