Merge remote-tracking branch 'origin/main' into fix/watch-build-dir

This commit is contained in:
Daniel Roe 2023-10-31 14:08:29 +01:00
commit 560a8a9168
53 changed files with 287 additions and 259 deletions

View File

@ -70,6 +70,11 @@
"target": "packages/nuxt/src/app", "target": "packages/nuxt/src/app",
"message": "app should not directly import from modules." "message": "app should not directly import from modules."
}, },
{
"from": "packages/nuxt/src/app/**/index.ts",
"target": "packages/nuxt/src",
"message": "should not import from barrel/index files"
},
{ {
"from": "packages/nitro", "from": "packages/nitro",
"target": "packages/!(nitro)/**/*", "target": "packages/!(nitro)/**/*",

View File

@ -66,7 +66,7 @@ export default defineNuxtPlugin({
// You can directly register Nuxt app runtime hooks here // You can directly register Nuxt app runtime hooks here
'app:created'() { 'app:created'() {
const nuxtApp = useNuxtApp() const nuxtApp = useNuxtApp()
// // do something in the hook
} }
}, },
env: { env: {

View File

@ -112,7 +112,7 @@ export default defineNuxtModule({
```ts [plugin.ts] ```ts [plugin.ts]
import { createHead as createClientHead, createServerHead } from '@unhead/vue' import { createHead as createClientHead, createServerHead } from '@unhead/vue'
import { defineNuxtPlugin } from '#app' import { defineNuxtPlugin } from '#imports'
// @ts-ignore // @ts-ignore
import metaConfig from '#build/meta.config.mjs' import metaConfig from '#build/meta.config.mjs'

View File

@ -234,7 +234,7 @@ export default defineNuxtModule({
```ts [runtime/plugin.ejs] ```ts [runtime/plugin.ejs]
import { VueFire, useSSRInitialState } from 'vuefire' import { VueFire, useSSRInitialState } from 'vuefire'
import { defineNuxtPlugin } from '#app' import { defineNuxtPlugin } from '#imports'
export default defineNuxtPlugin((nuxtApp) => { export default defineNuxtPlugin((nuxtApp) => {
const firebaseApp = nuxtApp.$firebaseApp const firebaseApp = nuxtApp.$firebaseApp

View File

@ -79,7 +79,7 @@
"vue-router": "4.2.5", "vue-router": "4.2.5",
"vue-tsc": "1.8.22" "vue-tsc": "1.8.22"
}, },
"packageManager": "pnpm@8.10.0", "packageManager": "pnpm@8.9.2",
"engines": { "engines": {
"node": "^14.18.0 || >=16.10.0" "node": "^14.18.0 || >=16.10.0"
} }

View File

@ -1,9 +1,10 @@
import type { defineAsyncComponent } from 'vue' import type { defineAsyncComponent } from 'vue'
import { createVNode, defineComponent } from 'vue' import { createVNode, defineComponent } from 'vue'
import { createError } from '../composables/error'
// @ts-expect-error virtual file // @ts-expect-error virtual file
import * as islandComponents from '#build/components.islands.mjs' import * as islandComponents from '#build/components.islands.mjs'
import { createError } from '#app/composables/error'
export default defineComponent({ export default defineComponent({
props: { props: {

View File

@ -1,5 +1,5 @@
import { defineComponent, onErrorCaptured, ref } from 'vue' import { defineComponent, onErrorCaptured, ref } from 'vue'
import { useNuxtApp } from '#app/nuxt' import { useNuxtApp } from '../nuxt'
export default defineComponent({ export default defineComponent({
emits: { emits: {

View File

@ -9,9 +9,9 @@ import type { FetchResponse } from 'ofetch'
// eslint-disable-next-line import/no-restricted-paths // eslint-disable-next-line import/no-restricted-paths
import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer' import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer'
import { useNuxtApp, useRuntimeConfig } from '../nuxt'
import { prerenderRoutes, useRequestEvent } from '../composables/ssr'
import { getFragmentHTML, getSlotProps } from './utils' import { getFragmentHTML, getSlotProps } from './utils'
import { useNuxtApp, useRuntimeConfig } from '#app/nuxt'
import { prerenderRoutes, useRequestEvent } from '#app/composables/ssr'
// @ts-expect-error virtual file // @ts-expect-error virtual file
import { remoteComponentIslands } from '#build/nuxt.config.mjs' import { remoteComponentIslands } from '#build/nuxt.config.mjs'

View File

@ -1,12 +1,15 @@
import type { DefineComponent, MaybeRef, VNode } from 'vue' import type { DefineComponent, MaybeRef, VNode } from 'vue'
import { Suspense, Transition, computed, defineComponent, h, inject, mergeProps, nextTick, onMounted, provide, ref, unref } from 'vue' import { Suspense, Transition, computed, defineComponent, h, inject, mergeProps, nextTick, onMounted, provide, ref, unref } from 'vue'
import type { RouteLocationNormalizedLoaded } from 'vue-router' import type { RouteLocationNormalizedLoaded } from 'vue-router'
// eslint-disable-next-line import/no-restricted-paths
import type { PageMeta } from '../../pages/runtime/composables'
import { useRoute } from '../composables/router'
import { useNuxtApp } from '../nuxt'
import { _wrapIf } from './utils' import { _wrapIf } from './utils'
import { LayoutMetaSymbol, PageRouteSymbol } from './injections' import { LayoutMetaSymbol, PageRouteSymbol } from './injections'
import type { PageMeta } from '#app'
import { useRoute } from '#app/composables/router'
import { useNuxtApp } from '#app/nuxt'
// @ts-expect-error virtual file // @ts-expect-error virtual file
import { useRoute as useVueRouterRoute } from '#build/pages' import { useRoute as useVueRouterRoute } from '#build/pages'
// @ts-expect-error virtual file // @ts-expect-error virtual file

View File

@ -1,7 +1,7 @@
import { computed, defineComponent, h, onBeforeUnmount, ref } from 'vue' import { computed, defineComponent, h, onBeforeUnmount, ref } from 'vue'
import { useNuxtApp } from '../nuxt'
import { useRouter } from '../composables/router'
import { isChangingPage } from './utils' import { isChangingPage } from './utils'
import { useNuxtApp } from '#app/nuxt'
import { useRouter } from '#app/composables/router'
// @ts-expect-error virtual file // @ts-expect-error virtual file
import { globalMiddleware } from '#build/middleware' import { globalMiddleware } from '#build/middleware'

View File

@ -9,10 +9,10 @@
<script setup> <script setup>
import { defineAsyncComponent, onErrorCaptured, onServerPrefetch, provide } from 'vue' import { defineAsyncComponent, onErrorCaptured, onServerPrefetch, provide } from 'vue'
import { useNuxtApp } from '#app/nuxt' import { useNuxtApp } from '../nuxt'
import { isNuxtError, showError, useError } from '#app/composables/error' import { isNuxtError, showError, useError } from '../composables/error'
import { useRoute } from '#app/composables/router' import { useRoute } from '../composables/router'
import { PageRouteSymbol } from '#app/components/injections' import { PageRouteSymbol } from '../components/injections'
import AppComponent from '#build/app-component.mjs' import AppComponent from '#build/app-component.mjs'
import ErrorComponent from '#build/error-component.mjs' import ErrorComponent from '#build/error-component.mjs'
@ -24,7 +24,7 @@ const nuxtApp = useNuxtApp()
const onResolve = nuxtApp.deferHydration() const onResolve = nuxtApp.deferHydration()
const url = import.meta.server ? nuxtApp.ssrContext.url : window.location.pathname const url = import.meta.server ? nuxtApp.ssrContext.url : window.location.pathname
const SingleRenderer = import.meta.test && import.meta.dev && import.meta.server && url.startsWith('/__nuxt_component_test__/') && /* #__PURE__ */ defineAsyncComponent(() => import('#build/test-component-wrapper.mjs') const SingleRenderer = import.meta.test && import.meta.dev && import.meta.server && url.startsWith('/__nuxt_component_test__/') && defineAsyncComponent(() => import('#build/test-component-wrapper.mjs')
.then(r => r.default(import.meta.server ? url : window.location.href))) .then(r => r.default(import.meta.server ? url : window.location.href)))
// Inject default route (outside of pages) as active route // Inject default route (outside of pages) as active route

View File

@ -1,7 +1,7 @@
import { defineComponent, h, nextTick, onMounted, provide, shallowReactive } from 'vue' import { defineComponent, h, nextTick, onMounted, provide, shallowReactive } from 'vue'
import type { Ref, VNode } from 'vue' import type { Ref, VNode } from 'vue'
import type { RouteLocation, RouteLocationNormalizedLoaded } from '#vue-router' import type { RouteLocation, RouteLocationNormalizedLoaded } from '#vue-router'
import { PageRouteSymbol } from '#app/components/injections' import { PageRouteSymbol } from './injections'
export const RouteProvider = defineComponent({ export const RouteProvider = defineComponent({
name: 'RouteProvider', name: 'RouteProvider',

View File

@ -1,5 +1,5 @@
import destr from 'destr' import destr from 'destr'
import { useNuxtApp } from '#app/nuxt' import { useNuxtApp } from '../nuxt'
export interface ReloadNuxtAppOptions { export interface ReloadNuxtAppOptions {
/** /**

View File

@ -1,5 +1,5 @@
import { useNuxtApp } from '../nuxt' import { useNuxtApp } from '../nuxt'
import type { NuxtPayload } from '#app' import type { NuxtPayload } from '../nuxt'
/** /**
* Allows full control of the hydration cycle to set and receive data from the server. * Allows full control of the hydration cycle to set and receive data from the server.

View File

@ -1,7 +1,7 @@
import type { MatcherExport, RouteMatcher } from 'radix3' import type { MatcherExport, RouteMatcher } from 'radix3'
import { createMatcherFromExport } from 'radix3' import { createMatcherFromExport } from 'radix3'
import { defu } from 'defu' import { defu } from 'defu'
import { useAppConfig } from '#app' import { useAppConfig } from '../config'
// @ts-expect-error virtual file // @ts-expect-error virtual file
import { appManifest as isAppManifestEnabled } from '#build/nuxt.config.mjs' import { appManifest as isAppManifestEnabled } from '#build/nuxt.config.mjs'
// @ts-expect-error virtual file // @ts-expect-error virtual file

View File

@ -4,8 +4,8 @@ import { useHead } from '@unhead/vue'
import { getCurrentInstance } from 'vue' import { getCurrentInstance } from 'vue'
import { useNuxtApp, useRuntimeConfig } from '../nuxt' import { useNuxtApp, useRuntimeConfig } from '../nuxt'
import { getAppManifest, getRouteRules } from '#app/composables/manifest' import { useRoute } from './router'
import { useRoute } from '#app/composables' import { getAppManifest, getRouteRules } from './manifest'
// @ts-expect-error virtual import // @ts-expect-error virtual import
import { appManifest, payloadExtraction, renderJsonPayloads } from '#build/nuxt.config.mjs' import { appManifest, payloadExtraction, renderJsonPayloads } from '#build/nuxt.config.mjs'
@ -23,7 +23,7 @@ export function loadPayload (url: string, opts: LoadPayloadOptions = {}): Record
if (payloadURL in cache) { if (payloadURL in cache) {
return cache[payloadURL] return cache[payloadURL]
} }
cache[payloadURL] = isPrerendered().then((prerendered) => { cache[payloadURL] = isPrerendered(url).then((prerendered) => {
if (!prerendered) { if (!prerendered) {
cache[payloadURL] = null cache[payloadURL] = null
return null return null
@ -78,11 +78,7 @@ async function _importPayload (payloadURL: string) {
export async function isPrerendered (url = useRoute().path) { export async function isPrerendered (url = useRoute().path) {
// Note: Alternative for server is checking x-nitro-prerender header // Note: Alternative for server is checking x-nitro-prerender header
const nuxtApp = useNuxtApp() if (!appManifest) { return !!useNuxtApp().payload.prerenderedAt }
if (nuxtApp.payload.prerenderedAt) {
return true
}
if (!appManifest) { return false }
const manifest = await getAppManifest() const manifest = await getAppManifest()
if (manifest.prerendered.includes(url)) { if (manifest.prerendered.includes(url)) {
return true return true

View File

@ -4,13 +4,14 @@ import type { NavigationFailure, NavigationGuard, RouteLocationNormalized, Route
import { sanitizeStatusCode } from 'h3' import { sanitizeStatusCode } from 'h3'
import { hasProtocol, isScriptProtocol, joinURL, parseURL, withQuery } from 'ufo' import { hasProtocol, isScriptProtocol, joinURL, parseURL, withQuery } from 'ufo'
// eslint-disable-next-line import/no-restricted-paths
import type { PageMeta } from '../../pages/runtime/composables'
import { useNuxtApp, useRuntimeConfig } from '../nuxt' import { useNuxtApp, useRuntimeConfig } from '../nuxt'
import { PageRouteSymbol } from '../components/injections'
import type { NuxtError } from './error' import type { NuxtError } from './error'
import { createError, showError } from './error' import { createError, showError } from './error'
import type { PageMeta } from '#app'
import { PageRouteSymbol } from '#app/components/injections'
export const useRouter: typeof _useRouter = () => { export const useRouter: typeof _useRouter = () => {
return useNuxtApp()?.$router as Router return useNuxtApp()?.$router as Router
} }

View File

@ -1,7 +1,7 @@
import { getRequestURL } from 'h3' import { getRequestURL } from 'h3'
import { joinURL } from 'ufo' import { joinURL } from 'ufo'
import { useRuntimeConfig } from '../nuxt'
import { useRequestEvent } from './ssr' import { useRequestEvent } from './ssr'
import { useRuntimeConfig } from '#app'
export function useRequestURL () { export function useRequestURL () {
if (import.meta.server) { if (import.meta.server) {

View File

@ -1,4 +1,4 @@
import type { CreateOptions } from '#app' import type { CreateOptions } from './nuxt'
const entry = import.meta.server const entry = import.meta.server
? (ctx?: CreateOptions['ssrContext']) => import('#app/entry').then(m => m.default(ctx)) ? (ctx?: CreateOptions['ssrContext']) => import('#app/entry').then(m => m.default(ctx))

View File

@ -5,8 +5,8 @@ import { createApp, createSSRApp, nextTick } from 'vue'
import '#build/paths.mjs' import '#build/paths.mjs'
import '#build/fetch.mjs' import '#build/fetch.mjs'
import type { CreateOptions } from '#app' import { applyPlugins, createNuxtApp } from './nuxt'
import { applyPlugins, createNuxtApp } from '#app/nuxt' import type { CreateOptions } from './nuxt'
import '#build/css' import '#build/css'
// @ts-expect-error virtual file // @ts-expect-error virtual file

View File

@ -1,7 +1,9 @@
/// <reference path="types/augments.d.ts" /> /// <reference path="types/augments.d.ts" />
export * from './nuxt' export * from './nuxt'
// eslint-disable-next-line import/no-restricted-paths
export * from './composables/index' export * from './composables/index'
// eslint-disable-next-line import/no-restricted-paths
export * from './components/index' export * from './components/index'
export * from './config' export * from './config'
export * from './compat/idle-callback' export * from './compat/idle-callback'

View File

@ -1,5 +1,5 @@
import { defineNuxtRouteMiddleware } from '#app/composables/router' import { defineNuxtRouteMiddleware } from '../composables/router'
import { getRouteRules } from '#app/composables/manifest' import { getRouteRules } from '../composables/manifest'
export default defineNuxtRouteMiddleware(async (to) => { export default defineNuxtRouteMiddleware(async (to) => {
if (import.meta.server || import.meta.test) { return } if (import.meta.server || import.meta.test) { return }

View File

@ -9,14 +9,14 @@ import type { SSRContext, createRenderer } from 'vue-bundle-renderer/runtime'
import type { H3Event } from 'h3' import type { H3Event } from 'h3'
import type { AppConfig, AppConfigInput, RuntimeConfig } from 'nuxt/schema' import type { AppConfig, AppConfigInput, RuntimeConfig } from 'nuxt/schema'
import type { RenderResponse } from 'nitropack' import type { RenderResponse } from 'nitropack'
import type { MergeHead, VueHeadClient } from '@unhead/vue' import type { MergeHead, VueHeadClient } from '@unhead/vue'
// eslint-disable-next-line import/no-restricted-paths // eslint-disable-next-line import/no-restricted-paths
import type { NuxtIslandContext } from '../core/runtime/nitro/renderer' import type { NuxtIslandContext } from '../core/runtime/nitro/renderer'
import type { RouteMiddleware } from '../../app' import type { RouteMiddleware } from '../app/composables/router'
import type { NuxtError } from '../app/composables/error' import type { NuxtError } from '../app/composables/error'
import type { AsyncDataRequestStatus } from '../app/composables/asyncData' import type { AsyncDataRequestStatus } from '../app/composables/asyncData'
import type { NuxtAppManifestMeta } from '#app/composables' import type { NuxtAppManifestMeta } from '../app/composables/manifest'
const nuxtAppCtx = /* #__PURE__ */ getContext<NuxtApp>('nuxt-app', { const nuxtAppCtx = /* #__PURE__ */ getContext<NuxtApp>('nuxt-app', {
asyncContext: !!process.env.NUXT_ASYNC_CONTEXT && process.server asyncContext: !!process.env.NUXT_ASYNC_CONTEXT && process.server

View File

@ -1,5 +1,7 @@
import type { NuxtAppManifestMeta } from '#app' import { defineNuxtPlugin } from '../nuxt'
import { defineNuxtPlugin, getAppManifest, onNuxtReady } from '#app' import { getAppManifest } from '../composables/manifest'
import type { NuxtAppManifestMeta } from '../composables/manifest'
import { onNuxtReady } from '../composables/ready'
// @ts-expect-error virtual file // @ts-expect-error virtual file
import { buildAssetsURL } from '#build/paths.mjs' import { buildAssetsURL } from '#build/paths.mjs'

View File

@ -1,8 +1,8 @@
import { joinURL } from 'ufo' import { joinURL } from 'ufo'
import type { RouteLocationNormalized } from 'vue-router' import type { RouteLocationNormalized } from 'vue-router'
import { defineNuxtPlugin, useRuntimeConfig } from '#app/nuxt' import { defineNuxtPlugin, useRuntimeConfig } from '../nuxt'
import { useRouter } from '#app/composables/router' import { useRouter } from '../composables/router'
import { reloadNuxtApp } from '#app/composables/chunk' import { reloadNuxtApp } from '../composables/chunk'
export default defineNuxtPlugin({ export default defineNuxtPlugin({
name: 'nuxt:chunk-reload', name: 'nuxt:chunk-reload',

View File

@ -1,7 +1,7 @@
import { ref } from 'vue' import { ref } from 'vue'
import { parseURL } from 'ufo' import { parseURL } from 'ufo'
import { useHead } from '@unhead/vue' import { useHead } from '@unhead/vue'
import { defineNuxtPlugin } from '#app/nuxt' import { defineNuxtPlugin } from '../nuxt'
export default defineNuxtPlugin({ export default defineNuxtPlugin({
name: 'nuxt:cross-origin-prefetch', name: 'nuxt:cross-origin-prefetch',

View File

@ -1,5 +1,5 @@
import { createDebugger } from 'hookable' import { createDebugger } from 'hookable'
import { defineNuxtPlugin } from '#app/nuxt' import { defineNuxtPlugin } from '../nuxt'
export default defineNuxtPlugin({ export default defineNuxtPlugin({
name: 'nuxt:debug', name: 'nuxt:debug',

View File

@ -1,9 +1,9 @@
import { parseURL } from 'ufo' import { parseURL } from 'ufo'
import { defineNuxtPlugin } from '#app/nuxt' import { defineNuxtPlugin } from '../nuxt'
import { loadPayload } from '#app/composables/payload' import { loadPayload } from '../composables/payload'
import { onNuxtReady } from '#app/composables/ready' import { onNuxtReady } from '../composables/ready'
import { useRouter } from '#app/composables/router' import { useRouter } from '../composables/router'
import { getAppManifest } from '#app/composables/manifest' import { getAppManifest } from '../composables/manifest'
// @ts-expect-error virtual file // @ts-expect-error virtual file
import { appManifest as isAppManifestEnabled } from '#build/nuxt.config.mjs' import { appManifest as isAppManifestEnabled } from '#build/nuxt.config.mjs'

View File

@ -1,4 +1,4 @@
import { defineNuxtPlugin } from '#app/nuxt' import { defineNuxtPlugin } from '../nuxt'
export default defineNuxtPlugin({ export default defineNuxtPlugin({
name: 'nuxt:webpack-preload', name: 'nuxt:webpack-preload',

View File

@ -1,5 +1,5 @@
import destr from 'destr' import destr from 'destr'
import { defineNuxtPlugin, useNuxtApp } from '#app/nuxt' import { defineNuxtPlugin, useNuxtApp } from '../nuxt'
export default defineNuxtPlugin({ export default defineNuxtPlugin({
name: 'nuxt:restore-state', name: 'nuxt:restore-state',

View File

@ -1,8 +1,8 @@
import { reactive, ref, shallowReactive, shallowRef } from 'vue' import { reactive, ref, shallowReactive, shallowRef } from 'vue'
import destr from 'destr' import destr from 'destr'
import { definePayloadReviver, getNuxtClientPayload } from '#app/composables/payload' import { definePayloadReviver, getNuxtClientPayload } from '../composables/payload'
import { createError } from '#app/composables/error' import { createError } from '../composables/error'
import { defineNuxtPlugin, useNuxtApp } from '#app/nuxt' import { defineNuxtPlugin, useNuxtApp } from '../nuxt'
// @ts-expect-error Virtual file. // @ts-expect-error Virtual file.
import { componentIslands } from '#build/nuxt.config.mjs' import { componentIslands } from '#build/nuxt.config.mjs'

View File

@ -1,7 +1,7 @@
import { isReactive, isRef, isShallow, toRaw } from 'vue' import { isReactive, isRef, isShallow, toRaw } from 'vue'
import { definePayloadReducer } from '#app/composables/payload' import { definePayloadReducer } from '../composables/payload'
import { isNuxtError } from '#app/composables/error' import { isNuxtError } from '../composables/error'
import { defineNuxtPlugin } from '#app/nuxt' import { defineNuxtPlugin } from '../nuxt'
// @ts-expect-error Virtual file. // @ts-expect-error Virtual file.
import { componentIslands } from '#build/nuxt.config.mjs' import { componentIslands } from '#build/nuxt.config.mjs'

View File

@ -1,6 +1,6 @@
import { isChangingPage } from '#app/components/utils' import { isChangingPage } from '../components/utils'
import { useRouter } from '#app/composables/router' import { useRouter } from '../composables/router'
import { defineNuxtPlugin } from '#app/nuxt' import { defineNuxtPlugin } from '../nuxt'
export default defineNuxtPlugin((nuxtApp) => { export default defineNuxtPlugin((nuxtApp) => {
if (!document.startViewTransition) { return } if (!document.startViewTransition) { return }

View File

@ -74,12 +74,12 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => {
if (lazy) { if (lazy) {
imports.add(genImport('vue', [{ name: 'defineAsyncComponent', as: '__defineAsyncComponent' }])) imports.add(genImport('vue', [{ name: 'defineAsyncComponent', as: '__defineAsyncComponent' }]))
identifier += '_lazy' identifier += '_lazy'
imports.add(`const ${identifier} = /*#__PURE__*/ __defineAsyncComponent(${genDynamicImport(component.filePath, { interopDefault: true })}${isClientOnly ? '.then(c => createClientOnly(c))' : ''})`) imports.add(`const ${identifier} = __defineAsyncComponent(${genDynamicImport(component.filePath, { interopDefault: true })}${isClientOnly ? '.then(c => createClientOnly(c))' : ''})`)
} else { } else {
imports.add(genImport(component.filePath, [{ name: component.export, as: identifier }])) imports.add(genImport(component.filePath, [{ name: component.export, as: identifier }]))
if (isClientOnly) { if (isClientOnly) {
imports.add(`const ${identifier}_wrapped = /*#__PURE__*/ createClientOnly(${identifier})`) imports.add(`const ${identifier}_wrapped = createClientOnly(${identifier})`)
identifier += '_wrapped' identifier += '_wrapped'
} }
} }

View File

@ -1,6 +1,7 @@
import { defineComponent, h } from 'vue' import { defineComponent, h } from 'vue'
import NuxtIsland from '#app/components/nuxt-island' import NuxtIsland from '#app/components/nuxt-island'
/*! @__NO_SIDE_EFFECTS__ */
export const createServerComponent = (name: string) => { export const createServerComponent = (name: string) => {
return defineComponent({ return defineComponent({
name, name,

View File

@ -90,7 +90,7 @@ export const componentsIslandsTemplate: NuxtTemplate<ComponentsTemplateContext>
(c) => { (c) => {
const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']` const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']`
const comment = createImportMagicComments(c) const comment = createImportMagicComments(c)
return `export const ${c.pascalName} = /* #__PURE__ */ defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))` return `export const ${c.pascalName} = defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))`
} }
)].join('\n') )].join('\n')
} }

View File

@ -244,7 +244,8 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
} }
) )
nuxt.hook('nitro:build:before', async (nitro) => { nuxt.hook('nitro:init', (nitro) => {
nitro.hooks.hook('rollup:before', async (nitro) => {
const routeRules = {} as Record<string, any> const routeRules = {} as Record<string, any>
const _routeRules = nitro.options.routeRules const _routeRules = nitro.options.routeRules
for (const key in _routeRules) { for (const key in _routeRules) {
@ -292,6 +293,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
})) }))
await fsp.writeFile(join(tempDir, `meta/${buildId}.json`), JSON.stringify(manifest)) await fsp.writeFile(join(tempDir, `meta/${buildId}.json`), JSON.stringify(manifest))
}) })
})
} }
// Add fallback server for `ssr: false` // Add fallback server for `ssr: false`
@ -457,6 +459,14 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
}) })
} }
// Copy public assets after prerender so app manifest can be present
if (!nuxt.options.dev) {
nitro.hooks.hook('rollup:before', async (nitro) => {
await copyPublicAssets(nitro)
await nuxt.callHook('nitro:build:public-assets', nitro)
})
}
// nuxt build/dev // nuxt build/dev
nuxt.hook('build:done', async () => { nuxt.hook('build:done', async () => {
await nuxt.callHook('nitro:build:before', nitro) await nuxt.callHook('nitro:build:before', nitro)
@ -464,8 +474,6 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
await build(nitro) await build(nitro)
} else { } else {
await prepare(nitro) await prepare(nitro)
await copyPublicAssets(nitro)
await nuxt.callHook('nitro:build:public-assets', nitro)
await prerender(nitro) await prerender(nitro)
logger.restoreAll() logger.restoreAll()

View File

@ -285,7 +285,7 @@ export const appConfigTemplate: NuxtTemplate = {
write: true, write: true,
getContents: async ({ app, nuxt }) => { getContents: async ({ app, nuxt }) => {
return ` return `
import { updateAppConfig } from '#app' import { updateAppConfig } from '#app/config'
import { defuFn } from '${await _resolveId('defu')}' import { defuFn } from '${await _resolveId('defu')}'
const inlineConfig = ${JSON.stringify(nuxt.options.appConfig, null, 2)} const inlineConfig = ${JSON.stringify(nuxt.options.appConfig, null, 2)}

View File

@ -1,7 +1,6 @@
import { createHead as createClientHead, setHeadInjectionHandler } from '@unhead/vue' import { createHead as createClientHead, setHeadInjectionHandler } from '@unhead/vue'
import { renderDOMHead } from '@unhead/dom' import { renderDOMHead } from '@unhead/dom'
import { defineNuxtPlugin } from '#app/nuxt' import { defineNuxtPlugin, useNuxtApp } from '#app/nuxt'
import { useNuxtApp } from '#app'
// @ts-expect-error virtual file // @ts-expect-error virtual file
import unheadPlugins from '#build/unhead-plugins.mjs' import unheadPlugins from '#build/unhead-plugins.mjs'

View File

@ -12,70 +12,89 @@ const commonPresets: InlinePreset[] = [
}) })
] ]
const appPreset = defineUnimportPreset({ const granularAppPresets: InlinePreset[] = [
from: '#app', {
imports: [ from: '#app/components/nuxt-link',
'useAsyncData', imports: ['defineNuxtLink']
'useLazyAsyncData', },
'useNuxtData', {
'refreshNuxtData', imports: ['useNuxtApp', 'defineNuxtPlugin', 'definePayloadPlugin', 'useRuntimeConfig', 'defineAppConfig'],
'clearNuxtData', from: '#app/nuxt'
'defineNuxtComponent', },
'useNuxtApp', {
'defineNuxtPlugin', imports: ['requestIdleCallback', 'cancelIdleCallback'],
'definePayloadPlugin', from: '#app/compat/idle-callback'
'reloadNuxtApp', },
'useRuntimeConfig', {
'useState', imports: ['useAppConfig', 'updateAppConfig'],
'clearNuxtState', from: '#app/config'
'useFetch', },
'useLazyFetch', {
'useCookie', imports: ['defineNuxtComponent'],
'useRequestHeaders', from: '#app/composables/component'
'useRequestEvent', },
'useRequestFetch', {
'useRequestURL', imports: ['useAsyncData', 'useLazyAsyncData', 'useNuxtData', 'refreshNuxtData', 'clearNuxtData'],
'setResponseStatus', from: '#app/composables/asyncData'
'setPageLayout', },
'prerenderRoutes', {
'onNuxtReady', imports: ['useHydration'],
'useRouter', from: '#app/composables/hydrate'
'useRoute', },
'defineNuxtRouteMiddleware', {
'navigateTo', imports: ['useState', 'clearNuxtState'],
'abortNavigation', from: '#app/composables/state'
'addRouteMiddleware', },
'showError', {
'clearError', imports: ['clearError', 'createError', 'isNuxtError', 'showError', 'useError'],
'isNuxtError', from: '#app/composables/error'
'useError', },
'createError', {
'defineNuxtLink', imports: ['useFetch', 'useLazyFetch'],
'useAppConfig', from: '#app/composables/fetch'
'updateAppConfig', },
'defineAppConfig', {
'preloadComponents', imports: ['useCookie'],
'preloadRouteComponents', from: '#app/composables/cookie'
'prefetchComponents', },
'loadPayload', {
'preloadPayload', imports: ['prerenderRoutes', 'useRequestHeaders', 'useRequestEvent', 'useRequestFetch', 'setResponseStatus'],
'isPrerendered', from: '#app/composables/ssr'
'getAppManifest', },
'getRouteRules', {
'definePayloadReducer', imports: ['onNuxtReady'],
'definePayloadReviver', from: '#app/composables/ready'
'requestIdleCallback', },
'cancelIdleCallback' {
imports: ['preloadComponents', 'prefetchComponents', 'preloadRouteComponents'],
from: '#app/composables/preload'
},
{
imports: ['abortNavigation', 'addRouteMiddleware', 'defineNuxtRouteMiddleware', 'setPageLayout', 'navigateTo', 'useRoute', 'useRouter'],
from: '#app/composables/router'
},
{
imports: ['isPrerendered', 'loadPayload', 'preloadPayload', 'definePayloadReducer', 'definePayloadReviver'],
from: '#app/composables/payload'
},
{
imports: ['getAppManifest', 'getRouteRules'],
from: '#app/composables/manifest'
},
{
imports: ['reloadNuxtApp'],
from: '#app/composables/chunk'
},
{
imports: ['useRequestURL'],
from: '#app/composables/url'
}
] ]
})
// vue-router // This is a separate preset as we'll swap these out for import from `vue-router` itself in `pages` module
const routerPreset = defineUnimportPreset({ const routerPreset = defineUnimportPreset({
from: '#app', imports: ['onBeforeRouteLeave', 'onBeforeRouteUpdate'],
imports: [ from: '#app/composables/router'
'onBeforeRouteLeave',
'onBeforeRouteUpdate'
]
}) })
// vue // vue
@ -180,7 +199,7 @@ const vueTypesPreset = defineUnimportPreset({
export const defaultPresets: InlinePreset[] = [ export const defaultPresets: InlinePreset[] = [
...commonPresets, ...commonPresets,
appPreset, ...granularAppPresets,
routerPreset, routerPreset,
vuePreset, vuePreset,
vueTypesPreset vueTypesPreset

View File

@ -53,6 +53,11 @@ export default defineNuxtModule({
} }
nuxt.options.pages = await isPagesEnabled() nuxt.options.pages = await isPagesEnabled()
nuxt.hook('app:templates', async (app) => {
app.pages = await resolvePagesRoutes()
await nuxt.callHook('pages:extend', app.pages)
})
// Restart Nuxt when pages dir is added or removed // Restart Nuxt when pages dir is added or removed
const restartPaths = nuxt.options._layers.flatMap((layer) => { const restartPaths = nuxt.options._layers.flatMap((layer) => {
const pagesDir = (layer.config.rootDir === nuxt.options.rootDir ? nuxt.options : layer.config).dir?.pages || 'pages' const pagesDir = (layer.config.rootDir === nuxt.options.rootDir ? nuxt.options : layer.config).dir?.pages || 'pages'
@ -110,8 +115,11 @@ export default defineNuxtModule({
logs: nuxt.options.debug, logs: nuxt.options.debug,
async beforeWriteFiles (rootPage) { async beforeWriteFiles (rootPage) {
rootPage.children.forEach(child => child.delete()) rootPage.children.forEach(child => child.delete())
const pages = await resolvePagesRoutes() let pages = nuxt.apps.default?.pages
if (!pages) {
pages = await resolvePagesRoutes()
await nuxt.callHook('pages:extend', pages) await nuxt.callHook('pages:extend', pages)
}
function addPage (parent: EditableTreeNode, page: NuxtPage) { function addPage (parent: EditableTreeNode, page: NuxtPage) {
// @ts-expect-error TODO: either fix types upstream or figure out another // @ts-expect-error TODO: either fix types upstream or figure out another
// way to add a route without a file, which must be possible // way to add a route without a file, which must be possible
@ -174,7 +182,7 @@ export default defineNuxtModule({
// Add vue-router route guard imports // Add vue-router route guard imports
nuxt.hook('imports:sources', (sources) => { nuxt.hook('imports:sources', (sources) => {
const routerImports = sources.find(s => s.from === '#app' && s.imports.includes('onBeforeRouteLeave')) const routerImports = sources.find(s => s.from === '#app/composables/router' && s.imports.includes('onBeforeRouteLeave'))
if (routerImports) { if (routerImports) {
routerImports.from = '#vue-router' routerImports.from = '#vue-router'
} }
@ -339,12 +347,9 @@ export default defineNuxtModule({
) )
// Do not prefetch page chunks // Do not prefetch page chunks
nuxt.hook('build:manifest', async (manifest) => { nuxt.hook('build:manifest', (manifest) => {
if (nuxt.options.dev) { return } if (nuxt.options.dev) { return }
const pages = await resolvePagesRoutes() const sourceFiles = getSources(nuxt.apps.default.pages || [])
await nuxt.callHook('pages:extend', pages)
const sourceFiles = getSources(pages)
for (const key in manifest) { for (const key in manifest) {
if (manifest[key].isEntry) { if (manifest[key].isEntry) {
@ -357,10 +362,8 @@ export default defineNuxtModule({
// Add routes template // Add routes template
addTemplate({ addTemplate({
filename: 'routes.mjs', filename: 'routes.mjs',
async getContents () { getContents ({ app }) {
const pages = await resolvePagesRoutes() const { routes, imports } = normalizeRoutes(app.pages)
await nuxt.callHook('pages:extend', pages)
const { routes, imports } = normalizeRoutes(pages)
return [...imports, `export default ${routes}`].join('\n') return [...imports, `export default ${routes}`].join('\n')
} }
}) })

View File

@ -3,7 +3,7 @@ import { getCurrentInstance } from 'vue'
import type { RouteLocationNormalized, RouteLocationNormalizedLoaded, RouteRecordRedirectOption } from '#vue-router' import type { RouteLocationNormalized, RouteLocationNormalizedLoaded, RouteRecordRedirectOption } from '#vue-router'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import type { NitroRouteConfig } from 'nitropack' import type { NitroRouteConfig } from 'nitropack'
import type { NuxtError } from '#app' import type { NuxtError } from '#app/composables/error'
export interface PageMeta { export interface PageMeta {
[key: string]: unknown [key: string]: unknown
@ -76,5 +76,6 @@ export const definePageMeta = (meta: PageMeta): void => {
* For more control, such as if you are using a custom `path` or `alias` set in the page's `definePageMeta`, you * For more control, such as if you are using a custom `path` or `alias` set in the page's `definePageMeta`, you
* should set `routeRules` directly within your `nuxt.config`. * should set `routeRules` directly within your `nuxt.config`.
*/ */
/*! @__NO_SIDE_EFFECTS__ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
export const defineRouteRules = (rules: NitroRouteConfig): void => {} export const defineRouteRules = (rules: NitroRouteConfig): void => {}

View File

@ -11,7 +11,10 @@ import {
import { createError } from 'h3' import { createError } from 'h3'
import { isEqual, withoutBase } from 'ufo' import { isEqual, withoutBase } from 'ufo'
import type { PageMeta, Plugin, RouteMiddleware } from '../../../app/index' import type { PageMeta } from '../composables'
import type { RouteMiddleware } from '#app/composables/router'
import type { Plugin } from '#app/nuxt'
import { defineNuxtPlugin, useRuntimeConfig } from '#app/nuxt' import { defineNuxtPlugin, useRuntimeConfig } from '#app/nuxt'
import { clearError, showError, useError } from '#app/composables/error' import { clearError, showError, useError } from '#app/composables/error'
import { navigateTo } from '#app/composables/router' import { navigateTo } from '#app/composables/router'

View File

@ -68,7 +68,7 @@ describe('imports:nuxt', () => {
continue continue
} }
it(`should register ${name} globally`, () => { it(`should register ${name} globally`, () => {
expect(defaultPresets.flatMap(a => a.from === '#app' ? a.imports : [])).to.include(name) expect(defaultPresets.flatMap(a => a.from.startsWith('#app/') ? a.imports : [])).to.include(name)
}) })
} }
} catch (e) { } catch (e) {

View File

@ -1,6 +1,6 @@
import type { Hookable } from 'hookable' import type { Hookable } from 'hookable'
import type { Ignore } from 'ignore' import type { Ignore } from 'ignore'
import type { NuxtHooks, NuxtLayout, NuxtMiddleware } from './hooks' import type { NuxtHooks, NuxtLayout, NuxtMiddleware, NuxtPage } from './hooks'
import type { Component } from './components' import type { Component } from './components'
import type { NuxtOptions } from './config' import type { NuxtOptions } from './config'
@ -61,6 +61,7 @@ export interface NuxtApp {
middleware: NuxtMiddleware[] middleware: NuxtMiddleware[]
templates: NuxtTemplate[] templates: NuxtTemplate[]
configs: string[] configs: string[]
pages?: NuxtPage[]
} }
export interface Nuxt { export interface Nuxt {

View File

@ -15,7 +15,6 @@ import type { ViteBuildContext } from './vite'
import { devStyleSSRPlugin } from './plugins/dev-ssr-css' import { devStyleSSRPlugin } from './plugins/dev-ssr-css'
import { runtimePathsPlugin } from './plugins/paths' import { runtimePathsPlugin } from './plugins/paths'
import { typeCheckPlugin } from './plugins/type-check' import { typeCheckPlugin } from './plugins/type-check'
import { pureAnnotationsPlugin } from './plugins/pure-annotations'
import { viteNodePlugin } from './vite-node' import { viteNodePlugin } from './vite-node'
import { createViteLogger } from './utils/logger' import { createViteLogger } from './utils/logger'
@ -80,11 +79,7 @@ export async function buildClient (ctx: ViteBuildContext) {
runtimePathsPlugin({ runtimePathsPlugin({
sourcemap: !!ctx.nuxt.options.sourcemap.client sourcemap: !!ctx.nuxt.options.sourcemap.client
}), }),
viteNodePlugin(ctx), viteNodePlugin(ctx)
pureAnnotationsPlugin.vite({
sourcemap: !!ctx.nuxt.options.sourcemap.client,
functions: ['defineComponent', 'defineAsyncComponent', 'defineNuxtLink', 'createClientOnly', 'defineNuxtPlugin', 'defineNuxtRouteMiddleware', 'defineNuxtComponent', 'useRuntimeConfig', 'defineRouteRules']
})
], ],
appType: 'custom', appType: 'custom',
server: { server: {

View File

@ -1,40 +0,0 @@
import MagicString from 'magic-string'
import { createUnplugin } from 'unplugin'
import { stripLiteral } from 'strip-literal'
import { isJS, isVue } from '../../../nuxt/src/core/utils/plugins'
interface PureAnnotationsOptions {
sourcemap: boolean
functions: string[]
}
export const pureAnnotationsPlugin = createUnplugin((options: PureAnnotationsOptions) => {
const FUNCTION_RE = new RegExp(`(?<!\\/\\* #__PURE__ \\*\\/ )\\b(${options.functions.join('|')})\\s*\\(`, 'g')
const FUNCTION_RE_SINGLE = new RegExp(`(?<!\\/\\* #__PURE__ \\*\\/ )\\b(${options.functions.join('|')})\\s*\\(`)
return {
name: 'nuxt:pure-annotations',
enforce: 'post',
transformInclude (id) {
return isVue(id, { type: ['script'] }) || isJS(id)
},
transform (code) {
if (!FUNCTION_RE_SINGLE.test(code)) { return }
const s = new MagicString(code)
const strippedCode = stripLiteral(code)
for (const match of strippedCode.matchAll(FUNCTION_RE)) {
s.overwrite(match.index!, match.index! + match[0].length, '/* #__PURE__ */ ' + match[0])
}
if (s.hasChanged()) {
return {
code: s.toString(),
map: options.sourcemap
? s.generateMap({ hires: true })
: undefined
}
}
}
}
})

View File

@ -8,7 +8,6 @@ import type { ViteConfig } from '@nuxt/schema'
import type { ViteBuildContext } from './vite' import type { ViteBuildContext } from './vite'
import { createViteLogger } from './utils/logger' import { createViteLogger } from './utils/logger'
import { initViteNodeServer } from './vite-node' import { initViteNodeServer } from './vite-node'
import { pureAnnotationsPlugin } from './plugins/pure-annotations'
import { writeManifest } from './manifest' import { writeManifest } from './manifest'
import { transpile } from './utils/transpile' import { transpile } from './utils/transpile'
@ -101,12 +100,7 @@ export async function buildServer (ctx: ViteBuildContext) {
preTransformRequests: false, preTransformRequests: false,
hmr: false hmr: false
}, },
plugins: [ plugins: []
pureAnnotationsPlugin.vite({
sourcemap: !!ctx.nuxt.options.sourcemap.server,
functions: ['defineComponent', 'defineAsyncComponent', 'defineNuxtLink', 'createClientOnly', 'defineNuxtPlugin', 'defineNuxtRouteMiddleware', 'defineNuxtComponent', 'useRuntimeConfig', 'defineRouteRules']
})
]
} satisfies vite.InlineConfig, ctx.nuxt.options.vite.$server || {})) } satisfies vite.InlineConfig, ctx.nuxt.options.vite.$server || {}))
if (!ctx.nuxt.options.dev) { if (!ctx.nuxt.options.dev) {

View File

@ -1,6 +1,33 @@
import { logger } from '@nuxt/kit' import { logger } from '@nuxt/kit'
import { join, normalize, relative } from 'pathe'
import { withoutBase } from 'ufo'
import { isCSSRequest } from 'vite'
import type { ViteDevServer } from 'vite' import type { ViteDevServer } from 'vite'
// https://github.com/vitejs/vite/tree/main/packages/vite/src/node/server/warmup.ts#L62-L70
function fileToUrl (file: string, root: string) {
const url = relative(root, file)
// out of root, use /@fs/ prefix
if (url[0] === '.') {
return join('/@fs/', normalize(file))
}
// file within root, create root-relative url
return '/' + normalize(url)
}
function normaliseURL (url: string, base: string) {
// remove any base url
url = withoutBase(url, base)
// unwrap record
if (url.startsWith('/@id/')) {
url = url.slice('/@id/'.length).replace('__x00__', '\0')
}
// strip query
url = url.replace(/(\?|&)import=?(?:&|$)/, '').replace(/[?&]$/, '')
return url
}
// TODO: use built-in warmup logic when we update to vite 5
export async function warmupViteServer ( export async function warmupViteServer (
server: ViteDevServer, server: ViteDevServer,
entries: string[], entries: string[],
@ -9,7 +36,12 @@ export async function warmupViteServer (
const warmedUrls = new Set<String>() const warmedUrls = new Set<String>()
const warmup = async (url: string) => { const warmup = async (url: string) => {
if (warmedUrls.has(url)) { url = normaliseURL(url, server.config.base)
if (warmedUrls.has(url)) { return }
const m = await server.moduleGraph.getModuleByUrl(url, isServer)
// a module that is already compiled (and can't be warmed up anyway)
if (m?.transformResult?.code || m?.ssrTransformResult?.code) {
return return
} }
warmedUrls.add(url) warmedUrls.add(url)
@ -18,10 +50,14 @@ export async function warmupViteServer (
} catch (e) { } catch (e) {
logger.debug('Warmup for %s failed with: %s', url, e) logger.debug('Warmup for %s failed with: %s', url, e)
} }
// Don't warmup CSS file dependencies as they have already all been loaded to produce result
if (isCSSRequest(url)) { return }
const mod = await server.moduleGraph.getModuleByUrl(url, isServer) const mod = await server.moduleGraph.getModuleByUrl(url, isServer)
const deps = mod?.ssrTransformResult?.deps /* server */ || Array.from(mod?.importedModules /* client */ || []).map(m => m.url) const deps = mod?.ssrTransformResult?.deps /* server */ || Array.from(mod?.importedModules /* client */ || []).map(m => m.url)
await Promise.all(deps.map(m => warmup(m.replace('/@id/__x00__', '\0')))) await Promise.all(deps.map(m => warmup(m)))
} }
await Promise.all(entries.map(entry => warmup(entry))) await Promise.all(entries.map(entry => warmup(fileToUrl(entry, server.config.root))))
} }

View File

@ -192,13 +192,9 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
} }
}) })
if ( if (nuxt.options.vite.warmupEntry !== false) {
nuxt.options.vite.warmupEntry !== false &&
// https://github.com/nuxt/nuxt/issues/14898
!(env.isServer && ctx.nuxt.options.vite.devBundler !== 'legacy')
) {
const start = Date.now() const start = Date.now()
warmupViteServer(server, [join('/@fs/', ctx.entry)], env.isServer) warmupViteServer(server, [ctx.entry], env.isServer)
.then(() => logger.info(`Vite ${env.isClient ? 'client' : 'server'} warmed up in ${Date.now() - start}ms`)) .then(() => logger.info(`Vite ${env.isClient ? 'client' : 'server'} warmed up in ${Date.now() - start}ms`))
.catch(logger.error) .catch(logger.error)
} }

View File

@ -1200,6 +1200,8 @@ describe('nested suspense', () => {
const first = start.match(/\/suspense\/(?<parentType>a?sync)-(?<parentNum>\d)\/(?<childType>a?sync)-(?<childNum>\d)\//)!.groups! const first = start.match(/\/suspense\/(?<parentType>a?sync)-(?<parentNum>\d)\/(?<childType>a?sync)-(?<childNum>\d)\//)!.groups!
const last = nav.match(/\/suspense\/(?<parentType>a?sync)-(?<parentNum>\d)\//)!.groups! const last = nav.match(/\/suspense\/(?<parentType>a?sync)-(?<parentNum>\d)\//)!.groups!
await new Promise<void>(resolve => setTimeout(resolve, 50))
expect(consoleLogs.map(l => l.text).filter(i => !i.includes('[vite]') && !i.includes('<Suspense> is an experimental feature')).sort()).toEqual([ expect(consoleLogs.map(l => l.text).filter(i => !i.includes('[vite]') && !i.includes('<Suspense> is an experimental feature')).sort()).toEqual([
// [first load] from parent // [first load] from parent
`[${first.parentType}]`, `[${first.parentType}]`,

View File

@ -3,7 +3,7 @@ if (import.meta.client) {
console.log('[async] [async]') console.log('[async] [async]')
} }
const route = useRoute('suspense-async-parent-async-child') const route = useRoute('suspense-async-parent-async-child')
await new Promise(resolve => setTimeout(resolve, 500)) await new Promise(resolve => setTimeout(resolve, 50))
if (import.meta.client) { if (import.meta.client) {
console.log(`[async] [${route.params.parent}] [async] [${route.params.child}] running async data`) console.log(`[async] [${route.params.parent}] [async] [${route.params.child}] running async data`)
} }

View File

@ -3,7 +3,7 @@ if (import.meta.client) {
console.log('[sync] [async]') console.log('[sync] [async]')
} }
const route = useRoute('suspense-async-parent-sync-child') const route = useRoute('suspense-async-parent-sync-child')
await new Promise(resolve => setTimeout(resolve, 500)) await new Promise(resolve => setTimeout(resolve, 50))
if (import.meta.client) { if (import.meta.client) {
console.log(`[sync] [${route.params.parent}] [async] [${route.params.child}] running async data`) console.log(`[sync] [${route.params.parent}] [async] [${route.params.child}] running async data`)
} }