@nuxt/nitro-server-nightly 4.3.0-29465977.c4f46c64 → 4.3.0-29466366.fa21bb17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +177 -177
- package/dist/index.mjs +664 -835
- package/dist/runtime/handlers/{error.d.ts → error.d.mts} +1 -1
- package/dist/runtime/handlers/error.mjs +77 -0
- package/dist/runtime/handlers/island.d.mts +2 -0
- package/dist/runtime/handlers/island.mjs +120 -0
- package/dist/runtime/handlers/renderer.d.mts +2 -0
- package/dist/runtime/handlers/renderer.mjs +298 -0
- package/dist/runtime/middleware/no-ssr.d.mts +2 -0
- package/dist/runtime/middleware/no-ssr.mjs +7 -0
- package/dist/runtime/plugins/dev-server-logs.d.mts +2 -0
- package/dist/runtime/plugins/dev-server-logs.mjs +94 -0
- package/dist/runtime/templates/error-500.mjs +15 -0
- package/dist/runtime/utils/app-config.d.mts +3 -0
- package/dist/runtime/utils/app-config.mjs +31 -0
- package/dist/runtime/utils/cache.d.mts +5 -0
- package/dist/runtime/utils/{cache.js → cache.mjs} +13 -12
- package/dist/runtime/utils/config.d.mts +1 -0
- package/dist/runtime/utils/{dev.d.ts → dev.d.mts} +1 -1
- package/dist/runtime/utils/{dev.js → dev.mjs} +15 -27
- package/dist/runtime/utils/error.d.mts +6 -0
- package/dist/runtime/utils/error.mjs +15 -0
- package/dist/runtime/utils/paths.mjs +19 -0
- package/dist/runtime/utils/renderer/{app.d.ts → app.d.mts} +4 -4
- package/dist/runtime/utils/renderer/app.mjs +39 -0
- package/dist/runtime/utils/renderer/build-files.d.mts +18 -0
- package/dist/runtime/utils/renderer/build-files.mjs +100 -0
- package/dist/runtime/utils/renderer/{inline-styles.d.ts → inline-styles.d.mts} +1 -1
- package/dist/runtime/utils/renderer/inline-styles.mjs +13 -0
- package/dist/runtime/utils/renderer/{islands.d.ts → islands.d.mts} +5 -5
- package/dist/runtime/utils/renderer/islands.mjs +87 -0
- package/dist/runtime/utils/renderer/payload.d.mts +24 -0
- package/dist/runtime/utils/renderer/payload.mjs +64 -0
- package/package.json +8 -8
- package/dist/index.d.ts +0 -185
- package/dist/runtime/handlers/error.js +0 -65
- package/dist/runtime/handlers/island.d.ts +0 -4
- package/dist/runtime/handlers/island.js +0 -101
- package/dist/runtime/handlers/renderer.d.ts +0 -2
- package/dist/runtime/handlers/renderer.js +0 -237
- package/dist/runtime/middleware/no-ssr.d.ts +0 -2
- package/dist/runtime/middleware/no-ssr.js +0 -7
- package/dist/runtime/plugins/dev-server-logs.d.ts +0 -3
- package/dist/runtime/plugins/dev-server-logs.js +0 -82
- package/dist/runtime/templates/error-500.js +0 -6
- package/dist/runtime/utils/app-config.d.ts +0 -3
- package/dist/runtime/utils/app-config.js +0 -25
- package/dist/runtime/utils/cache-driver.d.ts +0 -6
- package/dist/runtime/utils/cache.d.ts +0 -8
- package/dist/runtime/utils/config.d.ts +0 -1
- package/dist/runtime/utils/error.d.ts +0 -6
- package/dist/runtime/utils/error.js +0 -11
- package/dist/runtime/utils/paths.js +0 -16
- package/dist/runtime/utils/renderer/app.js +0 -34
- package/dist/runtime/utils/renderer/build-files.d.ts +0 -16
- package/dist/runtime/utils/renderer/build-files.js +0 -86
- package/dist/runtime/utils/renderer/inline-styles.js +0 -13
- package/dist/runtime/utils/renderer/islands.js +0 -82
- package/dist/runtime/utils/renderer/payload.d.ts +0 -24
- package/dist/runtime/utils/renderer/payload.js +0 -67
- /package/dist/runtime/templates/{error-500.d.ts → error-500.d.mts} +0 -0
- /package/dist/runtime/utils/{config.js → config.mjs} +0 -0
- /package/dist/runtime/utils/{paths.d.ts → paths.d.mts} +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { klona } from "klona";
|
|
2
|
+
// @ts-expect-error virtual file
|
|
3
|
+
import _inlineAppConfig from "#internal/nuxt/app-config";
|
|
4
|
+
// App config
|
|
5
|
+
const _sharedAppConfig = _deepFreeze(klona(_inlineAppConfig));
|
|
6
|
+
export function useAppConfig(event) {
|
|
7
|
+
// Backwards compatibility with ambient context
|
|
8
|
+
if (!event) {
|
|
9
|
+
return _sharedAppConfig;
|
|
10
|
+
}
|
|
11
|
+
event.context.nuxt ||= {};
|
|
12
|
+
// Reuse cached app config from event context
|
|
13
|
+
if (event.context.nuxt.appConfig) {
|
|
14
|
+
return event.context.nuxt.appConfig;
|
|
15
|
+
}
|
|
16
|
+
// Prepare app config for event context
|
|
17
|
+
const appConfig = klona(_inlineAppConfig);
|
|
18
|
+
event.context.nuxt.appConfig = appConfig;
|
|
19
|
+
return appConfig;
|
|
20
|
+
}
|
|
21
|
+
// --- Utils ---
|
|
22
|
+
function _deepFreeze(object) {
|
|
23
|
+
const propNames = Object.getOwnPropertyNames(object);
|
|
24
|
+
for (const name of propNames) {
|
|
25
|
+
const value = object[name];
|
|
26
|
+
if (value && typeof value === "object") {
|
|
27
|
+
_deepFreeze(value);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return Object.freeze(object);
|
|
31
|
+
}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { useStorage } from "nitropack/runtime";
|
|
2
|
+
// @ts-expect-error virtual file
|
|
2
3
|
import { NUXT_SHARED_DATA } from "#internal/nuxt/nitro-config.mjs";
|
|
3
4
|
export const payloadCache = import.meta.prerender ? useStorage("internal:nuxt:prerender:payload") : null;
|
|
4
5
|
export const islandCache = import.meta.prerender ? useStorage("internal:nuxt:prerender:island") : null;
|
|
5
6
|
export const islandPropCache = import.meta.prerender ? useStorage("internal:nuxt:prerender:island-props") : null;
|
|
6
|
-
export const sharedPrerenderPromises = import.meta.prerender && NUXT_SHARED_DATA ?
|
|
7
|
-
const sharedPrerenderKeys =
|
|
7
|
+
export const sharedPrerenderPromises = import.meta.prerender && NUXT_SHARED_DATA ? new Map() : null;
|
|
8
|
+
const sharedPrerenderKeys = new Set();
|
|
8
9
|
export const sharedPrerenderCache = import.meta.prerender && NUXT_SHARED_DATA ? {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
get(key) {
|
|
11
|
+
if (sharedPrerenderKeys.has(key)) {
|
|
12
|
+
return sharedPrerenderPromises.get(key) ?? useStorage("internal:nuxt:prerender:shared").getItem(key);
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
async set(key, value) {
|
|
16
|
+
sharedPrerenderKeys.add(key);
|
|
17
|
+
sharedPrerenderPromises.set(key, value);
|
|
18
|
+
useStorage("internal:nuxt:prerender:shared").setItem(key, await value).finally(() => sharedPrerenderPromises.delete(key));
|
|
19
|
+
}
|
|
19
20
|
} : null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const defineAppConfig: unknown;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
const iframeStorageBridge = (nonce) =>
|
|
2
|
-
/* js */
|
|
3
|
-
`
|
|
1
|
+
const iframeStorageBridge = (nonce) => `
|
|
4
2
|
(function () {
|
|
5
3
|
const NONCE = ${JSON.stringify(nonce)};
|
|
6
4
|
const memoryStore = Object.create(null);
|
|
@@ -78,11 +76,8 @@ const iframeStorageBridge = (nonce) => (
|
|
|
78
76
|
|
|
79
77
|
post('storage-sync-request', {});
|
|
80
78
|
})();
|
|
81
|
-
|
|
82
|
-
)
|
|
83
|
-
const parentStorageBridge = (nonce) => (
|
|
84
|
-
/* js */
|
|
85
|
-
`
|
|
79
|
+
`;
|
|
80
|
+
const parentStorageBridge = (nonce) => `
|
|
86
81
|
(function () {
|
|
87
82
|
const host = document.querySelector('nuxt-error-overlay');
|
|
88
83
|
if (!host) return;
|
|
@@ -147,11 +142,8 @@ const parentStorageBridge = (nonce) => (
|
|
|
147
142
|
|
|
148
143
|
obs.observe(host, { childList: true, subtree: true });
|
|
149
144
|
})();
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const errorCSS = (
|
|
153
|
-
/* css */
|
|
154
|
-
`
|
|
145
|
+
`;
|
|
146
|
+
const errorCSS = `
|
|
155
147
|
:host {
|
|
156
148
|
--preview-width: 240px;
|
|
157
149
|
--preview-height: 180px;
|
|
@@ -333,12 +325,9 @@ const errorCSS = (
|
|
|
333
325
|
transition: none;
|
|
334
326
|
}
|
|
335
327
|
}
|
|
336
|
-
|
|
337
|
-
);
|
|
328
|
+
`;
|
|
338
329
|
function webComponentScript(base64HTML, startMinimized) {
|
|
339
|
-
|
|
340
|
-
/* js */
|
|
341
|
-
`
|
|
330
|
+
return `
|
|
342
331
|
(function () {
|
|
343
332
|
try {
|
|
344
333
|
// =========================
|
|
@@ -397,7 +386,7 @@ function webComponentScript(base64HTML, startMinimized) {
|
|
|
397
386
|
pipRestoreButton.id = 'pip-restore';
|
|
398
387
|
pipRestoreButton.setAttribute('type', 'button');
|
|
399
388
|
pipRestoreButton.setAttribute('aria-label', 'Show error overlay');
|
|
400
|
-
pipRestoreButton.innerHTML = '<span aria-hidden="true"
|
|
389
|
+
pipRestoreButton.innerHTML = '<span aria-hidden="true">⟲</span><span>Show error overlay</span>';
|
|
401
390
|
pipRestoreButton.hidden = true;
|
|
402
391
|
|
|
403
392
|
// Order matters: #frame + #preview adjacency
|
|
@@ -686,10 +675,10 @@ function webComponentScript(base64HTML, startMinimized) {
|
|
|
686
675
|
|
|
687
676
|
const setRestoreLabel = (kind) => {
|
|
688
677
|
if (kind === 'pretty') {
|
|
689
|
-
pipRestoreButton.innerHTML = '<span aria-hidden="true"
|
|
678
|
+
pipRestoreButton.innerHTML = '<span aria-hidden="true">⟲</span><span>Show error overlay</span>';
|
|
690
679
|
pipRestoreButton.setAttribute('aria-label', 'Show error overlay');
|
|
691
680
|
} else {
|
|
692
|
-
pipRestoreButton.innerHTML = '<span aria-hidden="true"
|
|
681
|
+
pipRestoreButton.innerHTML = '<span aria-hidden="true">⟲</span><span>Show error page</span>';
|
|
693
682
|
pipRestoreButton.setAttribute('aria-label', 'Show error page');
|
|
694
683
|
}
|
|
695
684
|
};
|
|
@@ -982,14 +971,13 @@ function webComponentScript(base64HTML, startMinimized) {
|
|
|
982
971
|
console.error('Failed to initialize Nuxt error overlay:', err);
|
|
983
972
|
}
|
|
984
973
|
})();
|
|
985
|
-
|
|
986
|
-
);
|
|
974
|
+
`;
|
|
987
975
|
}
|
|
988
976
|
export function generateErrorOverlayHTML(html, options) {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
977
|
+
const nonce = Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
978
|
+
const errorPage = html.replace("<head>", `<head><script>${iframeStorageBridge(nonce)}<\/script>`);
|
|
979
|
+
const base64HTML = Buffer.from(errorPage, "utf8").toString("base64");
|
|
980
|
+
return `
|
|
993
981
|
<script>${parentStorageBridge(nonce)}<\/script>
|
|
994
982
|
<nuxt-error-overlay></nuxt-error-overlay>
|
|
995
983
|
<script>${webComponentScript(base64HTML, options?.startMinimized ?? false)}<\/script>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { H3Event } from "h3";
|
|
2
|
+
/**
|
|
3
|
+
* Nitro internal functions extracted from https://github.com/nitrojs/nitro/blob/v2/src/runtime/internal/utils.ts
|
|
4
|
+
*/
|
|
5
|
+
export declare function isJsonRequest(event: H3Event): boolean;
|
|
6
|
+
export declare function hasReqHeader(event: H3Event, name: string, includes: string);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getRequestHeader } from "h3";
|
|
2
|
+
/**
|
|
3
|
+
* Nitro internal functions extracted from https://github.com/nitrojs/nitro/blob/v2/src/runtime/internal/utils.ts
|
|
4
|
+
*/
|
|
5
|
+
export function isJsonRequest(event) {
|
|
6
|
+
// If the client specifically requests HTML, then avoid classifying as JSON.
|
|
7
|
+
if (hasReqHeader(event, "accept", "text/html")) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
return hasReqHeader(event, "accept", "application/json") || hasReqHeader(event, "user-agent", "curl/") || hasReqHeader(event, "user-agent", "httpie/") || hasReqHeader(event, "sec-fetch-mode", "cors") || event.path.startsWith("/api/") || event.path.endsWith(".json");
|
|
11
|
+
}
|
|
12
|
+
export function hasReqHeader(event, name, includes) {
|
|
13
|
+
const value = getRequestHeader(event, name);
|
|
14
|
+
return value && typeof value === "string" && value.toLowerCase().includes(includes);
|
|
15
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { joinRelativeURL } from "ufo";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
3
|
+
export function baseURL() {
|
|
4
|
+
// TODO: support passing event to `useRuntimeConfig`
|
|
5
|
+
return useRuntimeConfig().app.baseURL;
|
|
6
|
+
}
|
|
7
|
+
export function buildAssetsDir() {
|
|
8
|
+
// TODO: support passing event to `useRuntimeConfig`
|
|
9
|
+
return useRuntimeConfig().app.buildAssetsDir;
|
|
10
|
+
}
|
|
11
|
+
export function buildAssetsURL(...path) {
|
|
12
|
+
return joinRelativeURL(publicAssetsURL(), buildAssetsDir(), ...path);
|
|
13
|
+
}
|
|
14
|
+
export function publicAssetsURL(...path) {
|
|
15
|
+
// TODO: support passing event to `useRuntimeConfig`
|
|
16
|
+
const app = useRuntimeConfig().app;
|
|
17
|
+
const publicBase = app.cdnURL || app.baseURL;
|
|
18
|
+
return path.length ? joinRelativeURL(publicBase, ...path) : publicBase;
|
|
19
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { H3Event } from
|
|
2
|
-
import type { NuxtPayload, NuxtSSRContext } from
|
|
1
|
+
import type { H3Event } from "h3";
|
|
2
|
+
import type { NuxtPayload, NuxtSSRContext } from "nuxt/app";
|
|
3
3
|
export declare function createSSRContext(event: H3Event): NuxtSSRContext;
|
|
4
|
-
export declare function setSSRError(ssrContext: NuxtSSRContext, error: NuxtPayload[
|
|
5
|
-
|
|
4
|
+
export declare function setSSRError(ssrContext: NuxtSSRContext, error: NuxtPayload["error"] & {
|
|
5
|
+
url: string;
|
|
6
6
|
}): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { decodePath } from "ufo";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
3
|
+
import { createHead } from "@unhead/vue/server";
|
|
4
|
+
import { sharedPrerenderCache } from "../cache.mjs";
|
|
5
|
+
// @ts-expect-error virtual file
|
|
6
|
+
import unheadOptions from "#internal/unhead-options.mjs";
|
|
7
|
+
// @ts-expect-error virtual file
|
|
8
|
+
import { NUXT_NO_SSR, NUXT_SHARED_DATA } from "#internal/nuxt/nitro-config.mjs";
|
|
9
|
+
const PRERENDER_NO_SSR_ROUTES = new Set([
|
|
10
|
+
"/index.html",
|
|
11
|
+
"/200.html",
|
|
12
|
+
"/404.html"
|
|
13
|
+
]);
|
|
14
|
+
export function createSSRContext(event) {
|
|
15
|
+
const ssrContext = {
|
|
16
|
+
url: decodePath(event.path),
|
|
17
|
+
event,
|
|
18
|
+
runtimeConfig: useRuntimeConfig(event),
|
|
19
|
+
noSSR: !!NUXT_NO_SSR || event.context.nuxt?.noSSR || (import.meta.prerender ? PRERENDER_NO_SSR_ROUTES.has(event.path) : false),
|
|
20
|
+
head: createHead(unheadOptions),
|
|
21
|
+
error: false,
|
|
22
|
+
nuxt: undefined,
|
|
23
|
+
payload: {},
|
|
24
|
+
["~payloadReducers"]: Object.create(null),
|
|
25
|
+
modules: new Set()
|
|
26
|
+
};
|
|
27
|
+
if (import.meta.prerender) {
|
|
28
|
+
if (NUXT_SHARED_DATA) {
|
|
29
|
+
ssrContext["~sharedPrerenderCache"] = sharedPrerenderCache;
|
|
30
|
+
}
|
|
31
|
+
ssrContext.payload.prerenderedAt = Date.now();
|
|
32
|
+
}
|
|
33
|
+
return ssrContext;
|
|
34
|
+
}
|
|
35
|
+
export function setSSRError(ssrContext, error) {
|
|
36
|
+
ssrContext.error = true;
|
|
37
|
+
ssrContext.payload = { error };
|
|
38
|
+
ssrContext.url = error.url;
|
|
39
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RendererContext } from "vue-bundle-renderer/runtime";
|
|
2
|
+
import type { NuxtSSRContext } from "nuxt/app";
|
|
3
|
+
interface Renderer {
|
|
4
|
+
rendererContext: RendererContext;
|
|
5
|
+
renderToString(ssrContext: NuxtSSRContext): Promise<{
|
|
6
|
+
html: string;
|
|
7
|
+
renderResourceHeaders: () => Record<string, string>;
|
|
8
|
+
renderResourceHints: () => string;
|
|
9
|
+
renderStyles: () => string;
|
|
10
|
+
renderScripts: () => string;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
// -- SSR Renderer --
|
|
14
|
+
export declare const getSSRRenderer: unknown;
|
|
15
|
+
export declare function getRenderer(ssrContext: NuxtSSRContext): Promise<Renderer>;
|
|
16
|
+
// @ts-expect-error file will be produced after app build
|
|
17
|
+
export declare const getSSRStyles: unknown;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createRenderer } from "vue-bundle-renderer/runtime";
|
|
2
|
+
import { renderToString as _renderToString } from "vue/server-renderer";
|
|
3
|
+
import { propsToString } from "@unhead/vue/server";
|
|
4
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
5
|
+
// @ts-expect-error virtual file
|
|
6
|
+
import { NUXT_NO_SSR } from "#internal/nuxt/nitro-config.mjs";
|
|
7
|
+
// @ts-expect-error virtual file
|
|
8
|
+
import { appRootAttrs, appRootTag, appSpaLoaderAttrs, appSpaLoaderTag, spaLoadingTemplateOutside } from "#internal/nuxt.config.mjs";
|
|
9
|
+
// @ts-expect-error virtual file
|
|
10
|
+
import { buildAssetsURL } from "#internal/nuxt/paths";
|
|
11
|
+
const APP_ROOT_OPEN_TAG = `<${appRootTag}${propsToString(appRootAttrs)}>`;
|
|
12
|
+
const APP_ROOT_CLOSE_TAG = `</${appRootTag}>`;
|
|
13
|
+
// @ts-expect-error file will be produced after app build
|
|
14
|
+
const getServerEntry = () => import("#build/dist/server/server.mjs").then((r) => r.default || r);
|
|
15
|
+
// @ts-expect-error file will be produced after app build
|
|
16
|
+
const getClientManifest = () => import("#build/dist/server/client.manifest.mjs").then((r) => r.default || r).then((r) => typeof r === "function" ? r() : r);
|
|
17
|
+
// @ts-expect-error file will be produced after app build
|
|
18
|
+
const getPrecomputedDependencies = () => import("#build/dist/server/client.precomputed.mjs").then((r) => r.default || r).then((r) => typeof r === "function" ? r() : r);
|
|
19
|
+
// -- SSR Renderer --
|
|
20
|
+
export const getSSRRenderer = lazyCachedFunction(async () => {
|
|
21
|
+
// Load server bundle
|
|
22
|
+
const createSSRApp = await getServerEntry();
|
|
23
|
+
if (!createSSRApp) {
|
|
24
|
+
throw new Error("Server bundle is not available");
|
|
25
|
+
}
|
|
26
|
+
// Load precomputed dependencies
|
|
27
|
+
const precomputed = import.meta.dev ? undefined : await getPrecomputedDependencies();
|
|
28
|
+
// Create renderer
|
|
29
|
+
const renderer = createRenderer(createSSRApp, {
|
|
30
|
+
precomputed,
|
|
31
|
+
manifest: import.meta.dev ? await getClientManifest() : undefined,
|
|
32
|
+
renderToString,
|
|
33
|
+
buildAssetsURL
|
|
34
|
+
});
|
|
35
|
+
async function renderToString(input, context) {
|
|
36
|
+
const html = await _renderToString(input, context);
|
|
37
|
+
// In development with vite-node, the manifest is on-demand and will be available after rendering
|
|
38
|
+
// eslint-disable-next-line no-restricted-globals
|
|
39
|
+
if (import.meta.dev && process.env.NUXT_VITE_NODE_OPTIONS) {
|
|
40
|
+
renderer.rendererContext.updateManifest(await getClientManifest());
|
|
41
|
+
}
|
|
42
|
+
return APP_ROOT_OPEN_TAG + html + APP_ROOT_CLOSE_TAG;
|
|
43
|
+
}
|
|
44
|
+
return renderer;
|
|
45
|
+
});
|
|
46
|
+
// -- SPA Renderer --
|
|
47
|
+
const getSPARenderer = lazyCachedFunction(async () => {
|
|
48
|
+
const precomputed = import.meta.dev ? undefined : await getPrecomputedDependencies();
|
|
49
|
+
// @ts-expect-error virtual file
|
|
50
|
+
const spaTemplate = await import("#spa-template").then((r) => r.template).catch(() => "").then((r) => {
|
|
51
|
+
if (spaLoadingTemplateOutside) {
|
|
52
|
+
const APP_SPA_LOADER_OPEN_TAG = `<${appSpaLoaderTag}${propsToString(appSpaLoaderAttrs)}>`;
|
|
53
|
+
const APP_SPA_LOADER_CLOSE_TAG = `</${appSpaLoaderTag}>`;
|
|
54
|
+
const appTemplate = APP_ROOT_OPEN_TAG + APP_ROOT_CLOSE_TAG;
|
|
55
|
+
const loaderTemplate = r ? APP_SPA_LOADER_OPEN_TAG + r + APP_SPA_LOADER_CLOSE_TAG : "";
|
|
56
|
+
return appTemplate + loaderTemplate;
|
|
57
|
+
} else {
|
|
58
|
+
return APP_ROOT_OPEN_TAG + r + APP_ROOT_CLOSE_TAG;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// Create SPA renderer and cache the result for all requests
|
|
62
|
+
const renderer = createRenderer(() => () => {}, {
|
|
63
|
+
precomputed,
|
|
64
|
+
manifest: import.meta.dev ? await getClientManifest() : undefined,
|
|
65
|
+
renderToString: () => spaTemplate,
|
|
66
|
+
buildAssetsURL
|
|
67
|
+
});
|
|
68
|
+
const result = await renderer.renderToString({});
|
|
69
|
+
const renderToString = (ssrContext) => {
|
|
70
|
+
const config = useRuntimeConfig(ssrContext.event);
|
|
71
|
+
ssrContext.modules ||= new Set();
|
|
72
|
+
ssrContext.payload.serverRendered = false;
|
|
73
|
+
ssrContext.config = {
|
|
74
|
+
public: config.public,
|
|
75
|
+
app: config.app
|
|
76
|
+
};
|
|
77
|
+
return Promise.resolve(result);
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
rendererContext: renderer.rendererContext,
|
|
81
|
+
renderToString
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
function lazyCachedFunction(fn) {
|
|
85
|
+
let res = null;
|
|
86
|
+
return () => {
|
|
87
|
+
if (res === null) {
|
|
88
|
+
res = fn().catch((err) => {
|
|
89
|
+
res = null;
|
|
90
|
+
throw err;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return res;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function getRenderer(ssrContext) {
|
|
97
|
+
return NUXT_NO_SSR || ssrContext.noSSR ? getSPARenderer() : getSSRRenderer();
|
|
98
|
+
}
|
|
99
|
+
// @ts-expect-error file will be produced after app build
|
|
100
|
+
export const getSSRStyles = lazyCachedFunction(() => import("#build/dist/server/styles.mjs").then((r) => r.default || r));
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { Style } from
|
|
1
|
+
import type { Style } from "@unhead/vue/types";
|
|
2
2
|
export declare function renderInlineStyles(usedModules: Set<string> | string[]): Promise<Style[]>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getSSRStyles } from "./build-files.mjs";
|
|
2
|
+
export async function renderInlineStyles(usedModules) {
|
|
3
|
+
const styleMap = await getSSRStyles();
|
|
4
|
+
const inlinedStyles = new Set();
|
|
5
|
+
for (const mod of usedModules) {
|
|
6
|
+
if (mod in styleMap && styleMap[mod]) {
|
|
7
|
+
for (const style of await styleMap[mod]()) {
|
|
8
|
+
inlinedStyles.add(style);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return Array.from(inlinedStyles).map((style) => ({ innerHTML: style }));
|
|
13
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { NuxtIslandResponse, NuxtSSRContext } from
|
|
1
|
+
import type { NuxtIslandResponse, NuxtSSRContext } from "nuxt/app";
|
|
2
2
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
* remove the root node from the html body
|
|
4
|
+
*/
|
|
5
5
|
export declare function getServerComponentHTML(body: string): string;
|
|
6
|
-
export declare function getSlotIslandResponse(ssrContext: NuxtSSRContext): NuxtIslandResponse[
|
|
7
|
-
export declare function getClientIslandResponse(ssrContext: NuxtSSRContext): NuxtIslandResponse[
|
|
6
|
+
export declare function getSlotIslandResponse(ssrContext: NuxtSSRContext): NuxtIslandResponse["slots"];
|
|
7
|
+
export declare function getClientIslandResponse(ssrContext: NuxtSSRContext): NuxtIslandResponse["components"];
|
|
8
8
|
export declare function getComponentSlotTeleport(clientUid: string, teleports: Record<string, string>): Record<string, string>;
|
|
9
9
|
export declare function replaceIslandTeleports(ssrContext: NuxtSSRContext, html: string): string;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// @ts-expect-error virtual file
|
|
2
|
+
import { appRootTag } from "#internal/nuxt.config.mjs";
|
|
3
|
+
const ROOT_NODE_REGEX = new RegExp(`^<${appRootTag}[^>]*>([\\s\\S]*)<\\/${appRootTag}>$`);
|
|
4
|
+
/**
|
|
5
|
+
* remove the root node from the html body
|
|
6
|
+
*/
|
|
7
|
+
export function getServerComponentHTML(body) {
|
|
8
|
+
const match = body.match(ROOT_NODE_REGEX);
|
|
9
|
+
return match?.[1] || body;
|
|
10
|
+
}
|
|
11
|
+
const SSR_SLOT_TELEPORT_MARKER = /^uid=([^;]*);slot=(.*)$/;
|
|
12
|
+
const SSR_CLIENT_TELEPORT_MARKER = /^uid=([^;]*);client=(.*)$/;
|
|
13
|
+
const SSR_CLIENT_SLOT_MARKER = /^island-slot=([^;]*);(.*)$/;
|
|
14
|
+
export function getSlotIslandResponse(ssrContext) {
|
|
15
|
+
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.slots).length) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const response = {};
|
|
19
|
+
for (const [name, slot] of Object.entries(ssrContext.islandContext.slots)) {
|
|
20
|
+
response[name] = {
|
|
21
|
+
...slot,
|
|
22
|
+
fallback: ssrContext.teleports?.[`island-fallback=${name}`]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return response;
|
|
26
|
+
}
|
|
27
|
+
export function getClientIslandResponse(ssrContext) {
|
|
28
|
+
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.components).length) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const response = {};
|
|
32
|
+
for (const [clientUid, component] of Object.entries(ssrContext.islandContext.components)) {
|
|
33
|
+
// remove teleport anchor to avoid hydration issues
|
|
34
|
+
const html = ssrContext.teleports?.[clientUid]?.replaceAll("<!--teleport start anchor-->", "") || "";
|
|
35
|
+
response[clientUid] = {
|
|
36
|
+
...component,
|
|
37
|
+
html,
|
|
38
|
+
slots: getComponentSlotTeleport(clientUid, ssrContext.teleports ?? {})
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return response;
|
|
42
|
+
}
|
|
43
|
+
export function getComponentSlotTeleport(clientUid, teleports) {
|
|
44
|
+
const entries = Object.entries(teleports);
|
|
45
|
+
const slots = {};
|
|
46
|
+
for (const [key, value] of entries) {
|
|
47
|
+
const match = key.match(SSR_CLIENT_SLOT_MARKER);
|
|
48
|
+
if (match) {
|
|
49
|
+
const [, id, slot] = match;
|
|
50
|
+
if (!slot || clientUid !== id) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
slots[slot] = value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return slots;
|
|
57
|
+
}
|
|
58
|
+
export function replaceIslandTeleports(ssrContext, html) {
|
|
59
|
+
const { teleports, islandContext } = ssrContext;
|
|
60
|
+
if (islandContext || !teleports) {
|
|
61
|
+
return html;
|
|
62
|
+
}
|
|
63
|
+
for (const key in teleports) {
|
|
64
|
+
const matchClientComp = key.match(SSR_CLIENT_TELEPORT_MARKER);
|
|
65
|
+
if (matchClientComp) {
|
|
66
|
+
const [, uid, clientId] = matchClientComp;
|
|
67
|
+
if (!uid || !clientId) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
html = html.replace(new RegExp(` data-island-uid="${uid}" data-island-component="${clientId}"[^>]*>`), (full) => {
|
|
71
|
+
return full + teleports[key];
|
|
72
|
+
});
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const matchSlot = key.match(SSR_SLOT_TELEPORT_MARKER);
|
|
76
|
+
if (matchSlot) {
|
|
77
|
+
const [, uid, slot] = matchSlot;
|
|
78
|
+
if (!uid || !slot) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
html = html.replace(new RegExp(` data-island-uid="${uid}" data-island-slot="${slot}"[^>]*>`), (full) => {
|
|
82
|
+
return full + teleports[key];
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return html;
|
|
87
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { NitroRouteRules, RenderResponse } from "nitropack/types";
|
|
2
|
+
import type { Script } from "@unhead/vue";
|
|
3
|
+
import type { NuxtPayload, NuxtSSRContext } from "nuxt/app";
|
|
4
|
+
export declare function renderPayloadResponse(ssrContext: NuxtSSRContext): RenderResponse;
|
|
5
|
+
export declare function renderPayloadJsonScript(opts: {
|
|
6
|
+
ssrContext: NuxtSSRContext;
|
|
7
|
+
data?: any;
|
|
8
|
+
src?: string;
|
|
9
|
+
}): Script[];
|
|
10
|
+
export declare function renderPayloadScript(opts: {
|
|
11
|
+
ssrContext: NuxtSSRContext;
|
|
12
|
+
routeOptions: NitroRouteRules;
|
|
13
|
+
data?: any;
|
|
14
|
+
src?: string;
|
|
15
|
+
}): Script[];
|
|
16
|
+
interface SplitPayload {
|
|
17
|
+
initial: Omit<NuxtPayload, "data">;
|
|
18
|
+
payload: {
|
|
19
|
+
data?: NuxtPayload["data"];
|
|
20
|
+
prerenderedAt?: NuxtPayload["prerenderedAt"];
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export declare function splitPayload(ssrContext: NuxtSSRContext): SplitPayload;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getResponseStatus, getResponseStatusText } from "h3";
|
|
2
|
+
import devalue from "@nuxt/devalue";
|
|
3
|
+
import { stringify, uneval } from "devalue";
|
|
4
|
+
// @ts-expect-error virtual file
|
|
5
|
+
import { appId, multiApp } from "#internal/nuxt.config.mjs";
|
|
6
|
+
// @ts-expect-error virtual file
|
|
7
|
+
import { NUXT_JSON_PAYLOADS, NUXT_NO_SSR, NUXT_PAYLOAD_EXTRACTION, NUXT_RUNTIME_PAYLOAD_EXTRACTION } from "#internal/nuxt/nitro-config.mjs";
|
|
8
|
+
export function renderPayloadResponse(ssrContext) {
|
|
9
|
+
return {
|
|
10
|
+
body: NUXT_JSON_PAYLOADS ? stringify(splitPayload(ssrContext).payload, ssrContext["~payloadReducers"]) : `export default ${devalue(splitPayload(ssrContext).payload)}`,
|
|
11
|
+
statusCode: getResponseStatus(ssrContext.event),
|
|
12
|
+
statusMessage: getResponseStatusText(ssrContext.event),
|
|
13
|
+
headers: {
|
|
14
|
+
"content-type": NUXT_JSON_PAYLOADS ? "application/json;charset=utf-8" : "text/javascript;charset=utf-8",
|
|
15
|
+
"x-powered-by": "Nuxt"
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function renderPayloadJsonScript(opts) {
|
|
20
|
+
const contents = opts.data ? stringify(opts.data, opts.ssrContext["~payloadReducers"]) : "";
|
|
21
|
+
const payload = {
|
|
22
|
+
"type": "application/json",
|
|
23
|
+
"innerHTML": contents,
|
|
24
|
+
"data-nuxt-data": appId,
|
|
25
|
+
"data-ssr": !(NUXT_NO_SSR || opts.ssrContext.noSSR)
|
|
26
|
+
};
|
|
27
|
+
if (!multiApp) {
|
|
28
|
+
payload.id = "__NUXT_DATA__";
|
|
29
|
+
}
|
|
30
|
+
if (opts.src) {
|
|
31
|
+
payload["data-src"] = opts.src;
|
|
32
|
+
}
|
|
33
|
+
const config = uneval(opts.ssrContext.config);
|
|
34
|
+
return [payload, { innerHTML: multiApp ? `window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]={config:${config}}` : `window.__NUXT__={};window.__NUXT__.config=${config}` }];
|
|
35
|
+
}
|
|
36
|
+
export function renderPayloadScript(opts) {
|
|
37
|
+
opts.data.config = opts.ssrContext.config;
|
|
38
|
+
const _PAYLOAD_EXTRACTION = !opts.ssrContext.noSSR && (import.meta.prerender && NUXT_PAYLOAD_EXTRACTION || NUXT_RUNTIME_PAYLOAD_EXTRACTION && (opts.routeOptions.isr || opts.routeOptions.cache));
|
|
39
|
+
const nuxtData = devalue(opts.data);
|
|
40
|
+
if (_PAYLOAD_EXTRACTION) {
|
|
41
|
+
const singleAppPayload = `import p from "${opts.src}";window.__NUXT__={...p,...(${nuxtData})}`;
|
|
42
|
+
const multiAppPayload = `import p from "${opts.src}";window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]={...p,...(${nuxtData})}`;
|
|
43
|
+
return [{
|
|
44
|
+
type: "module",
|
|
45
|
+
innerHTML: multiApp ? multiAppPayload : singleAppPayload
|
|
46
|
+
}];
|
|
47
|
+
}
|
|
48
|
+
const singleAppPayload = `window.__NUXT__=${nuxtData}`;
|
|
49
|
+
const multiAppPayload = `window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]=${nuxtData}`;
|
|
50
|
+
return [{ innerHTML: multiApp ? multiAppPayload : singleAppPayload }];
|
|
51
|
+
}
|
|
52
|
+
export function splitPayload(ssrContext) {
|
|
53
|
+
const { data, prerenderedAt, ...initial } = ssrContext.payload;
|
|
54
|
+
return {
|
|
55
|
+
initial: {
|
|
56
|
+
...initial,
|
|
57
|
+
prerenderedAt
|
|
58
|
+
},
|
|
59
|
+
payload: {
|
|
60
|
+
data,
|
|
61
|
+
prerenderedAt
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxt/nitro-server-nightly",
|
|
3
|
-
"version": "4.3.0-
|
|
3
|
+
"version": "4.3.0-29466366.fa21bb17",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/nuxt/nuxt.git",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"homepage": "https://nuxt.com",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"type": "module",
|
|
13
|
-
"types": "./dist/index.d.
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
14
|
"exports": {
|
|
15
15
|
".": "./dist/index.mjs"
|
|
16
16
|
},
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@nuxt/devalue": "^2.0.2",
|
|
22
|
-
"@nuxt/kit": "npm:@nuxt/kit-nightly@4.3.0-
|
|
22
|
+
"@nuxt/kit": "npm:@nuxt/kit-nightly@4.3.0-29466366.fa21bb17",
|
|
23
23
|
"@unhead/vue": "^2.1.1",
|
|
24
24
|
"@vue/shared": "^3.5.26",
|
|
25
25
|
"consola": "^3.4.2",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
"vue-devtools-stub": "^0.1.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"nuxt": "npm:nuxt-nightly@4.3.0-
|
|
50
|
+
"nuxt": "npm:nuxt-nightly@4.3.0-29466366.fa21bb17"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@nuxt/schema": "npm:@nuxt/schema-nightly@4.3.0-
|
|
54
|
-
"nuxt": "npm:nuxt-nightly@4.3.0-
|
|
55
|
-
"
|
|
53
|
+
"@nuxt/schema": "npm:@nuxt/schema-nightly@4.3.0-29466366.fa21bb17",
|
|
54
|
+
"nuxt": "npm:nuxt-nightly@4.3.0-29466366.fa21bb17",
|
|
55
|
+
"obuild": "0.4.14",
|
|
56
56
|
"vitest": "3.2.4"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
},
|
|
61
61
|
"_name": "@nuxt/nitro-server",
|
|
62
62
|
"scripts": {
|
|
63
|
-
"build:stub": "
|
|
63
|
+
"build:stub": "obuild --stub",
|
|
64
64
|
"test:attw": "attw --pack"
|
|
65
65
|
}
|
|
66
66
|
}
|