vinext 1.0.0-beta.3 → 1.0.0-beta.4
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/build/precompress.js +1 -1
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +12 -2
- package/dist/cli-args.d.ts +2 -1
- package/dist/cli-args.js +10 -0
- package/dist/cli.js +14 -8
- package/dist/client/navigation-runtime.d.ts +6 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/dotenv.d.ts +3 -4
- package/dist/config/dotenv.js +30 -22
- package/dist/config/next-config.d.ts +4 -2
- package/dist/config/next-config.js +3 -0
- package/dist/entries/app-browser-entry.js +1 -1
- package/dist/entries/app-rsc-entry.js +18 -3
- package/dist/entries/pages-server-entry.js +4 -1
- package/dist/index.js +11 -7
- package/dist/plugins/client-reference-dedup.js +7 -5
- package/dist/plugins/sass.js +3 -4
- package/dist/server/api-handler.js +4 -3
- package/dist/server/app-bfcache-identity.js +28 -2
- package/dist/server/app-browser-entry.js +73 -45
- package/dist/server/app-browser-navigation-controller.d.ts +1 -1
- package/dist/server/app-browser-navigation-controller.js +29 -4
- package/dist/server/app-browser-prefetch-response.d.ts +9 -0
- package/dist/server/app-browser-prefetch-response.js +32 -0
- package/dist/server/app-browser-state.d.ts +8 -3
- package/dist/server/app-browser-state.js +9 -3
- package/dist/server/app-page-dispatch.d.ts +1 -1
- package/dist/server/app-page-dispatch.js +6 -2
- package/dist/server/app-page-element-builder.d.ts +2 -1
- package/dist/server/app-page-element-builder.js +1 -0
- package/dist/server/app-page-render.d.ts +1 -1
- package/dist/server/app-page-render.js +13 -3
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +3 -12
- package/dist/server/app-page-response.d.ts +2 -0
- package/dist/server/app-page-response.js +6 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -2
- package/dist/server/app-page-route-wiring.js +61 -13
- package/dist/server/app-pages-bridge.d.ts +2 -1
- package/dist/server/app-pages-bridge.js +2 -1
- package/dist/server/app-rsc-cache-busting.d.ts +7 -0
- package/dist/server/app-rsc-cache-busting.js +6 -0
- package/dist/server/app-rsc-handler.d.ts +2 -0
- package/dist/server/app-rsc-handler.js +9 -4
- package/dist/server/app-rsc-render-mode.d.ts +3 -2
- package/dist/server/app-rsc-render-mode.js +4 -1
- package/dist/server/app-rsc-request-normalization.js +65 -4
- package/dist/server/app-server-action-execution.d.ts +1 -1
- package/dist/server/app-visited-response-cache.d.ts +6 -1
- package/dist/server/app-visited-response-cache.js +49 -1
- package/dist/server/dev-server.d.ts +1 -1
- package/dist/server/dev-server.js +61 -38
- package/dist/server/edge-api-runtime.d.ts +10 -1
- package/dist/server/edge-api-runtime.js +29 -1
- package/dist/server/headers.d.ts +3 -1
- package/dist/server/headers.js +3 -1
- package/dist/server/pages-api-route.d.ts +2 -0
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +6 -4
- package/dist/server/pages-document-asset-props.d.ts +26 -0
- package/dist/server/pages-document-asset-props.js +69 -0
- package/dist/server/pages-node-compat.js +3 -3
- package/dist/server/pages-page-handler.d.ts +1 -0
- package/dist/server/pages-page-handler.js +4 -1
- package/dist/server/pages-page-response.d.ts +2 -0
- package/dist/server/pages-page-response.js +19 -8
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prerender-manifest.d.ts +1 -0
- package/dist/server/prod-server.js +2 -1
- package/dist/server/seed-cache.js +1 -1
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/shims/app-router-scroll-state.d.ts +2 -1
- package/dist/shims/app-router-scroll-state.js +7 -2
- package/dist/shims/document.js +15 -2
- package/dist/shims/hash-scroll.d.ts +1 -1
- package/dist/shims/hash-scroll.js +2 -1
- package/dist/shims/link.d.ts +2 -0
- package/dist/shims/link.js +59 -18
- package/dist/shims/metadata.d.ts +11 -17
- package/dist/shims/metadata.js +24 -32
- package/dist/shims/navigation.d.ts +18 -2
- package/dist/shims/navigation.js +69 -20
- package/dist/shims/request-context.d.ts +2 -1
- package/dist/shims/slot.d.ts +2 -1
- package/dist/shims/slot.js +6 -2
- package/dist/shims/streamed-icons.d.ts +9 -0
- package/dist/shims/streamed-icons.js +33 -0
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ import { encodeCacheTag } from "../utils/encode-cache-tag.js";
|
|
|
8
8
|
import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
|
|
9
9
|
import { withScriptNonce } from "../shims/script-nonce-context.js";
|
|
10
10
|
import { createNonceAttribute, escapeHtmlAttr } from "./html.js";
|
|
11
|
+
import { applyDocumentAssetProps, extractDocumentAssetProps } from "./pages-document-asset-props.js";
|
|
11
12
|
import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
|
|
12
13
|
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
13
14
|
import { readStreamAsText } from "../utils/text-stream.js";
|
|
@@ -54,7 +55,7 @@ function buildPagesFontHeadHtml(fontLinks, fontPreloads, fontStyles, scriptNonce
|
|
|
54
55
|
let html = "";
|
|
55
56
|
const nonceAttr = createNonceAttribute(scriptNonce);
|
|
56
57
|
for (const link of fontLinks) html += `<link rel="stylesheet"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(link))}" />\n `;
|
|
57
|
-
for (const preload of fontPreloads) html += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(preload.href)}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n `;
|
|
58
|
+
for (const preload of fontPreloads) html += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(preload.href)}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin="anonymous" />\n `;
|
|
58
59
|
if (fontStyles.length > 0) html += `<style data-vinext-fonts${nonceAttr}>${fontStyles.join("\n")}</style>\n `;
|
|
59
60
|
return html;
|
|
60
61
|
}
|
|
@@ -85,19 +86,27 @@ async function buildPagesShellHtml(bodyMarker, fontHeadHTML, nextDataScript, opt
|
|
|
85
86
|
if (options.DocumentComponent) {
|
|
86
87
|
const docProps = options.resolvedDocProps ?? await loadUserDocumentInitialProps(options.DocumentComponent);
|
|
87
88
|
const docElement = docProps ? React.createElement(options.DocumentComponent, docProps) : React.createElement(options.DocumentComponent);
|
|
88
|
-
|
|
89
|
+
const renderedDocument = extractDocumentAssetProps(await options.renderDocumentToString(docElement));
|
|
90
|
+
let html = renderedDocument.html;
|
|
91
|
+
const generatedAssetTags = applyDocumentAssetProps(options.assetTags, renderedDocument.props, {
|
|
92
|
+
configuredCrossOrigin: options.crossOrigin,
|
|
93
|
+
scriptOwner: options.disableOptimizedLoading ? "next-script" : "head"
|
|
94
|
+
});
|
|
95
|
+
const generatedNextDataScript = applyDocumentAssetProps(nextDataScript, renderedDocument.props, { configuredCrossOrigin: options.crossOrigin });
|
|
89
96
|
html = html.replace("__NEXT_MAIN__", bodyMarker);
|
|
90
|
-
if (options.ssrHeadHTML ||
|
|
91
|
-
html = html.replace("<!-- __NEXT_SCRIPTS__ -->",
|
|
92
|
-
if (!html.includes("__NEXT_DATA__")) html = html.replace("</body>", ` ${
|
|
97
|
+
if (options.ssrHeadHTML || generatedAssetTags || fontHeadHTML) html = html.replace("</head>", ` ${fontHeadHTML}${options.ssrHeadHTML}\n ${generatedAssetTags}\n</head>`);
|
|
98
|
+
html = html.replace("<!-- __NEXT_SCRIPTS__ -->", generatedNextDataScript);
|
|
99
|
+
if (!html.includes("__NEXT_DATA__")) html = html.replace("</body>", ` ${generatedNextDataScript}\n</body>`);
|
|
93
100
|
return html;
|
|
94
101
|
}
|
|
102
|
+
const generatedAssetTags = applyDocumentAssetProps(options.assetTags, {}, { configuredCrossOrigin: options.crossOrigin });
|
|
103
|
+
const generatedNextDataScript = applyDocumentAssetProps(nextDataScript, {}, { configuredCrossOrigin: options.crossOrigin });
|
|
95
104
|
return `<!DOCTYPE html>
|
|
96
105
|
<html>
|
|
97
106
|
<head>
|
|
98
|
-
${fontHeadHTML}${options.ssrHeadHTML}\n ${
|
|
107
|
+
${fontHeadHTML}${options.ssrHeadHTML}\n ${generatedAssetTags}\n</head>
|
|
99
108
|
<body>
|
|
100
|
-
<div id="__next">${bodyMarker}</div>\n ${
|
|
109
|
+
<div id="__next">${bodyMarker}</div>\n ${generatedNextDataScript}\n</body>
|
|
101
110
|
</html>`;
|
|
102
111
|
}
|
|
103
112
|
async function buildPagesCompositeStream(bodyStream, shellPrefix, shellSuffix) {
|
|
@@ -217,10 +226,12 @@ async function renderPagesPageResponse(options) {
|
|
|
217
226
|
if (documentRenderPage.status === "rendered" && documentRenderPage.stylesHTML) ssrHeadHTML += `\n ${documentRenderPage.stylesHTML}`;
|
|
218
227
|
const shellHtml = await buildPagesShellHtml(bodyMarker, fontHeadHTML, nextDataScript, {
|
|
219
228
|
assetTags: options.assetTags,
|
|
229
|
+
disableOptimizedLoading: options.disableOptimizedLoading,
|
|
220
230
|
DocumentComponent: options.DocumentComponent,
|
|
221
231
|
renderDocumentToString: options.renderDocumentToString,
|
|
222
232
|
ssrHeadHTML,
|
|
223
|
-
resolvedDocProps: documentRenderPage.status === "skipped" ? null : documentRenderPage.docProps
|
|
233
|
+
resolvedDocProps: documentRenderPage.status === "skipped" ? null : documentRenderPage.docProps,
|
|
234
|
+
crossOrigin: options.crossOrigin
|
|
224
235
|
});
|
|
225
236
|
options.clearSsrContext();
|
|
226
237
|
const markerIndex = shellHtml.indexOf(bodyMarker);
|
|
@@ -102,7 +102,7 @@ async function handleRequest(request, env, platformCtx) {
|
|
|
102
102
|
matchPageRoute: typeof matchPageRoute === "function" ? matchPageRoute : null,
|
|
103
103
|
runMiddleware: typeof runMiddleware === "function" ? wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath) : null,
|
|
104
104
|
renderPage: typeof renderPage === "function" ? (req, resolvedUrl, options, stagedHeaders) => renderPage(req, resolvedUrl, null, ctx, stagedHeaders, options) : null,
|
|
105
|
-
handleApi: typeof handleApiRoute === "function" ? (req, apiUrl) => handleApiRoute(req, apiUrl, ctx, new URL(req.url).origin) : null,
|
|
105
|
+
handleApi: typeof handleApiRoute === "function" ? (req, apiUrl) => handleApiRoute(req, apiUrl, ctx, new URL(req.url).origin, "worker") : null,
|
|
106
106
|
serveFilesystemRoute: async (requestPathname, _stagedHeaders, phase) => {
|
|
107
107
|
if (!env?.ASSETS) return false;
|
|
108
108
|
return fetchWorkerFilesystemRoute(request, requestPathname, phase, (assetRequest) => Promise.resolve(env.ASSETS.fetch(assetRequest)));
|
|
@@ -666,6 +666,7 @@ async function startProdServer(options = {}) {
|
|
|
666
666
|
}
|
|
667
667
|
function createNodeExecutionContext(trustedRevalidateOrigin) {
|
|
668
668
|
return {
|
|
669
|
+
hostRuntime: "node",
|
|
669
670
|
waitUntil(promise) {
|
|
670
671
|
Promise.resolve(promise).catch(() => {});
|
|
671
672
|
},
|
|
@@ -1148,7 +1149,7 @@ async function startPagesRouterServer(options) {
|
|
|
1148
1149
|
...options,
|
|
1149
1150
|
originalUrl: originalRenderUrl
|
|
1150
1151
|
}) : null,
|
|
1151
|
-
handleApi: typeof handleApi === "function" ? (request, apiUrl) => handleApi(request, apiUrl, createNodeExecutionContext(), resolveTrustedNodeRevalidateOrigin(req, host, port)) : null,
|
|
1152
|
+
handleApi: typeof handleApi === "function" ? (request, apiUrl) => handleApi(request, apiUrl, createNodeExecutionContext(), resolveTrustedNodeRevalidateOrigin(req, host, port), "node") : null,
|
|
1152
1153
|
serveFilesystemRoute: async (requestPathname, stagedHeaders, phase) => {
|
|
1153
1154
|
if (req.method !== "GET" && req.method !== "HEAD" || requestPathname === "/" || requestPathname === "/api" || requestPathname.startsWith("/api/") || phase === "direct" && requestPathname.startsWith(`/_next/static/`)) return false;
|
|
1154
1155
|
return tryServeStatic(req, res, clientDir, requestPathname, compress, staticCache, stagedHeaders);
|
|
@@ -66,7 +66,7 @@ async function seedMemoryCacheFromPrerender(serverDir, options) {
|
|
|
66
66
|
const rscKey = options?.buildAppPageRscKey?.(cachePathname) ?? baseKey + ":rsc";
|
|
67
67
|
const revalidateSeconds = typeof route.revalidate === "number" ? route.revalidate : void 0;
|
|
68
68
|
const expireSeconds = typeof route.expire === "number" ? route.expire : void 0;
|
|
69
|
-
const tags = buildAppPageCacheTags(cachePathname, []);
|
|
69
|
+
const tags = buildAppPageCacheTags(cachePathname, route.tags ?? []);
|
|
70
70
|
if (await seedHtml(writeAppPageEntry, prerenderDir, htmlKey, artifactPathname, trailingSlash, route.headers, revalidateSeconds, expireSeconds, tags)) {
|
|
71
71
|
await seedRsc(writeAppPageEntry, prerenderDir, rscKey, artifactPathname, revalidateSeconds, expireSeconds, tags);
|
|
72
72
|
seeded++;
|
|
@@ -8,6 +8,7 @@ function deriveExecutionContext(base, dispatchPagesRevalidate, isInternalPagesRe
|
|
|
8
8
|
...typeof base?.passThroughOnException === "function" ? { passThroughOnException() {
|
|
9
9
|
base.passThroughOnException?.();
|
|
10
10
|
} } : {},
|
|
11
|
+
hostRuntime: "worker",
|
|
11
12
|
...base?.cache === void 0 ? {} : { cache: base.cache },
|
|
12
13
|
...base?.trustedRevalidateOrigin === void 0 ? {} : { trustedRevalidateOrigin: base.trustedRevalidateOrigin },
|
|
13
14
|
dispatchPagesRevalidate,
|
|
@@ -9,8 +9,9 @@ type AppRouterScrollIntent = Readonly<{
|
|
|
9
9
|
declare function beginAppRouterScrollIntent(hash: string | null): AppRouterScrollIntent;
|
|
10
10
|
declare function clearAppRouterScrollIntent(): void;
|
|
11
11
|
declare function getPendingAppRouterScrollIntent(): AppRouterScrollIntent | null;
|
|
12
|
+
declare function isLatestAppRouterScrollIntent(expected: AppRouterScrollIntent | null | undefined): boolean;
|
|
12
13
|
declare function claimAppRouterScrollIntentForCommit(expected: AppRouterScrollIntent | null | undefined, commitId: number): void;
|
|
13
14
|
declare function markAppRouterScrollIntentHeadHoisted(expected: AppRouterScrollIntent | null | undefined, commitId: number): void;
|
|
14
15
|
declare function consumeAppRouterScrollIntent(expected: AppRouterScrollIntent | null | undefined, commitId?: number): AppRouterScrollIntent | null;
|
|
15
16
|
//#endregion
|
|
16
|
-
export { AppRouterScrollIntent, beginAppRouterScrollIntent, claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, markAppRouterScrollIntentHeadHoisted };
|
|
17
|
+
export { AppRouterScrollIntent, beginAppRouterScrollIntent, claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent, markAppRouterScrollIntentHeadHoisted };
|
|
@@ -22,11 +22,16 @@ function beginAppRouterScrollIntent(hash) {
|
|
|
22
22
|
return intent;
|
|
23
23
|
}
|
|
24
24
|
function clearAppRouterScrollIntent() {
|
|
25
|
-
getScrollIntentStore()
|
|
25
|
+
const store = getScrollIntentStore();
|
|
26
|
+
store.nextId += 1;
|
|
27
|
+
store.pending = null;
|
|
26
28
|
}
|
|
27
29
|
function getPendingAppRouterScrollIntent() {
|
|
28
30
|
return getScrollIntentStore().pending;
|
|
29
31
|
}
|
|
32
|
+
function isLatestAppRouterScrollIntent(expected) {
|
|
33
|
+
return expected !== null && expected !== void 0 && getScrollIntentStore().nextId === expected.id;
|
|
34
|
+
}
|
|
30
35
|
function claimAppRouterScrollIntentForCommit(expected, commitId) {
|
|
31
36
|
const store = getScrollIntentStore();
|
|
32
37
|
const intent = store.pending;
|
|
@@ -59,4 +64,4 @@ function consumeAppRouterScrollIntent(expected, commitId) {
|
|
|
59
64
|
return intent;
|
|
60
65
|
}
|
|
61
66
|
//#endregion
|
|
62
|
-
export { beginAppRouterScrollIntent, claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, markAppRouterScrollIntentHeadHoisted };
|
|
67
|
+
export { beginAppRouterScrollIntent, claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent, markAppRouterScrollIntentHeadHoisted };
|
package/dist/shims/document.js
CHANGED
|
@@ -8,6 +8,12 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
* custom Pages Router documents. Vinext's renderer replaces the Main and
|
|
9
9
|
* NextScript placeholders with the rendered page and hydration scripts.
|
|
10
10
|
*/
|
|
11
|
+
const documentAssetMarkerAttributes = {
|
|
12
|
+
headNonce: "data-vinext-head-nonce",
|
|
13
|
+
headCrossOrigin: "data-vinext-head-cross-origin",
|
|
14
|
+
scriptNonce: "data-vinext-script-nonce",
|
|
15
|
+
scriptCrossOrigin: "data-vinext-script-cross-origin"
|
|
16
|
+
};
|
|
11
17
|
const HtmlContext = React.createContext(void 0);
|
|
12
18
|
function Html(props) {
|
|
13
19
|
return /* @__PURE__ */ jsx("html", { ...props });
|
|
@@ -39,9 +45,11 @@ var Head = class extends React.Component {
|
|
|
39
45
|
return [];
|
|
40
46
|
}
|
|
41
47
|
render() {
|
|
42
|
-
const { children, ...props } = this.props;
|
|
48
|
+
const { children, nonce, crossOrigin, ...props } = this.props;
|
|
43
49
|
return /* @__PURE__ */ jsx("head", {
|
|
44
50
|
...props,
|
|
51
|
+
...nonce ? { [documentAssetMarkerAttributes.headNonce]: nonce } : {},
|
|
52
|
+
...crossOrigin ? { [documentAssetMarkerAttributes.headCrossOrigin]: crossOrigin } : {},
|
|
45
53
|
children
|
|
46
54
|
});
|
|
47
55
|
}
|
|
@@ -70,7 +78,12 @@ var NextScript = class extends React.Component {
|
|
|
70
78
|
return JSON.stringify(context.__NEXT_DATA__);
|
|
71
79
|
}
|
|
72
80
|
render() {
|
|
73
|
-
|
|
81
|
+
const { nonce, crossOrigin } = this.props;
|
|
82
|
+
return /* @__PURE__ */ jsx("span", {
|
|
83
|
+
...nonce ? { [documentAssetMarkerAttributes.scriptNonce]: nonce } : {},
|
|
84
|
+
...crossOrigin ? { [documentAssetMarkerAttributes.scriptCrossOrigin]: crossOrigin } : {},
|
|
85
|
+
dangerouslySetInnerHTML: { __html: "<!-- __NEXT_SCRIPTS__ -->" }
|
|
86
|
+
});
|
|
74
87
|
}
|
|
75
88
|
};
|
|
76
89
|
var Document = class extends React.Component {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//#region src/shims/hash-scroll.d.ts
|
|
2
2
|
declare function decodeHashFragment(fragment: string): string;
|
|
3
3
|
declare function scrollToHashTarget(hash: string): void;
|
|
4
|
-
declare function scrollToHashTargetOnNextFrame(hash: string): void;
|
|
4
|
+
declare function scrollToHashTargetOnNextFrame(hash: string, shouldScroll?: () => boolean): void;
|
|
5
5
|
declare function retryScrollTo(x: number, y: number, opts?: {
|
|
6
6
|
minFrames?: number;
|
|
7
7
|
shouldContinue?: () => boolean;
|
|
@@ -24,8 +24,9 @@ function scrollToHashTarget(hash) {
|
|
|
24
24
|
}
|
|
25
25
|
window.scrollTo(0, 0);
|
|
26
26
|
}
|
|
27
|
-
function scrollToHashTargetOnNextFrame(hash) {
|
|
27
|
+
function scrollToHashTargetOnNextFrame(hash, shouldScroll) {
|
|
28
28
|
requestAnimationFrame(() => {
|
|
29
|
+
if (shouldScroll && !shouldScroll()) return;
|
|
29
30
|
scrollToHashTarget(hash);
|
|
30
31
|
});
|
|
31
32
|
}
|
package/dist/shims/link.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ declare function resolveLinkPrefetchMode(prefetchProp: LinkProps["prefetch"], is
|
|
|
56
56
|
declare function canAutoPrefetchFullAppRoute(href: string): boolean;
|
|
57
57
|
declare function resolveAutoAppRoutePrefetch(href: string): {
|
|
58
58
|
cacheForNavigation: boolean;
|
|
59
|
+
fallbackTtl: "dynamic" | "static";
|
|
60
|
+
minimumTtlMs: number | undefined;
|
|
59
61
|
prefetchShellFirst: boolean;
|
|
60
62
|
shouldPrefetch: boolean;
|
|
61
63
|
};
|
package/dist/shims/link.js
CHANGED
|
@@ -30,6 +30,22 @@ import { jsx } from "react/jsx-runtime";
|
|
|
30
30
|
*/
|
|
31
31
|
const HAS_PAGES_ROUTER = process.env.__VINEXT_HAS_PAGES_ROUTER !== "false";
|
|
32
32
|
const HAS_CLIENT_REWRITES = process.env.__VINEXT_HAS_CLIENT_REWRITES !== "false";
|
|
33
|
+
let loadedNavigationModule = null;
|
|
34
|
+
let navigationModulePromise = null;
|
|
35
|
+
let loadedHybridClientRouteOwnerModule = null;
|
|
36
|
+
let hybridClientRouteOwnerModulePromise = null;
|
|
37
|
+
function loadNavigationModule() {
|
|
38
|
+
return navigationModulePromise ??= import("./navigation.js").then((module) => {
|
|
39
|
+
loadedNavigationModule = module;
|
|
40
|
+
return module;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function loadHybridClientRouteOwnerModule() {
|
|
44
|
+
return hybridClientRouteOwnerModulePromise ??= import("./internal/hybrid-client-route-owner.js").then((module) => {
|
|
45
|
+
loadedHybridClientRouteOwnerModule = module;
|
|
46
|
+
return module;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
33
49
|
const LinkStatusContext = createContext({ pending: false });
|
|
34
50
|
/**
|
|
35
51
|
* useLinkStatus returns the pending state of the enclosing <Link>.
|
|
@@ -148,6 +164,8 @@ function getLinkPrefetchRouterMode() {
|
|
|
148
164
|
function resolveMatchedAutoAppRoutePrefetch(route) {
|
|
149
165
|
return {
|
|
150
166
|
cacheForNavigation: !route.canPrefetchLoadingShell && route.requiresDynamicNavigationRequest !== true,
|
|
167
|
+
fallbackTtl: "static",
|
|
168
|
+
minimumTtlMs: route.isDynamic ? 0 : void 0,
|
|
151
169
|
prefetchShellFirst: !route.isDynamic,
|
|
152
170
|
shouldPrefetch: true
|
|
153
171
|
};
|
|
@@ -164,24 +182,32 @@ function canAutoPrefetchFullAppRoute(href) {
|
|
|
164
182
|
function resolveAutoAppRoutePrefetch(href) {
|
|
165
183
|
if (typeof window === "undefined") return {
|
|
166
184
|
cacheForNavigation: false,
|
|
185
|
+
fallbackTtl: "static",
|
|
186
|
+
minimumTtlMs: void 0,
|
|
167
187
|
prefetchShellFirst: false,
|
|
168
188
|
shouldPrefetch: false
|
|
169
189
|
};
|
|
170
190
|
const routes = window.__VINEXT_LINK_PREFETCH_ROUTES__;
|
|
171
191
|
if (!routes) return {
|
|
172
192
|
cacheForNavigation: false,
|
|
193
|
+
fallbackTtl: "static",
|
|
194
|
+
minimumTtlMs: void 0,
|
|
173
195
|
prefetchShellFirst: false,
|
|
174
196
|
shouldPrefetch: false
|
|
175
197
|
};
|
|
176
198
|
const routeHref = toSameOriginRouteHref(href);
|
|
177
199
|
if (routeHref === null) return {
|
|
178
200
|
cacheForNavigation: false,
|
|
201
|
+
fallbackTtl: "static",
|
|
202
|
+
minimumTtlMs: void 0,
|
|
179
203
|
prefetchShellFirst: false,
|
|
180
204
|
shouldPrefetch: false
|
|
181
205
|
};
|
|
182
206
|
const match = matchRouteWithTrie(routeHref, routes, linkPrefetchRouteTrieCache);
|
|
183
207
|
if (!match) return {
|
|
184
208
|
cacheForNavigation: false,
|
|
209
|
+
fallbackTtl: "static",
|
|
210
|
+
minimumTtlMs: void 0,
|
|
185
211
|
prefetchShellFirst: false,
|
|
186
212
|
shouldPrefetch: false
|
|
187
213
|
};
|
|
@@ -196,6 +222,8 @@ function resolveAutoAppRoutePrefetch(href) {
|
|
|
196
222
|
function resolveFullAppRoutePrefetch() {
|
|
197
223
|
return {
|
|
198
224
|
cacheForNavigation: true,
|
|
225
|
+
fallbackTtl: "static",
|
|
226
|
+
minimumTtlMs: void 0,
|
|
199
227
|
prefetchShellFirst: true,
|
|
200
228
|
shouldPrefetch: true
|
|
201
229
|
};
|
|
@@ -229,27 +257,30 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
229
257
|
}) ?? prefetchHref, window.location.href, __basePath);
|
|
230
258
|
const target = new URL(fullHref, window.location.href);
|
|
231
259
|
if (target.origin === window.location.origin && target.pathname === window.location.pathname && target.search === window.location.search) return;
|
|
260
|
+
if (mode === "auto" && priority === "low" && target.origin === window.location.origin && target.pathname === window.location.pathname && target.search !== window.location.search && target.hash !== "") return;
|
|
232
261
|
const runPrefetch = () => {
|
|
233
262
|
(async () => {
|
|
234
263
|
if (hasAppNavigationRuntime()) {
|
|
235
264
|
if (isBotUserAgent(window.navigator?.userAgent ?? "")) return;
|
|
236
265
|
const [navigation, { AppElementsWire }, rscCacheBusting, { APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL }, headersModule, hybridRouteOwner] = await Promise.all([
|
|
237
|
-
|
|
266
|
+
loadNavigationModule(),
|
|
238
267
|
import("../server/app-elements.js"),
|
|
239
268
|
import("../server/app-rsc-cache-busting.js"),
|
|
240
269
|
import("../server/app-rsc-render-mode.js"),
|
|
241
270
|
import("../server/headers.js"),
|
|
242
|
-
HAS_PAGES_ROUTER || HAS_CLIENT_REWRITES ?
|
|
271
|
+
HAS_PAGES_ROUTER || HAS_CLIENT_REWRITES ? loadHybridClientRouteOwnerModule() : null
|
|
243
272
|
]);
|
|
244
273
|
if (navigationEpoch !== linkPrefetchNavigationEpoch) return;
|
|
245
|
-
const { getPrefetchInterceptionContext, getPrefetchCache, getPrefetchedUrls, getMountedSlotsHeader, hasSearchAgnosticPrefetchShellForRoute, hasPrefetchCacheEntryForNavigation, peekPrefetchResponseForNavigation, prefetchRscResponse, restoreRscResponse, PREFETCH_CACHE_TTL } = navigation;
|
|
246
|
-
const {
|
|
274
|
+
const { getPrefetchInterceptionContext, getPrefetchCache, getPrefetchedUrls, getMountedSlotsHeader, createAppPrefetchRequestHeaders, discardLearningOnlyPrefetchCacheEntry, hasSearchAgnosticPrefetchShellForRoute, hasPrefetchCacheEntryForNavigation, peekPrefetchResponseForNavigation, prefetchRscResponse, DYNAMIC_NAVIGATION_CACHE_TTL, restoreRscResponse, PREFETCH_CACHE_TTL } = navigation;
|
|
275
|
+
const { createRscRequestUrl } = rscCacheBusting;
|
|
247
276
|
const { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, VINEXT_MOUNTED_SLOTS_HEADER } = headersModule;
|
|
248
277
|
const hybridOwner = HAS_PAGES_ROUTER ? hybridRouteOwner.resolveHybridClientRouteOwner(prefetchHref, __basePath) : null;
|
|
249
278
|
if (hybridOwner === "pages" || hybridOwner === "document") return;
|
|
250
279
|
const rewrittenPrefetchHref = HAS_CLIENT_REWRITES ? hybridRouteOwner.resolveHybridClientRewriteHref(fullHref, __basePath) : null;
|
|
251
280
|
const autoPrefetch = mode === "auto" ? resolveAutoAppRoutePrefetch(rewrittenPrefetchHref ?? prefetchHref) : mode === "full-after-shell" ? {
|
|
252
281
|
cacheForNavigation: true,
|
|
282
|
+
fallbackTtl: "static",
|
|
283
|
+
minimumTtlMs: void 0,
|
|
253
284
|
prefetchShellFirst: true,
|
|
254
285
|
shouldPrefetch: true
|
|
255
286
|
} : resolveFullAppRoutePrefetch();
|
|
@@ -260,13 +291,15 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
260
291
|
const hasSearchParams = new URL(fullHref, window.location.href).search !== "";
|
|
261
292
|
const isAutomaticSearchParamShell = mode === "auto" && isOptimisticRouteShellPrefetch && hasSearchParams;
|
|
262
293
|
const hasSearchAgnosticShell = isAutomaticSearchParamShell && hasSearchAgnosticPrefetchShellForRoute(await createRscRequestUrl(fullHref, new Headers()), interceptionContext, mountedSlotsHeader);
|
|
263
|
-
const headers =
|
|
294
|
+
const headers = createAppPrefetchRequestHeaders({
|
|
264
295
|
interceptionContext,
|
|
296
|
+
fetchPriority: priority,
|
|
297
|
+
prefetchKind: mode === "full" ? "full" : "auto",
|
|
265
298
|
renderMode: isOptimisticRouteShellPrefetch ? hasSearchAgnosticShell ? APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL : isAutomaticSearchParamShell ? APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL : APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL : void 0
|
|
266
299
|
});
|
|
267
300
|
if (mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);
|
|
268
301
|
const shouldSendSegmentPrefetchHeaders = isOptimisticRouteShellPrefetch || mode === "auto";
|
|
269
|
-
if (__prefetchInlining && autoPrefetch.cacheForNavigation) {
|
|
302
|
+
if (__prefetchInlining && mode === "auto" && autoPrefetch.cacheForNavigation) {
|
|
270
303
|
headers.set(NEXT_ROUTER_PREFETCH_HEADER, "1");
|
|
271
304
|
headers.set(NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, "/__PAGE__");
|
|
272
305
|
} else if (shouldSendSegmentPrefetchHeaders) {
|
|
@@ -277,10 +310,9 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
277
310
|
const additionalRscUrls = rewrittenPrefetchHref && rewrittenPrefetchHref !== fullHref ? [await createRscRequestUrl(rewrittenPrefetchHref, headers)] : [];
|
|
278
311
|
const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
279
312
|
const prefetched = getPrefetchedUrls();
|
|
313
|
+
if (autoPrefetch.cacheForNavigation) discardLearningOnlyPrefetchCacheEntry(rscUrl, interceptionContext);
|
|
280
314
|
if (prefetched.has(cacheKey)) {
|
|
281
315
|
if (!autoPrefetch.cacheForNavigation) return;
|
|
282
|
-
const existing = getPrefetchCache().get(cacheKey);
|
|
283
|
-
if (existing?.cacheForNavigation === false) existing.cacheForNavigation = true;
|
|
284
316
|
}
|
|
285
317
|
const fetchFullRscPayload = () => scheduleAppPrefetchFetch(() => fetch(rscUrl, {
|
|
286
318
|
headers,
|
|
@@ -289,8 +321,9 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
289
321
|
purpose: "prefetch"
|
|
290
322
|
}), priority);
|
|
291
323
|
const fetchLoadingShellForReuse = async () => {
|
|
292
|
-
const shellHeaders =
|
|
324
|
+
const shellHeaders = createAppPrefetchRequestHeaders({
|
|
293
325
|
interceptionContext,
|
|
326
|
+
fetchPriority: priority,
|
|
294
327
|
renderMode: APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL
|
|
295
328
|
});
|
|
296
329
|
shellHeaders.set(NEXT_ROUTER_PREFETCH_HEADER, "1");
|
|
@@ -317,8 +350,9 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
317
350
|
await shellEntry?.pending?.catch(() => {});
|
|
318
351
|
};
|
|
319
352
|
const fetchAliasCacheHitProbe = async () => {
|
|
320
|
-
const probeHeaders =
|
|
353
|
+
const probeHeaders = createAppPrefetchRequestHeaders({
|
|
321
354
|
interceptionContext,
|
|
355
|
+
fetchPriority: priority,
|
|
322
356
|
renderMode: APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL
|
|
323
357
|
});
|
|
324
358
|
probeHeaders.set(NEXT_ROUTER_PREFETCH_HEADER, "1");
|
|
@@ -350,8 +384,9 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
350
384
|
await fetchLoadingShellForReuse();
|
|
351
385
|
return fetchFullRscPayload();
|
|
352
386
|
}
|
|
353
|
-
const shellHeaders =
|
|
387
|
+
const shellHeaders = createAppPrefetchRequestHeaders({
|
|
354
388
|
interceptionContext,
|
|
389
|
+
fetchPriority: priority,
|
|
355
390
|
renderMode: void 0
|
|
356
391
|
});
|
|
357
392
|
shellHeaders.set(NEXT_ROUTER_PREFETCH_HEADER, "1");
|
|
@@ -389,12 +424,18 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
389
424
|
purpose: "prefetch"
|
|
390
425
|
}), priority);
|
|
391
426
|
})() : fetchFullRscPayload();
|
|
392
|
-
if (mode === "full" && autoPrefetch.cacheForNavigation && autoPrefetch.prefetchShellFirst && mountedSlotsHeader === null && !gateViaExplicitSearchShell) fetchLoadingShellForReuse();
|
|
427
|
+
if (!__prefetchInlining && mode === "full" && autoPrefetch.cacheForNavigation && autoPrefetch.prefetchShellFirst && mountedSlotsHeader === null && !gateViaExplicitSearchShell) fetchLoadingShellForReuse();
|
|
393
428
|
prefetchRscResponse(rscUrl, fetchPromise, interceptionContext, mountedSlotsHeader, void 0, {
|
|
394
429
|
cacheForNavigation: autoPrefetch.cacheForNavigation,
|
|
395
|
-
fallbackTtlMs: PREFETCH_CACHE_TTL,
|
|
430
|
+
fallbackTtlMs: autoPrefetch.fallbackTtl === "dynamic" ? DYNAMIC_NAVIGATION_CACHE_TTL : PREFETCH_CACHE_TTL,
|
|
431
|
+
minimumTtlMs: autoPrefetch.minimumTtlMs,
|
|
396
432
|
optimisticRouteShell: isOptimisticRouteShellPrefetch,
|
|
397
433
|
prefetchKind: isOptimisticRouteShellPrefetch ? "loading-shell" : "navigation",
|
|
434
|
+
prepareSnapshot: autoPrefetch.cacheForNavigation ? async (snapshot) => {
|
|
435
|
+
const preparePrefetchResponse = getNavigationRuntime()?.functions.preparePrefetchResponse;
|
|
436
|
+
if (!preparePrefetchResponse) throw new Error("App Router prefetch preparation is unavailable");
|
|
437
|
+
return await preparePrefetchResponse(restoreRscResponse(snapshot));
|
|
438
|
+
} : void 0,
|
|
398
439
|
searchAgnosticShell: isAutomaticSearchParamShell && !hasSearchAgnosticShell
|
|
399
440
|
});
|
|
400
441
|
} else if (HAS_PAGES_ROUTER && window.__NEXT_DATA__) {
|
|
@@ -427,7 +468,7 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
427
468
|
async function promotePrefetchEntriesForNavigation(href) {
|
|
428
469
|
if (typeof window === "undefined") return;
|
|
429
470
|
if (!hasAppNavigationRuntime()) return;
|
|
430
|
-
const [{ getPrefetchCache }, { stripRscCacheBustingSearchParam, stripRscSuffix }] = await Promise.all([
|
|
471
|
+
const [{ getPrefetchCache }, { stripRscCacheBustingSearchParam, stripRscSuffix }] = await Promise.all([loadNavigationModule(), import("../server/app-rsc-cache-busting.js")]);
|
|
431
472
|
let target;
|
|
432
473
|
try {
|
|
433
474
|
target = new URL(toBrowserNavigationHref(href, window.location.href, __basePath), window.location.href);
|
|
@@ -595,7 +636,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
|
|
|
595
636
|
} : null;
|
|
596
637
|
const pagesAsHref = asHref ?? dynamicRouteHref?.as;
|
|
597
638
|
const unresolvedHref = pagesAsHref ?? hrefStr;
|
|
598
|
-
const rawResolvedHref = typeof unresolvedHref === "string" && unresolvedHref.startsWith("#") ? resolvePagesQueryOnlyHref(unresolvedHref) : unresolvedHref;
|
|
639
|
+
const rawResolvedHref = typeof unresolvedHref === "string" && unresolvedHref.startsWith("#") && !getNavigationRuntime()?.functions.navigate ? resolvePagesQueryOnlyHref(unresolvedHref) : unresolvedHref;
|
|
599
640
|
const concreteRouteHref = HAS_PAGES_ROUTER ? resolveConcreteRouteHref(dynamicRouteHref ? hrefForImplicitInterpolation ?? href : href, pagesAsHref) : null;
|
|
600
641
|
const routeHrefRaw = dynamicRouteHref?.href ?? concreteRouteHref ?? hrefStr;
|
|
601
642
|
const prefetchRouteHrefRaw = concreteRouteHref ?? routeHrefRaw;
|
|
@@ -743,19 +784,19 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
|
|
|
743
784
|
onNavigate(navEvent);
|
|
744
785
|
if (navEvent.defaultPrevented) return;
|
|
745
786
|
} catch {}
|
|
746
|
-
const hybridOwner = HAS_PAGES_ROUTER && hasAppNavigationRuntime ?
|
|
787
|
+
const hybridOwner = (HAS_PAGES_ROUTER && hasAppNavigationRuntime ? loadedHybridClientRouteOwnerModule ?? await loadHybridClientRouteOwnerModule() : null)?.resolveHybridClientRouteOwner(navigateHref, __basePath);
|
|
747
788
|
if (HAS_PAGES_ROUTER && hasAppNavigationRuntime && ["pages", "document"].includes(hybridOwner ?? "")) {
|
|
748
789
|
if (replace) window.location.replace(absoluteFullHref);
|
|
749
790
|
else window.location.assign(absoluteFullHref);
|
|
750
791
|
return;
|
|
751
792
|
}
|
|
752
793
|
if (hasAppNavigationRuntime) {
|
|
753
|
-
const { navigateClientSide } = await
|
|
794
|
+
const { navigateClientSide } = loadedNavigationModule ?? await loadNavigationModule();
|
|
754
795
|
const setter = setPendingRef.current;
|
|
755
796
|
if (setter) setLinkForCurrentNavigation(setter);
|
|
756
797
|
setPending(true);
|
|
757
798
|
React.startTransition(() => {
|
|
758
|
-
navigateClientSide(navigateHref, replace ? "replace" : "push", scroll,
|
|
799
|
+
navigateClientSide(navigateHref, replace ? "replace" : "push", scroll, false).finally(() => {
|
|
759
800
|
if (mountedRef.current) setPending(false);
|
|
760
801
|
if (setter) clearLinkForCurrentNavigation(setter);
|
|
761
802
|
});
|
package/dist/shims/metadata.d.ts
CHANGED
|
@@ -181,28 +181,19 @@ type SocialImageDescriptor = {
|
|
|
181
181
|
};
|
|
182
182
|
type IconDescriptor = {
|
|
183
183
|
url: string | URL;
|
|
184
|
-
sizes?: string;
|
|
185
184
|
type?: string;
|
|
186
|
-
media?: string;
|
|
187
|
-
};
|
|
188
|
-
type AppleIconDescriptor = {
|
|
189
|
-
url: string | URL;
|
|
190
185
|
sizes?: string;
|
|
191
|
-
|
|
186
|
+
color?: string;
|
|
187
|
+
rel?: string;
|
|
188
|
+
media?: string;
|
|
189
|
+
fetchPriority?: "high" | "low" | "auto";
|
|
192
190
|
};
|
|
193
191
|
type IconInput = string | URL | IconDescriptor;
|
|
194
|
-
type AppleIconInput = string | URL | AppleIconDescriptor;
|
|
195
|
-
type OtherIconDescriptor = {
|
|
196
|
-
rel: string;
|
|
197
|
-
url: string | URL;
|
|
198
|
-
sizes?: string;
|
|
199
|
-
type?: string;
|
|
200
|
-
};
|
|
201
192
|
type IconsMap = {
|
|
202
193
|
icon?: IconInput | IconInput[];
|
|
203
|
-
shortcut?:
|
|
204
|
-
apple?:
|
|
205
|
-
other?:
|
|
194
|
+
shortcut?: IconInput | IconInput[];
|
|
195
|
+
apple?: IconInput | IconInput[];
|
|
196
|
+
other?: IconDescriptor | IconDescriptor[];
|
|
206
197
|
};
|
|
207
198
|
type IconsMetadata = IconInput | IconInput[] | IconsMap;
|
|
208
199
|
type MetadataMergeEntry = {
|
|
@@ -263,14 +254,17 @@ type MetadataHeadProps = {
|
|
|
263
254
|
metadata: Metadata;
|
|
264
255
|
pathname?: string;
|
|
265
256
|
trailingSlash?: boolean;
|
|
257
|
+
streamedIconKey?: string;
|
|
266
258
|
};
|
|
267
259
|
declare function renderMetadataToHtml(metadata: Metadata, pathname?: string, options?: {
|
|
268
260
|
trailingSlash?: boolean;
|
|
261
|
+
streamedIconKey?: string;
|
|
269
262
|
}): string;
|
|
270
263
|
declare function MetadataHead({
|
|
271
264
|
metadata,
|
|
272
265
|
pathname,
|
|
273
|
-
trailingSlash
|
|
266
|
+
trailingSlash,
|
|
267
|
+
streamedIconKey
|
|
274
268
|
}: MetadataHeadProps): React.JSX.Element;
|
|
275
269
|
//#endregion
|
|
276
270
|
export { DEFAULT_VIEWPORT, Metadata, MetadataHead, MetadataMergeEntry, ResolvedViewport, Viewport, ViewportHead, mergeMetadata, mergeMetadataEntries, mergeViewport, postProcessMetadata, renderMetadataToHtml, resolveModuleMetadata, resolveModuleViewport };
|
package/dist/shims/metadata.js
CHANGED
|
@@ -420,12 +420,15 @@ function renderMetadataElementToHtml(node) {
|
|
|
420
420
|
"content"
|
|
421
421
|
])}>`;
|
|
422
422
|
case "link": return `<link${renderMetadataAttributes(props, [
|
|
423
|
+
"data-vinext-streamed-icon",
|
|
423
424
|
"rel",
|
|
424
425
|
"href",
|
|
425
426
|
"hrefLang",
|
|
426
|
-
"media",
|
|
427
427
|
"type",
|
|
428
|
-
"sizes"
|
|
428
|
+
"sizes",
|
|
429
|
+
"color",
|
|
430
|
+
"media",
|
|
431
|
+
"fetchPriority"
|
|
429
432
|
])}>`;
|
|
430
433
|
default: return "";
|
|
431
434
|
}
|
|
@@ -434,10 +437,11 @@ function renderMetadataToHtml(metadata, pathname = "/", options) {
|
|
|
434
437
|
return renderMetadataElementToHtml(MetadataHead({
|
|
435
438
|
metadata,
|
|
436
439
|
pathname,
|
|
437
|
-
trailingSlash: options?.trailingSlash
|
|
440
|
+
trailingSlash: options?.trailingSlash,
|
|
441
|
+
streamedIconKey: options?.streamedIconKey
|
|
438
442
|
}));
|
|
439
443
|
}
|
|
440
|
-
function MetadataHead({ metadata, pathname = "/", trailingSlash }) {
|
|
444
|
+
function MetadataHead({ metadata, pathname = "/", trailingSlash, streamedIconKey }) {
|
|
441
445
|
const elements = [];
|
|
442
446
|
let key = 0;
|
|
443
447
|
const base = metadata.metadataBase;
|
|
@@ -725,35 +729,23 @@ function MetadataHead({ metadata, pathname = "/", trailingSlash }) {
|
|
|
725
729
|
}
|
|
726
730
|
if (metadata.icons) {
|
|
727
731
|
const iconEntries = isIconsMap(metadata.icons) ? normalizeUrlDescriptorEntries(metadata.icons.icon, (url) => ({ url })) : normalizeUrlDescriptorEntries(metadata.icons, (url) => ({ url }));
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
for (const
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
...i.type ? { type: i.type } : {},
|
|
740
|
-
...i.media ? { media: i.media } : {}
|
|
741
|
-
}, key++));
|
|
742
|
-
if (isIconsMap(metadata.icons) && metadata.icons.apple) for (const a of normalizeUrlDescriptorEntries(metadata.icons.apple, (url) => ({ url }))) elements.push(/* @__PURE__ */ jsx("link", {
|
|
743
|
-
rel: "apple-touch-icon",
|
|
744
|
-
href: stringifyUrl(a.url),
|
|
745
|
-
...a.sizes ? { sizes: a.sizes } : {},
|
|
746
|
-
...a.type ? { type: a.type } : {}
|
|
747
|
-
}, key++));
|
|
748
|
-
if (isIconsMap(metadata.icons) && metadata.icons.other) {
|
|
749
|
-
const others = Array.isArray(metadata.icons.other) ? metadata.icons.other : [metadata.icons.other];
|
|
750
|
-
for (const o of others) elements.push(/* @__PURE__ */ jsx("link", {
|
|
751
|
-
rel: o.rel,
|
|
752
|
-
href: stringifyUrl(o.url),
|
|
753
|
-
...o.sizes ? { sizes: o.sizes } : {},
|
|
754
|
-
...o.type ? { type: o.type } : {}
|
|
732
|
+
let streamedIconOrder = 0;
|
|
733
|
+
const appendIcons = (entries, defaultRel) => {
|
|
734
|
+
for (const { url, rel, type, sizes, color, media, fetchPriority } of entries) elements.push(/* @__PURE__ */ jsx("link", {
|
|
735
|
+
"data-vinext-streamed-icon": streamedIconKey ? `${streamedIconKey}:${streamedIconOrder++}` : void 0,
|
|
736
|
+
rel: rel || defaultRel,
|
|
737
|
+
href: stringifyUrl(url),
|
|
738
|
+
type,
|
|
739
|
+
sizes,
|
|
740
|
+
color,
|
|
741
|
+
media,
|
|
742
|
+
fetchPriority
|
|
755
743
|
}, key++));
|
|
756
|
-
}
|
|
744
|
+
};
|
|
745
|
+
if (isIconsMap(metadata.icons) && metadata.icons.shortcut) appendIcons(normalizeUrlDescriptorEntries(metadata.icons.shortcut, (url) => ({ url })), "shortcut icon");
|
|
746
|
+
if (iconEntries.length > 0) appendIcons(iconEntries, "icon");
|
|
747
|
+
if (isIconsMap(metadata.icons) && metadata.icons.apple) appendIcons(normalizeUrlDescriptorEntries(metadata.icons.apple, (url) => ({ url })), "apple-touch-icon");
|
|
748
|
+
if (isIconsMap(metadata.icons) && metadata.icons.other) appendIcons(normalizeUrlDescriptorEntries(metadata.icons.other, (url) => ({ url })), "icon");
|
|
757
749
|
}
|
|
758
750
|
if (metadata.manifest) elements.push(/* @__PURE__ */ jsx("link", {
|
|
759
751
|
rel: "manifest",
|