mirror of
https://github.com/nuxt/nuxt.git
synced 2025-03-21 00:35:55 +00:00
refactor(nuxt): re-organize internal runtime/nitro
files (#31131)
This commit is contained in:
parent
563d449010
commit
1baf3ebad6
@ -700,7 +700,7 @@ These options have been set to their current values for some time and we do not
|
|||||||
|
|
||||||
* `polyfillVueUseHead` is implementable in user-land with [this plugin](https://github.com/nuxt/nuxt/blob/f209158352b09d1986aa320e29ff36353b91c358/packages/nuxt/src/head/runtime/plugins/vueuse-head-polyfill.ts#L10-L11)
|
* `polyfillVueUseHead` is implementable in user-land with [this plugin](https://github.com/nuxt/nuxt/blob/f209158352b09d1986aa320e29ff36353b91c358/packages/nuxt/src/head/runtime/plugins/vueuse-head-polyfill.ts#L10-L11)
|
||||||
|
|
||||||
* `respectNoSSRHeader`is implementable in user-land with [server middleware](https://github.com/nuxt/nuxt/blob/c660b39447f0d5b8790c0826092638d321cd6821/packages/nuxt/src/core/runtime/nitro/no-ssr.ts#L8-L9)
|
* `respectNoSSRHeader`is implementable in user-land with [server middleware](https://github.com/nuxt/nuxt/blob/c660b39447f0d5b8790c0826092638d321cd6821/packages/nuxt/src/core/runtime/nitro/middleware/no-ssr.ts#L8-L9)
|
||||||
|
|
||||||
## Nuxt 2 vs Nuxt 3+
|
## Nuxt 2 vs Nuxt 3+
|
||||||
|
|
||||||
|
@ -95,9 +95,9 @@ See [Nitro](https://nitro.unjs.io/guide/plugins#available-hooks) for all availab
|
|||||||
Hook | Arguments | Description | Types
|
Hook | Arguments | Description | Types
|
||||||
-----------------------|-----------------------|--------------------------------------|------------------
|
-----------------------|-----------------------|--------------------------------------|------------------
|
||||||
`dev:ssr-logs` | `{ path, logs }` | Server | Called at the end of a request cycle with an array of server-side logs.
|
`dev:ssr-logs` | `{ path, logs }` | Server | Called at the end of a request cycle with an array of server-side logs.
|
||||||
`render:response` | `response, { event }` | Called before sending the response. | [response](https://github.com/nuxt/nuxt/blob/71ef8bd3ff207fd51c2ca18d5a8c7140476780c7/packages/nuxt/src/core/runtime/nitro/renderer.ts#L24), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
|
`render:response` | `response, { event }` | Called before sending the response. | [response](https://github.com/nuxt/nuxt/blob/71ef8bd3ff207fd51c2ca18d5a8c7140476780c7/packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts#L24), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
|
||||||
`render:html` | `html, { event }` | Called before constructing the HTML. | [html](https://github.com/nuxt/nuxt/blob/71ef8bd3ff207fd51c2ca18d5a8c7140476780c7/packages/nuxt/src/core/runtime/nitro/renderer.ts#L15), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
|
`render:html` | `html, { event }` | Called before constructing the HTML. | [html](https://github.com/nuxt/nuxt/blob/71ef8bd3ff207fd51c2ca18d5a8c7140476780c7/packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts#L15), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
|
||||||
`render:island` | `islandResponse, { event, islandContext }` | Called before constructing the island HTML. | [islandResponse](https://github.com/nuxt/nuxt/blob/e50cabfed1984c341af0d0c056a325a8aec26980/packages/nuxt/src/core/runtime/nitro/renderer.ts#L28), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38), [islandContext](https://github.com/nuxt/nuxt/blob/e50cabfed1984c341af0d0c056a325a8aec26980/packages/nuxt/src/core/runtime/nitro/renderer.ts#L38)
|
`render:island` | `islandResponse, { event, islandContext }` | Called before constructing the island HTML. | [islandResponse](https://github.com/nuxt/nuxt/blob/e50cabfed1984c341af0d0c056a325a8aec26980/packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts#L28), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38), [islandContext](https://github.com/nuxt/nuxt/blob/e50cabfed1984c341af0d0c056a325a8aec26980/packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts#L38)
|
||||||
`close` | - | Called when Nitro is closed. | -
|
`close` | - | Called when Nitro is closed. | -
|
||||||
`error` | `error, { event? }` | Called when an error occurs. | [error](https://github.com/nitrojs/nitro/blob/d20ffcbd16fc4003b774445e1a01e698c2bb078a/src/types/runtime/nitro.ts#L48), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
|
`error` | `error, { event? }` | Called when an error occurs. | [error](https://github.com/nitrojs/nitro/blob/d20ffcbd16fc4003b774445e1a01e698c2bb078a/src/types/runtime/nitro.ts#L48), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
|
||||||
`request` | `event` | Called when a request is received. | [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
|
`request` | `event` | Called when a request is received. | [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
|
||||||
|
@ -21,7 +21,7 @@ export default createConfigForNuxt({
|
|||||||
'packages/schema/schema/**',
|
'packages/schema/schema/**',
|
||||||
'packages/nuxt/src/app/components/welcome.vue',
|
'packages/nuxt/src/app/components/welcome.vue',
|
||||||
'packages/nuxt/src/app/components/error-*.vue',
|
'packages/nuxt/src/app/components/error-*.vue',
|
||||||
'packages/nuxt/src/core/runtime/nitro/error-*',
|
'packages/nuxt/src/core/runtime/nitro/handlers/error-*',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
4
packages/nuxt/.gitignore
vendored
4
packages/nuxt/.gitignore
vendored
@ -2,5 +2,5 @@ src/app/components/error-404.vue
|
|||||||
src/app/components/error-500.vue
|
src/app/components/error-500.vue
|
||||||
src/app/components/error-dev.vue
|
src/app/components/error-dev.vue
|
||||||
src/app/components/welcome.vue
|
src/app/components/welcome.vue
|
||||||
src/core/runtime/nitro/error-500.ts
|
src/core/runtime/nitro/handlers/error-500.ts
|
||||||
src/core/runtime/nitro/error-dev.ts
|
src/core/runtime/nitro/handlers/error-dev.ts
|
||||||
|
@ -4,4 +4,4 @@ export interface NuxtAppLiterals {
|
|||||||
[key: string]: string
|
[key: string]: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { NuxtIslandContext, NuxtIslandResponse, NuxtRenderHTMLContext } from '../core/runtime/nitro/renderer'
|
export type { NuxtIslandContext, NuxtIslandResponse, NuxtRenderHTMLContext } from '../core/runtime/nitro/handlers/renderer'
|
||||||
|
@ -84,18 +84,18 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
{
|
{
|
||||||
as: '__buildAssetsURL',
|
as: '__buildAssetsURL',
|
||||||
name: 'buildAssetsURL',
|
name: 'buildAssetsURL',
|
||||||
from: resolve(distDir, 'core/runtime/nitro/paths'),
|
from: resolve(distDir, 'core/runtime/nitro/utils/paths'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
as: '__publicAssetsURL',
|
as: '__publicAssetsURL',
|
||||||
name: 'publicAssetsURL',
|
name: 'publicAssetsURL',
|
||||||
from: resolve(distDir, 'core/runtime/nitro/paths'),
|
from: resolve(distDir, 'core/runtime/nitro/utils/paths'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// TODO: Remove after https://github.com/nitrojs/nitro/issues/1049
|
// TODO: Remove after https://github.com/nitrojs/nitro/issues/1049
|
||||||
as: 'defineAppConfig',
|
as: 'defineAppConfig',
|
||||||
name: 'defineAppConfig',
|
name: 'defineAppConfig',
|
||||||
from: resolve(distDir, 'core/runtime/nitro/config'),
|
from: resolve(distDir, 'core/runtime/nitro/utils/config'),
|
||||||
priority: -1,
|
priority: -1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -112,7 +112,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
}
|
}
|
||||||
: false,
|
: false,
|
||||||
scanDirs: nuxt.options._layers.map(layer => (layer.config.serverDir || layer.config.srcDir) && resolve(layer.cwd, layer.config.serverDir || resolve(layer.config.srcDir, 'server'))).filter(Boolean),
|
scanDirs: nuxt.options._layers.map(layer => (layer.config.serverDir || layer.config.srcDir) && resolve(layer.cwd, layer.config.serverDir || resolve(layer.config.srcDir, 'server'))).filter(Boolean),
|
||||||
renderer: resolve(distDir, 'core/runtime/nitro/renderer'),
|
renderer: resolve(distDir, 'core/runtime/nitro/handlers/renderer'),
|
||||||
nodeModulesDirs: nuxt.options.modulesDir,
|
nodeModulesDirs: nuxt.options.modulesDir,
|
||||||
handlers: nuxt.options.serverHandlers,
|
handlers: nuxt.options.serverHandlers,
|
||||||
devHandlers: [],
|
devHandlers: [],
|
||||||
@ -210,7 +210,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
...nuxt.options.alias,
|
...nuxt.options.alias,
|
||||||
|
|
||||||
// Paths
|
// Paths
|
||||||
'#internal/nuxt/paths': resolve(distDir, 'core/runtime/nitro/paths'),
|
'#internal/nuxt/paths': resolve(distDir, 'core/runtime/nitro/utils/paths'),
|
||||||
},
|
},
|
||||||
replace: {
|
replace: {
|
||||||
'process.env.NUXT_NO_SSR': nuxt.options.ssr === false,
|
'process.env.NUXT_NO_SSR': nuxt.options.ssr === false,
|
||||||
@ -234,13 +234,13 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
nitroConfig.imports.imports ||= []
|
nitroConfig.imports.imports ||= []
|
||||||
nitroConfig.imports.imports.push({
|
nitroConfig.imports.imports.push({
|
||||||
name: 'useAppConfig',
|
name: 'useAppConfig',
|
||||||
from: resolve(distDir, 'core/runtime/nitro/app-config'),
|
from: resolve(distDir, 'core/runtime/nitro/utils/app-config'),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// add error handler
|
// add error handler
|
||||||
if (!nitroConfig.errorHandler && (nuxt.options.dev || !nuxt.options.experimental.noVueServer)) {
|
if (!nitroConfig.errorHandler && (nuxt.options.dev || !nuxt.options.experimental.noVueServer)) {
|
||||||
nitroConfig.errorHandler = resolve(distDir, 'core/runtime/nitro/error')
|
nitroConfig.errorHandler = resolve(distDir, 'core/runtime/nitro/handlers/error')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve user-provided paths
|
// Resolve user-provided paths
|
||||||
@ -421,7 +421,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
ImpoundPlugin.rollup({
|
ImpoundPlugin.rollup({
|
||||||
cwd: nuxt.options.rootDir,
|
cwd: nuxt.options.rootDir,
|
||||||
patterns: createImportProtectionPatterns(nuxt, { context: 'nitro-app' }),
|
patterns: createImportProtectionPatterns(nuxt, { context: 'nitro-app' }),
|
||||||
exclude: [/core[\\/]runtime[\\/]nitro[\\/]renderer/, ...sharedPatterns],
|
exclude: [/core[\\/]runtime[\\/]nitro[\\/](?:handlers|utils)/, ...sharedPatterns],
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -443,7 +443,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const cacheDir = resolve(nuxt.options.buildDir, 'cache/nitro/prerender')
|
const cacheDir = resolve(nuxt.options.buildDir, 'cache/nitro/prerender')
|
||||||
const cacheDriverPath = join(distDir, 'core/runtime/nitro/cache-driver.js')
|
const cacheDriverPath = join(distDir, 'core/runtime/nitro/utils/cache-driver.js')
|
||||||
await fsp.rm(cacheDir, { recursive: true, force: true }).catch(() => {})
|
await fsp.rm(cacheDir, { recursive: true, force: true }).catch(() => {})
|
||||||
nitro.options._config.storage = defu(nitro.options._config.storage, {
|
nitro.options._config.storage = defu(nitro.options._config.storage, {
|
||||||
'internal:nuxt:prerender': {
|
'internal:nuxt:prerender': {
|
||||||
@ -506,13 +506,13 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
nitro.options.handlers.unshift({
|
nitro.options.handlers.unshift({
|
||||||
route: '/__nuxt_error',
|
route: '/__nuxt_error',
|
||||||
lazy: true,
|
lazy: true,
|
||||||
handler: resolve(distDir, 'core/runtime/nitro/renderer'),
|
handler: resolve(distDir, 'core/runtime/nitro/handlers/renderer'),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!nuxt.options.dev && nuxt.options.experimental.noVueServer) {
|
if (!nuxt.options.dev && nuxt.options.experimental.noVueServer) {
|
||||||
nitro.hooks.hook('rollup:before', (nitro) => {
|
nitro.hooks.hook('rollup:before', (nitro) => {
|
||||||
if (nitro.options.preset === 'nitro-prerender') {
|
if (nitro.options.preset === 'nitro-prerender') {
|
||||||
nitro.options.errorHandler = resolve(distDir, 'core/runtime/nitro/error')
|
nitro.options.errorHandler = resolve(distDir, 'core/runtime/nitro/handlers/error')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const nuxtErrorHandler = nitro.options.handlers.findIndex(h => h.route === '/__nuxt_error')
|
const nuxtErrorHandler = nitro.options.handlers.findIndex(h => h.route === '/__nuxt_error')
|
||||||
|
@ -431,7 +431,7 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
|
|
||||||
if (nuxt.options.dev && nuxt.options.features.devLogs) {
|
if (nuxt.options.dev && nuxt.options.features.devLogs) {
|
||||||
addPlugin(resolve(nuxt.options.appDir, 'plugins/dev-server-logs'))
|
addPlugin(resolve(nuxt.options.appDir, 'plugins/dev-server-logs'))
|
||||||
addServerPlugin(resolve(distDir, 'core/runtime/nitro/dev-server-logs'))
|
addServerPlugin(resolve(distDir, 'core/runtime/nitro/plugins/dev-server-logs'))
|
||||||
nuxt.options.nitro = defu(nuxt.options.nitro, {
|
nuxt.options.nitro = defu(nuxt.options.nitro, {
|
||||||
externals: {
|
externals: {
|
||||||
inline: [/#internal\/dev-server-logs-options/],
|
inline: [/#internal\/dev-server-logs-options/],
|
||||||
|
@ -1,36 +1,34 @@
|
|||||||
import { AsyncLocalStorage } from 'node:async_hooks'
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
||||||
import {
|
import {
|
||||||
createRenderer,
|
|
||||||
getPrefetchLinks,
|
getPrefetchLinks,
|
||||||
getPreloadLinks,
|
getPreloadLinks,
|
||||||
getRequestDependencies,
|
getRequestDependencies,
|
||||||
renderResourceHeaders,
|
renderResourceHeaders,
|
||||||
} from 'vue-bundle-renderer/runtime'
|
} from 'vue-bundle-renderer/runtime'
|
||||||
import type { Manifest as ClientManifest } from 'vue-bundle-renderer'
|
|
||||||
import type { RenderResponse } from 'nitro/types'
|
import type { RenderResponse } from 'nitro/types'
|
||||||
import type { Manifest } from 'vite'
|
|
||||||
import type { H3Event } from 'h3'
|
import type { H3Event } from 'h3'
|
||||||
import { appendResponseHeader, createError, getQuery, getResponseStatus, getResponseStatusText, readBody, writeEarlyHints } from 'h3'
|
import { appendResponseHeader, createError, getQuery, getResponseStatus, getResponseStatusText, readBody, writeEarlyHints } from 'h3'
|
||||||
import devalue from '@nuxt/devalue'
|
|
||||||
import { stringify, uneval } from 'devalue'
|
|
||||||
import destr from 'destr'
|
import destr from 'destr'
|
||||||
import { getQuery as getURLQuery, joinURL, withoutTrailingSlash } from 'ufo'
|
import { getQuery as getURLQuery, joinURL, withoutTrailingSlash } from 'ufo'
|
||||||
import { renderToString as _renderToString } from 'vue/server-renderer'
|
|
||||||
import { propsToString, renderSSRHead } from '@unhead/ssr'
|
import { propsToString, renderSSRHead } from '@unhead/ssr'
|
||||||
import type { Head, HeadEntryOptions } from '@unhead/schema'
|
import type { Head, HeadEntryOptions } from '@unhead/schema'
|
||||||
import type { Link, Script, Style } from '@unhead/vue'
|
import type { Link, Script, Style } from '@unhead/vue'
|
||||||
import { createServerHead, resolveUnrefHeadInput } from '@unhead/vue'
|
import { createServerHead, resolveUnrefHeadInput } from '@unhead/vue'
|
||||||
|
|
||||||
import { defineRenderHandler, getRouteRules, useNitroApp, useRuntimeConfig, useStorage } from 'nitro/runtime'
|
import { defineRenderHandler, getRouteRules, useNitroApp, useRuntimeConfig } from 'nitro/runtime'
|
||||||
import type { NuxtPayload, NuxtSSRContext } from 'nuxt/app'
|
import type { NuxtPayload, NuxtSSRContext } from 'nuxt/app'
|
||||||
|
|
||||||
|
import { getEntryIds, getSPARenderer, getSSRRenderer, getSSRStyles } from '../utils/build-files'
|
||||||
|
import { islandCache, islandPropCache, payloadCache, sharedPrerenderCache } from '../utils/cache'
|
||||||
|
|
||||||
|
import { renderPayloadJsonScript, renderPayloadResponse, renderPayloadScript, splitPayload } from '../utils/payload'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import unheadPlugins from '#internal/unhead-plugins.mjs'
|
import unheadPlugins from '#internal/unhead-plugins.mjs'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { renderSSRHeadOptions } from '#internal/unhead.config.mjs'
|
import { renderSSRHeadOptions } from '#internal/unhead.config.mjs'
|
||||||
|
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { appHead, appId, appRootAttrs, appRootTag, appSpaLoaderAttrs, appSpaLoaderTag, appTeleportAttrs, appTeleportTag, componentIslands, appManifest as isAppManifestEnabled, multiApp, spaLoadingTemplateOutside } from '#internal/nuxt.config.mjs'
|
import { appHead, appRootTag, appTeleportAttrs, appTeleportTag, componentIslands, appManifest as isAppManifestEnabled } from '#internal/nuxt.config.mjs'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { buildAssetsURL, publicAssetsURL } from '#internal/nuxt/paths'
|
import { buildAssetsURL, publicAssetsURL } from '#internal/nuxt/paths'
|
||||||
|
|
||||||
@ -91,119 +89,6 @@ export interface NuxtRenderResponse {
|
|||||||
headers: Record<string, string>
|
headers: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error file will be produced after app build
|
|
||||||
const getClientManifest: () => Promise<Manifest> = () => import('#build/dist/server/client.manifest.mjs')
|
|
||||||
.then(r => r.default || r)
|
|
||||||
.then(r => typeof r === 'function' ? r() : r) as Promise<ClientManifest>
|
|
||||||
|
|
||||||
const getEntryIds: () => Promise<string[]> = () => getClientManifest().then(r => Object.values(r).filter(r =>
|
|
||||||
// @ts-expect-error internal key set by CSS inlining configuration
|
|
||||||
r._globalCSS,
|
|
||||||
).map(r => r.src!))
|
|
||||||
|
|
||||||
// @ts-expect-error file will be produced after app build
|
|
||||||
const getServerEntry = () => import('#build/dist/server/server.mjs').then(r => r.default || r)
|
|
||||||
|
|
||||||
// @ts-expect-error file will be produced after app build
|
|
||||||
const getSSRStyles = lazyCachedFunction((): Promise<Record<string, () => Promise<string[]>>> => import('#build/dist/server/styles.mjs').then(r => r.default || r))
|
|
||||||
|
|
||||||
// -- SSR Renderer --
|
|
||||||
const getSSRRenderer = lazyCachedFunction(async () => {
|
|
||||||
// Load client manifest
|
|
||||||
const manifest = await getClientManifest()
|
|
||||||
if (!manifest) { throw new Error('client.manifest is not available') }
|
|
||||||
|
|
||||||
// Load server bundle
|
|
||||||
const createSSRApp = await getServerEntry()
|
|
||||||
if (!createSSRApp) { throw new Error('Server bundle is not available') }
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
manifest,
|
|
||||||
renderToString,
|
|
||||||
buildAssetsURL,
|
|
||||||
}
|
|
||||||
// Create renderer
|
|
||||||
const renderer = createRenderer(createSSRApp, options)
|
|
||||||
|
|
||||||
type RenderToStringParams = Parameters<typeof _renderToString>
|
|
||||||
async function renderToString (input: RenderToStringParams[0], context: RenderToStringParams[1]) {
|
|
||||||
const html = await _renderToString(input, context)
|
|
||||||
// In development with vite-node, the manifest is on-demand and will be available after rendering
|
|
||||||
if (import.meta.dev && process.env.NUXT_VITE_NODE_OPTIONS) {
|
|
||||||
renderer.rendererContext.updateManifest(await getClientManifest())
|
|
||||||
}
|
|
||||||
return APP_ROOT_OPEN_TAG + html + APP_ROOT_CLOSE_TAG
|
|
||||||
}
|
|
||||||
|
|
||||||
return renderer
|
|
||||||
})
|
|
||||||
|
|
||||||
// -- SPA Renderer --
|
|
||||||
const getSPARenderer = lazyCachedFunction(async () => {
|
|
||||||
const manifest = await getClientManifest()
|
|
||||||
|
|
||||||
// @ts-expect-error virtual file
|
|
||||||
const spaTemplate = await import('#spa-template').then(r => r.template).catch(() => '')
|
|
||||||
.then((r) => {
|
|
||||||
if (spaLoadingTemplateOutside) {
|
|
||||||
const APP_SPA_LOADER_OPEN_TAG = `<${appSpaLoaderTag}${propsToString(appSpaLoaderAttrs)}>`
|
|
||||||
const APP_SPA_LOADER_CLOSE_TAG = `</${appSpaLoaderTag}>`
|
|
||||||
const appTemplate = APP_ROOT_OPEN_TAG + APP_ROOT_CLOSE_TAG
|
|
||||||
const loaderTemplate = r ? APP_SPA_LOADER_OPEN_TAG + r + APP_SPA_LOADER_CLOSE_TAG : ''
|
|
||||||
return appTemplate + loaderTemplate
|
|
||||||
} else {
|
|
||||||
return APP_ROOT_OPEN_TAG + r + APP_ROOT_CLOSE_TAG
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
manifest,
|
|
||||||
renderToString: () => spaTemplate,
|
|
||||||
buildAssetsURL,
|
|
||||||
}
|
|
||||||
// Create SPA renderer and cache the result for all requests
|
|
||||||
const renderer = createRenderer(() => () => {}, options)
|
|
||||||
const result = await renderer.renderToString({})
|
|
||||||
|
|
||||||
const renderToString = (ssrContext: NuxtSSRContext) => {
|
|
||||||
const config = useRuntimeConfig(ssrContext.event)
|
|
||||||
ssrContext.modules ||= new Set<string>()
|
|
||||||
ssrContext.payload.serverRendered = false
|
|
||||||
ssrContext.config = {
|
|
||||||
public: config.public,
|
|
||||||
app: config.app,
|
|
||||||
}
|
|
||||||
return Promise.resolve(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
rendererContext: renderer.rendererContext,
|
|
||||||
renderToString,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const payloadCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:payload') : null
|
|
||||||
const islandCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:island') : null
|
|
||||||
const islandPropCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:island-props') : null
|
|
||||||
const sharedPrerenderPromises = import.meta.prerender && process.env.NUXT_SHARED_DATA ? new Map<string, Promise<any>>() : null
|
|
||||||
const sharedPrerenderKeys = new Set<string>()
|
|
||||||
const sharedPrerenderCache = import.meta.prerender && process.env.NUXT_SHARED_DATA
|
|
||||||
? {
|
|
||||||
get<T = unknown> (key: string): Promise<T> | undefined {
|
|
||||||
if (sharedPrerenderKeys.has(key)) {
|
|
||||||
return sharedPrerenderPromises!.get(key) ?? useStorage('internal:nuxt:prerender:shared').getItem(key) as Promise<T>
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async set<T> (key: string, value: Promise<T>): Promise<void> {
|
|
||||||
sharedPrerenderKeys.add(key)
|
|
||||||
sharedPrerenderPromises!.set(key, value)
|
|
||||||
useStorage('internal:nuxt:prerender:shared').setItem(key, await value as any)
|
|
||||||
// free up memory after the promise is resolved
|
|
||||||
.finally(() => sharedPrerenderPromises!.delete(key))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: null
|
|
||||||
|
|
||||||
const ISLAND_SUFFIX_RE = /\.json(\?.*)?$/
|
const ISLAND_SUFFIX_RE = /\.json(\?.*)?$/
|
||||||
async function getIslandContext (event: H3Event): Promise<NuxtIslandContext> {
|
async function getIslandContext (event: H3Event): Promise<NuxtIslandContext> {
|
||||||
// TODO: Strict validation for url
|
// TODO: Strict validation for url
|
||||||
@ -236,9 +121,6 @@ const HAS_APP_TELEPORTS = !!(appTeleportTag && appTeleportAttrs.id)
|
|||||||
const APP_TELEPORT_OPEN_TAG = HAS_APP_TELEPORTS ? `<${appTeleportTag}${propsToString(appTeleportAttrs)}>` : ''
|
const APP_TELEPORT_OPEN_TAG = HAS_APP_TELEPORTS ? `<${appTeleportTag}${propsToString(appTeleportAttrs)}>` : ''
|
||||||
const APP_TELEPORT_CLOSE_TAG = HAS_APP_TELEPORTS ? `</${appTeleportTag}>` : ''
|
const APP_TELEPORT_CLOSE_TAG = HAS_APP_TELEPORTS ? `</${appTeleportTag}>` : ''
|
||||||
|
|
||||||
const APP_ROOT_OPEN_TAG = `<${appRootTag}${propsToString(appRootAttrs)}>`
|
|
||||||
const APP_ROOT_CLOSE_TAG = `</${appRootTag}>`
|
|
||||||
|
|
||||||
const PAYLOAD_URL_RE = process.env.NUXT_JSON_PAYLOADS ? /\/_payload.json(\?.*)?$/ : /\/_payload.js(\?.*)?$/
|
const PAYLOAD_URL_RE = process.env.NUXT_JSON_PAYLOADS ? /\/_payload.json(\?.*)?$/ : /\/_payload.js(\?.*)?$/
|
||||||
const ROOT_NODE_REGEX = new RegExp(`^<${appRootTag}[^>]*>([\\s\\S]*)<\\/${appRootTag}>$`)
|
const ROOT_NODE_REGEX = new RegExp(`^<${appRootTag}[^>]*>([\\s\\S]*)<\\/${appRootTag}>$`)
|
||||||
|
|
||||||
@ -548,16 +430,6 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
return response
|
return response
|
||||||
})
|
})
|
||||||
|
|
||||||
function lazyCachedFunction<T> (fn: () => Promise<T>): () => Promise<T> {
|
|
||||||
let res: Promise<T> | null = null
|
|
||||||
return () => {
|
|
||||||
if (res === null) {
|
|
||||||
res = fn().catch((err) => { res = null; throw err })
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeChunks (chunks: (string | undefined)[]) {
|
function normalizeChunks (chunks: (string | undefined)[]) {
|
||||||
return chunks.filter(Boolean).map(i => i!.trim())
|
return chunks.filter(Boolean).map(i => i!.trim())
|
||||||
}
|
}
|
||||||
@ -592,76 +464,6 @@ async function renderInlineStyles (usedModules: Set<string> | string[]): Promise
|
|||||||
return Array.from(inlinedStyles).map(style => ({ innerHTML: style }))
|
return Array.from(inlinedStyles).map(style => ({ innerHTML: style }))
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPayloadResponse (ssrContext: NuxtSSRContext) {
|
|
||||||
return {
|
|
||||||
body: process.env.NUXT_JSON_PAYLOADS
|
|
||||||
? stringify(splitPayload(ssrContext).payload, ssrContext._payloadReducers)
|
|
||||||
: `export default ${devalue(splitPayload(ssrContext).payload)}`,
|
|
||||||
statusCode: getResponseStatus(ssrContext.event),
|
|
||||||
statusMessage: getResponseStatusText(ssrContext.event),
|
|
||||||
headers: {
|
|
||||||
'content-type': process.env.NUXT_JSON_PAYLOADS ? 'application/json;charset=utf-8' : 'text/javascript;charset=utf-8',
|
|
||||||
'x-powered-by': 'Nuxt',
|
|
||||||
},
|
|
||||||
} satisfies RenderResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderPayloadJsonScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
|
||||||
const contents = opts.data ? stringify(opts.data, opts.ssrContext._payloadReducers) : ''
|
|
||||||
const payload: Script = {
|
|
||||||
'type': 'application/json',
|
|
||||||
'innerHTML': contents,
|
|
||||||
'data-nuxt-data': appId,
|
|
||||||
'data-ssr': !(process.env.NUXT_NO_SSR || opts.ssrContext.noSSR),
|
|
||||||
}
|
|
||||||
if (!multiApp) {
|
|
||||||
payload.id = '__NUXT_DATA__'
|
|
||||||
}
|
|
||||||
if (opts.src) {
|
|
||||||
payload['data-src'] = opts.src
|
|
||||||
}
|
|
||||||
const config = uneval(opts.ssrContext.config)
|
|
||||||
return [
|
|
||||||
payload,
|
|
||||||
{
|
|
||||||
innerHTML: multiApp
|
|
||||||
? `window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]={config:${config}}`
|
|
||||||
: `window.__NUXT__={};window.__NUXT__.config=${config}`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderPayloadScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
|
||||||
opts.data.config = opts.ssrContext.config
|
|
||||||
const _PAYLOAD_EXTRACTION = import.meta.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !opts.ssrContext.noSSR
|
|
||||||
const nuxtData = devalue(opts.data)
|
|
||||||
if (_PAYLOAD_EXTRACTION) {
|
|
||||||
const singleAppPayload = `import p from "${opts.src}";window.__NUXT__={...p,...(${nuxtData})}`
|
|
||||||
const multiAppPayload = `import p from "${opts.src}";window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]={...p,...(${nuxtData})}`
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
type: 'module',
|
|
||||||
innerHTML: multiApp ? multiAppPayload : singleAppPayload,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const singleAppPayload = `window.__NUXT__=${nuxtData}`
|
|
||||||
const multiAppPayload = `window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]=${nuxtData}`
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
innerHTML: multiApp ? multiAppPayload : singleAppPayload,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
function splitPayload (ssrContext: NuxtSSRContext) {
|
|
||||||
const { data, prerenderedAt, ...initial } = ssrContext.payload
|
|
||||||
return {
|
|
||||||
initial: { ...initial, prerenderedAt },
|
|
||||||
payload: { data, prerenderedAt },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* remove the root node from the html body
|
* remove the root node from the html body
|
||||||
*/
|
*/
|
119
packages/nuxt/src/core/runtime/nitro/utils/build-files.ts
Normal file
119
packages/nuxt/src/core/runtime/nitro/utils/build-files.ts
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import {
|
||||||
|
createRenderer,
|
||||||
|
} from 'vue-bundle-renderer/runtime'
|
||||||
|
import type { Manifest as ClientManifest } from 'vue-bundle-renderer'
|
||||||
|
import type { Manifest } from 'vite'
|
||||||
|
import { renderToString as _renderToString } from 'vue/server-renderer'
|
||||||
|
import { propsToString } from '@unhead/ssr'
|
||||||
|
|
||||||
|
import { useRuntimeConfig } from 'nitro/runtime'
|
||||||
|
import type { NuxtSSRContext } from 'nuxt/app'
|
||||||
|
|
||||||
|
// @ts-expect-error virtual file
|
||||||
|
import { appRootAttrs, appRootTag, appSpaLoaderAttrs, appSpaLoaderTag, spaLoadingTemplateOutside } from '#internal/nuxt.config.mjs'
|
||||||
|
// @ts-expect-error virtual file
|
||||||
|
import { buildAssetsURL } from '#internal/nuxt/paths'
|
||||||
|
|
||||||
|
const APP_ROOT_OPEN_TAG = `<${appRootTag}${propsToString(appRootAttrs)}>`
|
||||||
|
const APP_ROOT_CLOSE_TAG = `</${appRootTag}>`
|
||||||
|
|
||||||
|
// @ts-expect-error file will be produced after app build
|
||||||
|
export const getClientManifest: () => Promise<Manifest> = () => import('#build/dist/server/client.manifest.mjs')
|
||||||
|
.then(r => r.default || r)
|
||||||
|
.then(r => typeof r === 'function' ? r() : r) as Promise<ClientManifest>
|
||||||
|
|
||||||
|
export const getEntryIds: () => Promise<string[]> = () => getClientManifest().then(r => Object.values(r).filter(r =>
|
||||||
|
// @ts-expect-error internal key set by CSS inlining configuration
|
||||||
|
r._globalCSS,
|
||||||
|
).map(r => r.src!))
|
||||||
|
|
||||||
|
// @ts-expect-error file will be produced after app build
|
||||||
|
export const getServerEntry = () => import('#build/dist/server/server.mjs').then(r => r.default || r)
|
||||||
|
|
||||||
|
// @ts-expect-error file will be produced after app build
|
||||||
|
export const getSSRStyles = lazyCachedFunction((): Promise<Record<string, () => Promise<string[]>>> => import('#build/dist/server/styles.mjs').then(r => r.default || r))
|
||||||
|
|
||||||
|
// -- SSR Renderer --
|
||||||
|
export const getSSRRenderer = lazyCachedFunction(async () => {
|
||||||
|
// Load client manifest
|
||||||
|
const manifest = await getClientManifest()
|
||||||
|
if (!manifest) { throw new Error('client.manifest is not available') }
|
||||||
|
|
||||||
|
// Load server bundle
|
||||||
|
const createSSRApp = await getServerEntry()
|
||||||
|
if (!createSSRApp) { throw new Error('Server bundle is not available') }
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
manifest,
|
||||||
|
renderToString,
|
||||||
|
buildAssetsURL,
|
||||||
|
}
|
||||||
|
// Create renderer
|
||||||
|
const renderer = createRenderer(createSSRApp, options)
|
||||||
|
|
||||||
|
type RenderToStringParams = Parameters<typeof _renderToString>
|
||||||
|
async function renderToString (input: RenderToStringParams[0], context: RenderToStringParams[1]) {
|
||||||
|
const html = await _renderToString(input, context)
|
||||||
|
// In development with vite-node, the manifest is on-demand and will be available after rendering
|
||||||
|
if (import.meta.dev && process.env.NUXT_VITE_NODE_OPTIONS) {
|
||||||
|
renderer.rendererContext.updateManifest(await getClientManifest())
|
||||||
|
}
|
||||||
|
return APP_ROOT_OPEN_TAG + html + APP_ROOT_CLOSE_TAG
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderer
|
||||||
|
})
|
||||||
|
|
||||||
|
// -- SPA Renderer --
|
||||||
|
export const getSPARenderer = lazyCachedFunction(async () => {
|
||||||
|
const manifest = await getClientManifest()
|
||||||
|
|
||||||
|
// @ts-expect-error virtual file
|
||||||
|
const spaTemplate = await import('#spa-template').then(r => r.template).catch(() => '')
|
||||||
|
.then((r) => {
|
||||||
|
if (spaLoadingTemplateOutside) {
|
||||||
|
const APP_SPA_LOADER_OPEN_TAG = `<${appSpaLoaderTag}${propsToString(appSpaLoaderAttrs)}>`
|
||||||
|
const APP_SPA_LOADER_CLOSE_TAG = `</${appSpaLoaderTag}>`
|
||||||
|
const appTemplate = APP_ROOT_OPEN_TAG + APP_ROOT_CLOSE_TAG
|
||||||
|
const loaderTemplate = r ? APP_SPA_LOADER_OPEN_TAG + r + APP_SPA_LOADER_CLOSE_TAG : ''
|
||||||
|
return appTemplate + loaderTemplate
|
||||||
|
} else {
|
||||||
|
return APP_ROOT_OPEN_TAG + r + APP_ROOT_CLOSE_TAG
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
manifest,
|
||||||
|
renderToString: () => spaTemplate,
|
||||||
|
buildAssetsURL,
|
||||||
|
}
|
||||||
|
// Create SPA renderer and cache the result for all requests
|
||||||
|
const renderer = createRenderer(() => () => {}, options)
|
||||||
|
const result = await renderer.renderToString({})
|
||||||
|
|
||||||
|
const renderToString = (ssrContext: NuxtSSRContext) => {
|
||||||
|
const config = useRuntimeConfig(ssrContext.event)
|
||||||
|
ssrContext.modules ||= new Set<string>()
|
||||||
|
ssrContext.payload.serverRendered = false
|
||||||
|
ssrContext.config = {
|
||||||
|
public: config.public,
|
||||||
|
app: config.app,
|
||||||
|
}
|
||||||
|
return Promise.resolve(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
rendererContext: renderer.rendererContext,
|
||||||
|
renderToString,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function lazyCachedFunction<T> (fn: () => Promise<T>): () => Promise<T> {
|
||||||
|
let res: Promise<T> | null = null
|
||||||
|
return () => {
|
||||||
|
if (res === null) {
|
||||||
|
res = fn().catch((err) => { res = null; throw err })
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
24
packages/nuxt/src/core/runtime/nitro/utils/cache.ts
Normal file
24
packages/nuxt/src/core/runtime/nitro/utils/cache.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { useStorage } from 'nitro/runtime'
|
||||||
|
|
||||||
|
export const payloadCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:payload') : null
|
||||||
|
export const islandCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:island') : null
|
||||||
|
export const islandPropCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:island-props') : null
|
||||||
|
export const sharedPrerenderPromises = import.meta.prerender && process.env.NUXT_SHARED_DATA ? new Map<string, Promise<any>>() : null
|
||||||
|
|
||||||
|
const sharedPrerenderKeys = new Set<string>()
|
||||||
|
export const sharedPrerenderCache = import.meta.prerender && process.env.NUXT_SHARED_DATA
|
||||||
|
? {
|
||||||
|
get<T = unknown> (key: string): Promise<T> | undefined {
|
||||||
|
if (sharedPrerenderKeys.has(key)) {
|
||||||
|
return sharedPrerenderPromises!.get(key) ?? useStorage('internal:nuxt:prerender:shared').getItem(key) as Promise<T>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async set<T> (key: string, value: Promise<T>): Promise<void> {
|
||||||
|
sharedPrerenderKeys.add(key)
|
||||||
|
sharedPrerenderPromises!.set(key, value)
|
||||||
|
useStorage('internal:nuxt:prerender:shared').setItem(key, await value as any)
|
||||||
|
// free up memory after the promise is resolved
|
||||||
|
.finally(() => sharedPrerenderPromises!.delete(key))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: null
|
80
packages/nuxt/src/core/runtime/nitro/utils/payload.ts
Normal file
80
packages/nuxt/src/core/runtime/nitro/utils/payload.ts
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import type { RenderResponse } from 'nitro/types'
|
||||||
|
import { getResponseStatus, getResponseStatusText } from 'h3'
|
||||||
|
import devalue from '@nuxt/devalue'
|
||||||
|
import { stringify, uneval } from 'devalue'
|
||||||
|
import type { Script } from '@unhead/vue'
|
||||||
|
|
||||||
|
import type { NuxtSSRContext } from 'nuxt/app'
|
||||||
|
|
||||||
|
// @ts-expect-error virtual file
|
||||||
|
import { appId, multiApp } from '#internal/nuxt.config.mjs'
|
||||||
|
|
||||||
|
export function renderPayloadResponse (ssrContext: NuxtSSRContext) {
|
||||||
|
return {
|
||||||
|
body: process.env.NUXT_JSON_PAYLOADS
|
||||||
|
? stringify(splitPayload(ssrContext).payload, ssrContext._payloadReducers)
|
||||||
|
: `export default ${devalue(splitPayload(ssrContext).payload)}`,
|
||||||
|
statusCode: getResponseStatus(ssrContext.event),
|
||||||
|
statusMessage: getResponseStatusText(ssrContext.event),
|
||||||
|
headers: {
|
||||||
|
'content-type': process.env.NUXT_JSON_PAYLOADS ? 'application/json;charset=utf-8' : 'text/javascript;charset=utf-8',
|
||||||
|
'x-powered-by': 'Nuxt',
|
||||||
|
},
|
||||||
|
} satisfies RenderResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderPayloadJsonScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
||||||
|
const contents = opts.data ? stringify(opts.data, opts.ssrContext._payloadReducers) : ''
|
||||||
|
const payload: Script = {
|
||||||
|
'type': 'application/json',
|
||||||
|
'innerHTML': contents,
|
||||||
|
'data-nuxt-data': appId,
|
||||||
|
'data-ssr': !(process.env.NUXT_NO_SSR || opts.ssrContext.noSSR),
|
||||||
|
}
|
||||||
|
if (!multiApp) {
|
||||||
|
payload.id = '__NUXT_DATA__'
|
||||||
|
}
|
||||||
|
if (opts.src) {
|
||||||
|
payload['data-src'] = opts.src
|
||||||
|
}
|
||||||
|
const config = uneval(opts.ssrContext.config)
|
||||||
|
return [
|
||||||
|
payload,
|
||||||
|
{
|
||||||
|
innerHTML: multiApp
|
||||||
|
? `window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]={config:${config}}`
|
||||||
|
: `window.__NUXT__={};window.__NUXT__.config=${config}`,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderPayloadScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
||||||
|
opts.data.config = opts.ssrContext.config
|
||||||
|
const _PAYLOAD_EXTRACTION = import.meta.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !opts.ssrContext.noSSR
|
||||||
|
const nuxtData = devalue(opts.data)
|
||||||
|
if (_PAYLOAD_EXTRACTION) {
|
||||||
|
const singleAppPayload = `import p from "${opts.src}";window.__NUXT__={...p,...(${nuxtData})}`
|
||||||
|
const multiAppPayload = `import p from "${opts.src}";window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]={...p,...(${nuxtData})}`
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: 'module',
|
||||||
|
innerHTML: multiApp ? multiAppPayload : singleAppPayload,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const singleAppPayload = `window.__NUXT__=${nuxtData}`
|
||||||
|
const multiAppPayload = `window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]=${nuxtData}`
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
innerHTML: multiApp ? multiAppPayload : singleAppPayload,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function splitPayload (ssrContext: NuxtSSRContext) {
|
||||||
|
const { data, prerenderedAt, ...initial } = ssrContext.payload
|
||||||
|
return {
|
||||||
|
initial: { ...initial, prerenderedAt },
|
||||||
|
payload: { data, prerenderedAt },
|
||||||
|
}
|
||||||
|
}
|
@ -483,7 +483,7 @@ export const publicPathTemplate: NuxtTemplate = {
|
|||||||
' return path.length ? joinRelativeURL(publicBase, ...path) : publicBase',
|
' return path.length ? joinRelativeURL(publicBase, ...path) : publicBase',
|
||||||
'}',
|
'}',
|
||||||
|
|
||||||
// On server these are registered directly in packages/nuxt/src/core/runtime/nitro/renderer.ts
|
// On server these are registered directly in packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts
|
||||||
'if (import.meta.client) {',
|
'if (import.meta.client) {',
|
||||||
' globalThis.__buildAssetsURL = buildAssetsURL',
|
' globalThis.__buildAssetsURL = buildAssetsURL',
|
||||||
' globalThis.__publicAssetsURL = publicAssetsURL',
|
' globalThis.__publicAssetsURL = publicAssetsURL',
|
||||||
|
@ -201,7 +201,7 @@ export const RenderPlugin = () => {
|
|||||||
await copyFile(r(`dist/templates/${file}`), join(nuxtRoot, 'src/app/components', file))
|
await copyFile(r(`dist/templates/${file}`), join(nuxtRoot, 'src/app/components', file))
|
||||||
}
|
}
|
||||||
for (const file of ['error-500.ts', 'error-dev.ts']) {
|
for (const file of ['error-500.ts', 'error-dev.ts']) {
|
||||||
await copyFile(r(`dist/templates/${file}`), join(nuxtRoot, 'src/core/runtime/nitro', file))
|
await copyFile(r(`dist/templates/${file}`), join(nuxtRoot, 'src/core/runtime/nitro/handlers', file))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -2426,7 +2426,7 @@ describe('component islands', () => {
|
|||||||
`)
|
`)
|
||||||
} else if (isDev() && !isWebpack) {
|
} else if (isDev() && !isWebpack) {
|
||||||
// TODO: resolve dev bug triggered by earlier fetch of /vueuse-head page
|
// TODO: resolve dev bug triggered by earlier fetch of /vueuse-head page
|
||||||
// https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/core/runtime/nitro/renderer.ts#L139
|
// https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/core/runtime/nitro/handlers/renderer.ts#L139
|
||||||
result.head.link = result.head.link?.filter(l => typeof l.href !== 'string' || !l.href.includes('SharedComponent'))
|
result.head.link = result.head.link?.filter(l => typeof l.href !== 'string' || !l.href.includes('SharedComponent'))
|
||||||
|
|
||||||
expect(result.head).toMatchInlineSnapshot(`
|
expect(result.head).toMatchInlineSnapshot(`
|
||||||
|
Loading…
Reference in New Issue
Block a user