chore: rebase to vue 3.5 branch

rebases to #28285
This commit is contained in:
tbitw2549 2024-08-16 17:52:26 +03:00
parent 3426fca610
commit f3f594f7f9
6 changed files with 18 additions and 100 deletions

View File

@ -1,60 +1,3 @@
import { getCurrentInstance, inject } from 'vue'
import { useNuxtApp } from '../nuxt'
import { clientOnlySymbol } from '#app/components/client-only'
import { useId as _useId } from 'vue'
const ATTR_KEY = 'data-n-ids'
const SEPARATOR = '-'
/**
* Generate an SSR-friendly unique identifier that can be passed to accessibility attributes.
*
* The generated ID is unique in the context of the current Nuxt instance and key.
*/
export function useId (): string
export function useId (key?: string): string {
if (typeof key !== 'string') {
throw new TypeError('[nuxt] [useId] key must be a string.')
}
// TODO: implement in composable-keys
// Make sure key starts with a letter to be a valid selector
key = `n${key.slice(1)}`
const nuxtApp = useNuxtApp()
const instance = getCurrentInstance()
if (!instance) {
// TODO: support auto-incrementing ID for plugins if there is need?
throw new TypeError('[nuxt] `useId` must be called within a component setup function.')
}
nuxtApp._genId ||= 0
instance._nuxtIdIndex ||= {}
instance._nuxtIdIndex[key] ||= 0
const instanceIndex = key + SEPARATOR + instance._nuxtIdIndex[key]++
if (import.meta.server) {
const ids = JSON.parse(instance.attrs[ATTR_KEY] as string | undefined || '{}')
ids[instanceIndex] = key + SEPARATOR + nuxtApp._genId++
instance.attrs[ATTR_KEY] = JSON.stringify(ids)
return ids[instanceIndex]
}
if (nuxtApp.payload.serverRendered && nuxtApp.isHydrating && !inject(clientOnlySymbol, false)) {
// Access data attribute from sibling if root is a comment node and sibling is an element
const el = instance.vnode.el?.nodeType === 8 && instance.vnode.el?.nextElementSibling?.getAttribute
? instance.vnode.el?.nextElementSibling
: instance.vnode.el
const ids = JSON.parse(el?.getAttribute?.(ATTR_KEY) || '{}')
if (ids[instanceIndex]) {
return ids[instanceIndex]
}
if (import.meta.dev && instance.vnode.type && typeof instance.vnode.type === 'object' && 'inheritAttrs' in instance.vnode.type && instance.vnode.type.inheritAttrs === false) {
console.warn('[nuxt] `useId` might not work correctly with components that have `inheritAttrs: false`.')
}
}
// pure client-side ids, avoiding potential collision with server-side ids
return key + '_' + nuxtApp._genId++
}
export const useId = _useId

View File

@ -105,10 +105,6 @@ const granularAppPresets: InlinePreset[] = [
imports: ['usePreviewMode'],
from: '#app/composables/preview',
},
{
imports: ['useId'],
from: '#app/composables/id',
},
{
imports: ['useRouteAnnouncer'],
from: '#app/composables/route-announcer',
@ -231,6 +227,14 @@ const vuePreset = defineUnimportPreset({
'useCssVars',
'useSlots',
'useTransitionState',
'useId',
'useTemplateRef',
'hydrateOnInteraction',
'hydrateOnMediaQuery',
'hydrateOnVisible',
'hydrateOnIdle',
'useHost',
'useShadowRoot',
],
})

View File

@ -56,7 +56,7 @@ describe('imports:transform', () => {
})
})
const excludedNuxtHelpers = ['useHydration', 'useHead', 'useSeoMeta', 'useServerSeoMeta']
const excludedNuxtHelpers = ['useHydration', 'useHead', 'useSeoMeta', 'useServerSeoMeta', 'useId']
describe('imports:nuxt', () => {
try {

View File

@ -127,10 +127,10 @@ describe('treeshake client only in ssr', () => {
const ssrResult = await SFCCompile(`SomeComponent${state.index}.vue`, WithClientOnly, state.options, true)
const treeshaken = await treeshake(ssrResult)
const [_, scopeId] = clientResult.match(/_pushScopeId\("(.*)"\)/)!
const [_, scopeId] = clientResult.match(/['"]__scopeId['"],\s*['"](data-v-[^'"]+)['"]/)!
// ensure the id is correctly passed between server and client
expect(clientResult).toContain(`pushScopeId("${scopeId}")`)
expect(clientResult).toContain(`'__scopeId',"${scopeId}"`)
expect(treeshaken).toContain(`<div ${scopeId}>`)
expect(clientResult).toContain('should-be-treeshaken')

View File

@ -19,7 +19,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
for (const outputDir of ['.output', '.output-inline']) {
it('default client bundle size', async () => {
const clientStats = await analyzeSizes('**/*.js', join(rootDir, outputDir, 'public'))
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot(`"107k"`)
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot(`"112k"`)
expect(clientStats.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
[
"_nuxt/entry.js",
@ -32,10 +32,10 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
const serverDir = join(rootDir, '.output/server')
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"211k"`)
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"205k"`)
const modules = await analyzeSizes('node_modules/**/*', serverDir)
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"1348k"`)
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"1370k"`)
const packages = modules.files
.filter(m => m.endsWith('package.json'))
@ -74,7 +74,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
const serverDir = join(rootDir, '.output-inline/server')
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"535k"`)
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"549k"`)
const modules = await analyzeSizes('node_modules/**/*', serverDir)
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"80.3k"`)

View File

@ -4,7 +4,6 @@ import { describe, expect, it, vi } from 'vitest'
import { defineEventHandler } from 'h3'
import { destr } from 'destr'
import { mount } from '@vue/test-utils'
import { mountSuspended, registerEndpoint } from '@nuxt/test-utils/runtime'
import { hasProtocol } from 'ufo'
@ -17,7 +16,6 @@ import { setResponseStatus, useRequestEvent, useRequestFetch, useRequestHeaders
import { clearNuxtState, useState } from '#app/composables/state'
import { useRequestURL } from '#app/composables/url'
import { getAppManifest, getRouteRules } from '#app/composables/manifest'
import { useId } from '#app/composables/id'
import { callOnce } from '#app/composables/once'
import { useLoadingIndicator } from '#app/composables/loading-indicator'
import { useRouteAnnouncer } from '#app/composables/route-announcer'
@ -79,7 +77,6 @@ describe('composables', () => {
'clearNuxtState',
'useState',
'useRequestURL',
'useId',
'useRoute',
'navigateTo',
'abortNavigation',
@ -101,6 +98,7 @@ describe('composables', () => {
'reloadNuxtApp',
'refreshCookie',
'onPrehydrate',
'useId',
'useFetch',
'useHead',
'useLazyFetch',
@ -459,33 +457,6 @@ describe('clearNuxtState', () => {
})
})
describe('useId', () => {
it('default', () => {
const vals = new Set<string>()
for (let index = 0; index < 100; index++) {
mount(defineComponent({
setup () {
const id = useId()
vals.add(id)
return () => h('div', id)
},
}))
}
expect(vals.size).toBe(100)
})
it('generates unique ids per-component', () => {
const component = defineComponent({
setup () {
const id = useId()
return () => h('div', id)
},
})
expect(mount(component).html()).not.toBe(mount(component).html())
})
})
describe('url', () => {
it('useRequestURL', () => {
const url = useRequestURL()