mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-23 22:25:12 +00:00
Merge remote-tracking branch 'origin/main' into fix/watch-build-dir
This commit is contained in:
commit
560a8a9168
@ -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)/**/*",
|
||||||
|
@ -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: {
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
|
@ -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: {
|
||||||
|
@ -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: {
|
||||||
|
@ -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'
|
||||||
|
@ -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
|
||||||
|
@ -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'
|
||||||
|
@ -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
|
||||||
|
@ -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',
|
||||||
|
@ -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 {
|
||||||
/**
|
/**
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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))
|
||||||
|
@ -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
|
||||||
|
@ -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'
|
||||||
|
@ -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 }
|
||||||
|
@ -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
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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'
|
||||||
|
@ -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'
|
||||||
|
@ -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 }
|
||||||
|
@ -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'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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')
|
||||||
}
|
}
|
||||||
|
@ -244,53 +244,55 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
nuxt.hook('nitro:build:before', async (nitro) => {
|
nuxt.hook('nitro:init', (nitro) => {
|
||||||
const routeRules = {} as Record<string, any>
|
nitro.hooks.hook('rollup:before', async (nitro) => {
|
||||||
const _routeRules = nitro.options.routeRules
|
const routeRules = {} as Record<string, any>
|
||||||
for (const key in _routeRules) {
|
const _routeRules = nitro.options.routeRules
|
||||||
if (key === '/__nuxt_error') { continue }
|
for (const key in _routeRules) {
|
||||||
const filteredRules = Object.entries(_routeRules[key])
|
if (key === '/__nuxt_error') { continue }
|
||||||
.filter(([key, value]) => ['prerender', 'redirect'].includes(key) && value)
|
const filteredRules = Object.entries(_routeRules[key])
|
||||||
.map(([key, value]: any) => {
|
.filter(([key, value]) => ['prerender', 'redirect'].includes(key) && value)
|
||||||
if (key === 'redirect') {
|
.map(([key, value]: any) => {
|
||||||
return [key, typeof value === 'string' ? value : value.to]
|
if (key === 'redirect') {
|
||||||
}
|
return [key, typeof value === 'string' ? value : value.to]
|
||||||
return [key, value]
|
}
|
||||||
})
|
return [key, value]
|
||||||
if (filteredRules.length > 0) {
|
})
|
||||||
routeRules[key] = Object.fromEntries(filteredRules)
|
if (filteredRules.length > 0) {
|
||||||
}
|
routeRules[key] = Object.fromEntries(filteredRules)
|
||||||
}
|
|
||||||
|
|
||||||
// Add pages prerendered but not covered by route rules
|
|
||||||
const prerenderedRoutes = new Set<string>()
|
|
||||||
const routeRulesMatcher = toRouteMatcher(
|
|
||||||
createRadixRouter({ routes: routeRules })
|
|
||||||
)
|
|
||||||
const payloadSuffix = nuxt.options.experimental.renderJsonPayloads ? '/_payload.json' : '/_payload.js'
|
|
||||||
for (const route of nitro._prerenderedRoutes || []) {
|
|
||||||
if (!route.error && route.route.endsWith(payloadSuffix)) {
|
|
||||||
const url = route.route.slice(0, -payloadSuffix.length) || '/'
|
|
||||||
const rules = defu({}, ...routeRulesMatcher.matchAll(url).reverse()) as Record<string, any>
|
|
||||||
if (!rules.prerender) {
|
|
||||||
prerenderedRoutes.add(url)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const manifest = {
|
// Add pages prerendered but not covered by route rules
|
||||||
id: buildId,
|
const prerenderedRoutes = new Set<string>()
|
||||||
timestamp: buildTimestamp,
|
const routeRulesMatcher = toRouteMatcher(
|
||||||
matcher: exportMatcher(routeRulesMatcher),
|
createRadixRouter({ routes: routeRules })
|
||||||
prerendered: nuxt.options.dev ? [] : [...prerenderedRoutes]
|
)
|
||||||
}
|
const payloadSuffix = nuxt.options.experimental.renderJsonPayloads ? '/_payload.json' : '/_payload.js'
|
||||||
|
for (const route of nitro._prerenderedRoutes || []) {
|
||||||
|
if (!route.error && route.route.endsWith(payloadSuffix)) {
|
||||||
|
const url = route.route.slice(0, -payloadSuffix.length) || '/'
|
||||||
|
const rules = defu({}, ...routeRulesMatcher.matchAll(url).reverse()) as Record<string, any>
|
||||||
|
if (!rules.prerender) {
|
||||||
|
prerenderedRoutes.add(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await fsp.mkdir(join(tempDir, 'meta'), { recursive: true })
|
const manifest = {
|
||||||
await fsp.writeFile(join(tempDir, 'latest.json'), JSON.stringify({
|
id: buildId,
|
||||||
id: buildId,
|
timestamp: buildTimestamp,
|
||||||
timestamp: buildTimestamp
|
matcher: exportMatcher(routeRulesMatcher),
|
||||||
}))
|
prerendered: nuxt.options.dev ? [] : [...prerenderedRoutes]
|
||||||
await fsp.writeFile(join(tempDir, `meta/${buildId}.json`), JSON.stringify(manifest))
|
}
|
||||||
|
|
||||||
|
await fsp.mkdir(join(tempDir, 'meta'), { recursive: true })
|
||||||
|
await fsp.writeFile(join(tempDir, 'latest.json'), JSON.stringify({
|
||||||
|
id: buildId,
|
||||||
|
timestamp: buildTimestamp
|
||||||
|
}))
|
||||||
|
await fsp.writeFile(join(tempDir, `meta/${buildId}.json`), JSON.stringify(manifest))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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()
|
||||||
|
@ -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)}
|
||||||
|
@ -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'
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
await nuxt.callHook('pages:extend', pages)
|
if (!pages) {
|
||||||
|
pages = await resolvePagesRoutes()
|
||||||
|
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')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -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 => {}
|
||||||
|
@ -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'
|
||||||
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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: {
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
@ -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) {
|
||||||
|
@ -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))))
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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}]`,
|
||||||
|
@ -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`)
|
||||||
}
|
}
|
||||||
|
@ -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`)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user