fix(nuxt): use useId for client-fallback component uid (#30314)

This commit is contained in:
Julien Huang 2024-12-20 11:13:46 +01:00 committed by Daniel Roe
parent f5df827a90
commit 483435ba34
No known key found for this signature in database
GPG Key ID: 3714AB03996F442B
4 changed files with 6 additions and 75 deletions

View File

@ -1,13 +1,10 @@
import { createElementBlock, defineComponent, onMounted, ref } from 'vue'
import { createElementBlock, defineComponent, onMounted, ref, useId } from 'vue'
import { useState } from '../composables/state'
export default defineComponent({
name: 'NuxtClientFallback',
inheritAttrs: false,
props: {
uid: {
type: String,
},
fallbackTag: {
type: String,
default: () => 'div',
@ -31,7 +28,7 @@ export default defineComponent({
setup (props, ctx) {
const mounted = ref(false)
// This is deliberate - `uid` should not be provided by user but by a transform plugin and will not be reactive.
const ssrFailed = useState(`${props.uid}`)
const ssrFailed = useState(useId())
if (ssrFailed.value) {
onMounted(() => { mounted.value = true })

View File

@ -1,18 +1,14 @@
import { defineComponent, getCurrentInstance, onErrorCaptured, ref } from 'vue'
import { defineComponent, getCurrentInstance, onErrorCaptured, ref, useId } from 'vue'
import { ssrRenderAttrs, ssrRenderSlot, ssrRenderVNode } from 'vue/server-renderer'
import { isPromise } from '@vue/shared'
import { useState } from '../composables/state'
import { useNuxtApp } from '../nuxt'
import { createBuffer } from './utils'
const NuxtClientFallbackServer = defineComponent({
name: 'NuxtClientFallback',
inheritAttrs: false,
props: {
uid: {
type: String,
},
fallbackTag: {
type: String,
default: () => 'div',
@ -37,11 +33,10 @@ const NuxtClientFallbackServer = defineComponent({
return true
},
},
async setup (props, ctx) {
async setup (_, ctx) {
const vm = getCurrentInstance()
const ssrFailed = ref(false)
const nuxtApp = useNuxtApp()
const error = useState<boolean | undefined>(`${props.uid}`)
const error = useState<boolean | undefined>(useId())
onErrorCaptured((err) => {
error.value = true
@ -68,7 +63,7 @@ const NuxtClientFallbackServer = defineComponent({
return { ssrFailed, ssrVNodes }
} catch (ssrError) {
// catch in dev
nuxtApp.runWithContext(() => useState(`${props.uid}`, () => true))
error.value = true
ctx.emit('ssr-error', ssrError)
return { ssrFailed: true, ssrVNodes: [] }
}

View File

@ -7,7 +7,6 @@ import { distDir } from '../dirs'
import { componentNamesTemplate, componentsIslandsTemplate, componentsMetadataTemplate, componentsPluginTemplate, componentsTypeTemplate } from './templates'
import { scanComponents } from './scan'
import { ClientFallbackAutoIdPlugin } from './plugins/client-fallback-auto-id'
import { LoaderPlugin } from './plugins/loader'
import { ComponentsChunkPlugin, IslandsTransformPlugin } from './plugins/islands-transform'
import { TransformPlugin } from './plugins/transform'
@ -220,11 +219,6 @@ export default defineNuxtModule<ComponentsOptions>({
addBuildPlugin(TreeShakeTemplatePlugin({ sourcemap: !!nuxt.options.sourcemap.server, getComponents }), { client: false })
}
if (nuxt.options.experimental.clientFallback) {
addBuildPlugin(ClientFallbackAutoIdPlugin({ sourcemap: !!nuxt.options.sourcemap.client, rootDir: nuxt.options.rootDir }), { server: false })
addBuildPlugin(ClientFallbackAutoIdPlugin({ sourcemap: !!nuxt.options.sourcemap.server, rootDir: nuxt.options.rootDir }), { client: false })
}
const sharedLoaderOptions = {
getComponents,
serverComponentRuntime,

View File

@ -1,55 +0,0 @@
import { createUnplugin } from 'unplugin'
import type { ComponentsOptions } from '@nuxt/schema'
import MagicString from 'magic-string'
import { isAbsolute, relative } from 'pathe'
import { hash } from 'ohash'
import { isVue } from '../../core/utils'
interface LoaderOptions {
sourcemap?: boolean
transform?: ComponentsOptions['transform']
rootDir: string
}
const CLIENT_FALLBACK_RE = /<(?:NuxtClientFallback|nuxt-client-fallback)(?: [^>]*)?>/
const CLIENT_FALLBACK_GLOBAL_RE = /<(NuxtClientFallback|nuxt-client-fallback)( [^>]*)?>/g
const UID_RE = / :?uid=/
export const ClientFallbackAutoIdPlugin = (options: LoaderOptions) => createUnplugin(() => {
const exclude = options.transform?.exclude || []
const include = options.transform?.include || []
return {
name: 'nuxt:client-fallback-auto-id',
enforce: 'pre',
transformInclude (id) {
if (exclude.some(pattern => pattern.test(id))) {
return false
}
if (include.some(pattern => pattern.test(id))) {
return true
}
return isVue(id)
},
transform (code, id) {
if (!CLIENT_FALLBACK_RE.test(code)) { return }
const s = new MagicString(code)
const relativeID = isAbsolute(id) ? relative(options.rootDir, id) : id
let count = 0
s.replace(CLIENT_FALLBACK_GLOBAL_RE, (full, name, attrs) => {
count++
if (UID_RE.test(attrs)) { return full }
return `<${name} :uid="'${hash(relativeID)}' + JSON.stringify($props) + '${count}'" ${attrs ?? ''}>`
})
if (s.hasChanged()) {
return {
code: s.toString(),
map: options.sourcemap
? s.generateMap({ hires: true })
: undefined,
}
}
},
}
})