vinext 1.4.1 → 1.4.3
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/README.md +5 -2
- package/dist/build/action-owner-manifest.js +1 -0
- package/dist/build/prerender-paths.d.ts +11 -1
- package/dist/build/prerender-paths.js +36 -10
- package/dist/check.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/dev-error-overlay.d.ts +2 -1
- package/dist/client/dev-error-overlay.js +8 -3
- package/dist/config/config-matchers.js +8 -4
- package/dist/config/destination-params.js +5 -2
- package/dist/config/next-config.d.ts +25 -1
- package/dist/config/next-config.js +31 -1
- package/dist/entries/app-rsc-entry.js +65 -30
- package/dist/entries/app-rsc-manifest.js +4 -0
- package/dist/entries/pages-server-entry.js +19 -4
- package/dist/index.js +37 -37
- package/dist/init-cloudflare.js +18 -2
- package/dist/init-platform.js +2 -2
- package/dist/init.js +42 -5
- package/dist/plugins/css-target.d.ts +18 -0
- package/dist/plugins/css-target.js +93 -0
- package/dist/routing/app-route-graph.d.ts +10 -0
- package/dist/routing/app-route-graph.js +15 -1
- package/dist/server/api-handler.d.ts +2 -0
- package/dist/server/api-handler.js +10 -8
- package/dist/server/app-action-forwarding.js +3 -1
- package/dist/server/app-browser-entry.js +37 -41
- package/dist/server/app-browser-error.d.ts +1 -1
- package/dist/server/app-browser-error.js +13 -4
- package/dist/server/app-browser-supplemental-refresh.d.ts +13 -0
- package/dist/server/app-browser-supplemental-refresh.js +36 -4
- package/dist/server/app-elements.d.ts +3 -0
- package/dist/server/app-elements.js +14 -1
- package/dist/server/app-fallback-renderer.js +2 -2
- package/dist/server/app-middleware.d.ts +2 -0
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.d.ts +12 -1
- package/dist/server/app-optimistic-routing.js +38 -16
- package/dist/server/app-page-boundary-render.js +4 -2
- package/dist/server/app-page-cache-render.js +1 -1
- package/dist/server/app-page-dispatch.d.ts +11 -1
- package/dist/server/app-page-dispatch.js +78 -31
- package/dist/server/app-page-element-builder.d.ts +11 -20
- package/dist/server/app-page-element-builder.js +39 -50
- package/dist/server/app-page-intercept-segment-config.d.ts +56 -0
- package/dist/server/app-page-intercept-segment-config.js +90 -0
- package/dist/server/app-page-navigation-params.d.ts +23 -0
- package/dist/server/app-page-navigation-params.js +49 -0
- package/dist/server/app-page-render.d.ts +5 -2
- package/dist/server/app-page-render.js +17 -3
- package/dist/server/app-page-request.d.ts +24 -2
- package/dist/server/app-page-request.js +10 -10
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +19 -13
- package/dist/server/app-page-segment-plan.js +9 -1
- package/dist/server/app-page-segment-state.d.ts +9 -0
- package/dist/server/app-page-segment-state.js +54 -1
- package/dist/server/app-pages-bridge.d.ts +6 -0
- package/dist/server/app-pages-bridge.js +8 -3
- package/dist/server/app-request-stage-independent-entry.js +2 -3
- package/dist/server/app-response-stage-entry.js +1 -0
- package/dist/server/app-route-module-loader.d.ts +2 -0
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-router-entry.js +2 -3
- package/dist/server/app-rsc-cache-busting.d.ts +8 -0
- package/dist/server/app-rsc-cache-busting.js +13 -1
- package/dist/server/app-rsc-combined-handler.js +2 -1
- package/dist/server/app-rsc-handler.d.ts +14 -1
- package/dist/server/app-rsc-handler.js +111 -62
- package/dist/server/app-rsc-response-finalizer.d.ts +18 -3
- package/dist/server/app-rsc-response-finalizer.js +61 -7
- package/dist/server/app-rsc-route-matching.d.ts +14 -0
- package/dist/server/app-rsc-route-matching.js +42 -18
- package/dist/server/app-server-action-execution.js +16 -10
- package/dist/server/app-ssr-entry.js +8 -0
- package/dist/server/cache-control.d.ts +2 -0
- package/dist/server/cache-control.js +3 -1
- package/dist/server/config-headers.d.ts +7 -0
- package/dist/server/config-headers.js +20 -1
- package/dist/server/image-animation.d.ts +9 -0
- package/dist/server/image-animation.js +118 -0
- package/dist/server/image-local-patterns.d.ts +21 -0
- package/dist/server/image-local-patterns.js +59 -0
- package/dist/server/image-optimization.d.ts +48 -27
- package/dist/server/image-optimization.js +316 -22
- package/dist/server/image-source-reader.d.ts +34 -0
- package/dist/server/image-source-reader.js +126 -0
- package/dist/server/metadata-route-response.d.ts +6 -1
- package/dist/server/metadata-route-response.js +46 -10
- package/dist/server/middleware-matcher.d.ts +1 -0
- package/dist/server/middleware-matcher.js +1 -1
- package/dist/server/middleware-runtime.d.ts +5 -0
- package/dist/server/middleware-runtime.js +48 -15
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +2 -1
- package/dist/server/nitro-public-files-plugin.js +20 -8
- package/dist/server/nitro-request-target-plugin.d.ts +17 -0
- package/dist/server/nitro-request-target-plugin.js +22 -0
- package/dist/server/open-redirect.d.ts +2 -1
- package/dist/server/open-redirect.js +2 -1
- package/dist/server/pages-client-assets.d.ts +1 -0
- package/dist/server/pages-data-route.d.ts +5 -1
- package/dist/server/pages-data-route.js +14 -6
- package/dist/server/pages-i18n.d.ts +7 -0
- package/dist/server/pages-i18n.js +14 -1
- package/dist/server/pages-node-compat.js +7 -3
- package/dist/server/pages-page-handler.js +4 -4
- package/dist/server/pages-request-pipeline.d.ts +9 -0
- package/dist/server/pages-request-pipeline.js +35 -15
- package/dist/server/pages-request-stage-entry.js +8 -2
- package/dist/server/pages-router-entry.js +3 -0
- package/dist/server/prod-server.d.ts +1 -1
- package/dist/server/prod-server.js +64 -62
- package/dist/server/request-pipeline.d.ts +5 -0
- package/dist/server/request-pipeline.js +11 -1
- package/dist/server/response-stage-cacheability.d.ts +7 -0
- package/dist/server/response-stage-cacheability.js +6 -5
- package/dist/server/srvx-middleware-origin.d.ts +13 -0
- package/dist/server/srvx-middleware-origin.js +19 -0
- package/dist/server/srvx-request-target.d.ts +12 -0
- package/dist/server/srvx-request-target.js +20 -0
- package/dist/server/static-file-cache.js +10 -22
- package/dist/server/worker-image-optimization.d.ts +10 -3
- package/dist/server/worker-image-optimization.js +43 -9
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/server/worker-utils.d.ts +8 -0
- package/dist/server/worker-utils.js +19 -2
- package/dist/shims/error-boundary.d.ts +6 -2
- package/dist/shims/error-boundary.js +4 -2
- package/dist/shims/image-props.d.ts +6 -0
- package/dist/shims/image-props.js +39 -3
- package/dist/shims/image.js +3 -3
- package/dist/shims/request-context.d.ts +3 -1
- package/dist/shims/slot.d.ts +3 -0
- package/dist/shims/slot.js +67 -9
- package/dist/shims/url-utils.js +6 -1
- package/dist/utils/base-path.d.ts +7 -0
- package/dist/utils/base-path.js +11 -1
- package/dist/utils/client-entry-manifest.d.ts +5 -0
- package/dist/utils/client-entry-manifest.js +1 -0
- package/dist/utils/client-runtime-metadata.d.ts +5 -0
- package/dist/utils/client-runtime-metadata.js +33 -7
- package/package.json +1 -1
|
@@ -30,6 +30,16 @@ function canonicalizeRequestUrlPathname(url) {
|
|
|
30
30
|
return canonicalizeRequestPathname(pathname) + search;
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
+
* Whether the pathname has a segment the URL parser resolves as `.` or `..`,
|
|
34
|
+
* literally or percent-encoded. Such a pathname changes when it becomes a URL.
|
|
35
|
+
*/
|
|
36
|
+
function hasUrlParserDotSegment(pathname) {
|
|
37
|
+
return pathname.split("/").some((segment) => {
|
|
38
|
+
const decodedDots = segment.replaceAll(/%2e/gi, ".");
|
|
39
|
+
return decodedDots === "." || decodedDots === "..";
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
33
43
|
* Shared request pipeline utilities.
|
|
34
44
|
*
|
|
35
45
|
* Extracted from generated entries and server hot paths to keep codegen focused
|
|
@@ -472,4 +482,4 @@ function stripRequestUrlFragment(request) {
|
|
|
472
482
|
return attachRequestCfMetadata(new Request(stripped, { signal }), request);
|
|
473
483
|
}
|
|
474
484
|
//#endregion
|
|
475
|
-
export { INTERNAL_HEADERS, VINEXT_INTERNAL_HEADERS, attachRequestCfMetadata, canonicalizeRequestPathname, canonicalizeRequestUrlPathname, cloneRequestWithHeaders, cloneRequestWithUrl, createStaticFileSignal, dropEmptyMiddlewareSetCookie, filterInternalHeaders, getRepeatedSlashRedirect, guardProtocolRelativeUrl, hasBasePath, haveSameHeaders, isOpenRedirectShaped, isOriginAllowed, normalizeTrailingSlash, normalizeTrailingSlashPathname, processMiddlewareHeaders, resolvePublicFileRoute, sendRepeatedSlashRedirect, stripBasePath, stripRequestUrlFragment, validateCsrfOrigin, validateServerActionPayload, withRequestHeaders };
|
|
485
|
+
export { INTERNAL_HEADERS, VINEXT_INTERNAL_HEADERS, attachRequestCfMetadata, canonicalizeRequestPathname, canonicalizeRequestUrlPathname, cloneRequestWithHeaders, cloneRequestWithUrl, createStaticFileSignal, dropEmptyMiddlewareSetCookie, filterInternalHeaders, getRepeatedSlashRedirect, guardProtocolRelativeUrl, hasBasePath, hasUrlParserDotSegment, haveSameHeaders, isOpenRedirectShaped, isOriginAllowed, normalizeTrailingSlash, normalizeTrailingSlashPathname, processMiddlewareHeaders, resolvePublicFileRoute, sendRepeatedSlashRedirect, stripBasePath, stripRequestUrlFragment, validateCsrfOrigin, validateServerActionPayload, withRequestHeaders };
|
|
@@ -23,6 +23,13 @@ export type ResponseStageCacheabilityOptions = {
|
|
|
23
23
|
* shared response drops them before admission and storage.
|
|
24
24
|
*/
|
|
25
25
|
recomposesRequestScopedHeaders?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Keeps `X-Vinext-Params` when the request scoped headers are dropped. An
|
|
28
|
+
* intercepted response's params include its target's, which the request
|
|
29
|
+
* stage doesn't match. Its identity holds the interception context, so the
|
|
30
|
+
* stored params are its own.
|
|
31
|
+
*/
|
|
32
|
+
keepsParamsHeader?: boolean;
|
|
26
33
|
/** Generated adapter registration, deferred until the response stage executes. */
|
|
27
34
|
registerCacheAdapters(): void;
|
|
28
35
|
request: Request;
|
|
@@ -24,13 +24,13 @@ async function withResponseStageCacheability(options, render) {
|
|
|
24
24
|
const stripsRequestScopedHeaders = options.recomposesRequestScopedHeaders === true && options.cache === "shared" && !options.probeMode;
|
|
25
25
|
if (!cacheability) {
|
|
26
26
|
const rendered = await render(context);
|
|
27
|
-
return stripsRequestScopedHeaders ? withoutRequestScopedHeaders(rendered) : rendered;
|
|
27
|
+
return stripsRequestScopedHeaders ? withoutRequestScopedHeaders(rendered, options.keepsParamsHeader === true) : rendered;
|
|
28
28
|
}
|
|
29
29
|
if (options.policyHeadersAppliedBeforeRender) cacheability.recordResponseStageCachePolicy(context, options.policyHeaders);
|
|
30
30
|
const state = Reflect.get(context, CACHEABILITY_REQUEST_STATE);
|
|
31
31
|
if (options.probeMode && options.forceDynamic && !options.policyHeaders?.length && state) state.patternDynamicReason = "dynamic = \"force-dynamic\"";
|
|
32
32
|
const renderedResponse = await render(context);
|
|
33
|
-
const rendered = stripsRequestScopedHeaders ? withoutRequestScopedHeaders(renderedResponse) : renderedResponse;
|
|
33
|
+
const rendered = stripsRequestScopedHeaders ? withoutRequestScopedHeaders(renderedResponse, options.keepsParamsHeader === true) : renderedResponse;
|
|
34
34
|
const response = options.policyHeadersAppliedBeforeRender ? rendered : cacheability.applyResponseStageCachePolicy(rendered, context, options.policyHeaders);
|
|
35
35
|
const complete = (candidate) => cacheability.finalizeWorkerCacheabilityResponse(candidate, context);
|
|
36
36
|
const route = state?.route;
|
|
@@ -40,10 +40,11 @@ async function withResponseStageCacheability(options, render) {
|
|
|
40
40
|
}
|
|
41
41
|
return complete(response);
|
|
42
42
|
}
|
|
43
|
-
function withoutRequestScopedHeaders(response) {
|
|
44
|
-
|
|
43
|
+
function withoutRequestScopedHeaders(response, keepsParams) {
|
|
44
|
+
const dropsParams = !keepsParams && response.headers.has("X-Vinext-Params");
|
|
45
|
+
if (!dropsParams && !response.headers.has("X-Vinext-Rendered-Path-And-Search")) return response;
|
|
45
46
|
const headers = new Headers(response.headers);
|
|
46
|
-
headers.delete(VINEXT_PARAMS_HEADER);
|
|
47
|
+
if (dropsParams) headers.delete(VINEXT_PARAMS_HEADER);
|
|
47
48
|
headers.delete(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER);
|
|
48
49
|
return preserveFullyBufferedBodyMetadata(response, new Response(response.body, {
|
|
49
50
|
headers,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/server/srvx-middleware-origin.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The server-owned origin middleware runs against when srvx serves the
|
|
4
|
+
* request on Node. srvx builds `request.url` from the client's Host and
|
|
5
|
+
* `X-Forwarded-Proto` headers, which must not decide whether a rewrite to
|
|
6
|
+
* another host is external, so like the Node production server (and Next.js,
|
|
7
|
+
* which uses its hostname and port) this uses the socket's TLS state and
|
|
8
|
+
* local port, or a trusted `X-Forwarded-Proto` and `X-Forwarded-Host`.
|
|
9
|
+
* Undefined on other hosts, and on Vercel, which routes by hostname like
|
|
10
|
+
* Workers; they keep the request URL's origin.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveSrvxMiddlewareOrigin(request: Request): string | undefined;
|
|
13
|
+
//#endregion
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { resolveRequestProtocol, resolveTrustedForwardedHost } from "./proxy-trust.js";
|
|
2
|
+
//#region src/server/srvx-middleware-origin.ts
|
|
3
|
+
/**
|
|
4
|
+
* The server-owned origin middleware runs against when srvx serves the
|
|
5
|
+
* request on Node. srvx builds `request.url` from the client's Host and
|
|
6
|
+
* `X-Forwarded-Proto` headers, which must not decide whether a rewrite to
|
|
7
|
+
* another host is external, so like the Node production server (and Next.js,
|
|
8
|
+
* which uses its hostname and port) this uses the socket's TLS state and
|
|
9
|
+
* local port, or a trusted `X-Forwarded-Proto` and `X-Forwarded-Host`.
|
|
10
|
+
* Undefined on other hosts, and on Vercel, which routes by hostname like
|
|
11
|
+
* Workers; they keep the request URL's origin.
|
|
12
|
+
*/
|
|
13
|
+
function resolveSrvxMiddlewareOrigin(request) {
|
|
14
|
+
const socket = request.runtime?.node?.req?.socket;
|
|
15
|
+
if (!socket || process.env.VERCEL) return void 0;
|
|
16
|
+
return `${socket.encrypted === true || resolveRequestProtocol(request.headers) === "https" ? "https:" : "http:"}//${resolveTrustedForwardedHost(request.headers) ?? (socket.localPort === void 0 ? "localhost" : `localhost:${socket.localPort}`)}`;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { resolveSrvxMiddlewareOrigin };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/server/srvx-request-target.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Whether srvx, serving the request on Node, got a request target that is not
|
|
4
|
+
* origin-form (`GET https://other.example/x`). srvx then takes the origin of
|
|
5
|
+
* `request.url` from the target, as RFC 9112 §3.2.2 asks of an origin server.
|
|
6
|
+
* `vinext start` 404s every such target (see `getRepeatedSlashRedirect`) and
|
|
7
|
+
* Next.js never routes one, so the request-based entries Nitro calls refuse
|
|
8
|
+
* them too. The raw target is the one `nitroRequestTargetPlugin` saved before
|
|
9
|
+
* h3 could rewrite `req.url`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isSrvxAbsoluteFormTarget(request: Request): boolean;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { NITRO_REQUEST_TARGET_KEY } from "./nitro-request-target-plugin.js";
|
|
2
|
+
//#region src/server/srvx-request-target.ts
|
|
3
|
+
/**
|
|
4
|
+
* Whether srvx, serving the request on Node, got a request target that is not
|
|
5
|
+
* origin-form (`GET https://other.example/x`). srvx then takes the origin of
|
|
6
|
+
* `request.url` from the target, as RFC 9112 §3.2.2 asks of an origin server.
|
|
7
|
+
* `vinext start` 404s every such target (see `getRepeatedSlashRedirect`) and
|
|
8
|
+
* Next.js never routes one, so the request-based entries Nitro calls refuse
|
|
9
|
+
* them too. The raw target is the one `nitroRequestTargetPlugin` saved before
|
|
10
|
+
* h3 could rewrite `req.url`.
|
|
11
|
+
*/
|
|
12
|
+
function isSrvxAbsoluteFormTarget(request) {
|
|
13
|
+
const req = request.runtime?.node?.req;
|
|
14
|
+
if (!req) return false;
|
|
15
|
+
const saved = Reflect.get(req, Symbol.for(NITRO_REQUEST_TARGET_KEY));
|
|
16
|
+
const target = typeof saved === "string" ? saved : req.url;
|
|
17
|
+
return !!target && !target.startsWith("/");
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { isSrvxAbsoluteFormTarget };
|
|
@@ -29,9 +29,11 @@ const CONTENT_TYPES = {
|
|
|
29
29
|
".css": "text/css; charset=utf-8",
|
|
30
30
|
".html": "text/html; charset=utf-8",
|
|
31
31
|
".ico": "image/x-icon",
|
|
32
|
+
".icns": "image/x-icns",
|
|
32
33
|
".jpeg": "image/jpeg",
|
|
33
34
|
".jpg": "image/jpeg",
|
|
34
35
|
".json": "application/json; charset=utf-8",
|
|
36
|
+
".jxl": "image/jxl",
|
|
35
37
|
".map": "application/json; charset=utf-8",
|
|
36
38
|
".mp3": "audio/mpeg",
|
|
37
39
|
".mp4": "video/mp4",
|
|
@@ -148,30 +150,16 @@ var StaticFileCache = class StaticFileCache {
|
|
|
148
150
|
}
|
|
149
151
|
const pathname = "/" + relativePath;
|
|
150
152
|
entries.set(pathname, entry);
|
|
151
|
-
if (ext === ".html") {
|
|
152
|
-
if (relativePath.endsWith("/index.html")) {
|
|
153
|
-
const dirPath = "/" + relativePath.slice(0, -11);
|
|
154
|
-
if (dirPath !== "/") entries.set(dirPath, entry);
|
|
155
|
-
} else {
|
|
156
|
-
const withoutExt = "/" + relativePath.slice(0, -ext.length);
|
|
157
|
-
entries.set(withoutExt, entry);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
153
|
}
|
|
161
154
|
const toBuffer = [];
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
entry.zst
|
|
171
|
-
]) {
|
|
172
|
-
if (!variant || variant.size > BUFFER_THRESHOLD) continue;
|
|
173
|
-
toBuffer.push(variant);
|
|
174
|
-
}
|
|
155
|
+
for (const entry of entries.values()) for (const variant of [
|
|
156
|
+
entry.original,
|
|
157
|
+
entry.br,
|
|
158
|
+
entry.gz,
|
|
159
|
+
entry.zst
|
|
160
|
+
]) {
|
|
161
|
+
if (!variant || variant.size > BUFFER_THRESHOLD) continue;
|
|
162
|
+
toBuffer.push(variant);
|
|
175
163
|
}
|
|
176
164
|
for (let i = 0; i < toBuffer.length; i += 64) await Promise.all(toBuffer.slice(i, i + 64).map(async (v) => {
|
|
177
165
|
v.buffer = await fsp.readFile(v.path);
|
|
@@ -19,16 +19,23 @@ export type WorkerImageSourceOptions = {
|
|
|
19
19
|
* served only when the application pipeline selects a public file for it.
|
|
20
20
|
*/
|
|
21
21
|
export declare function fetchWorkerImageSource(imageUrl: string, request: Request, options: WorkerImageSourceOptions): Promise<Response>;
|
|
22
|
+
/**
|
|
23
|
+
* Give a public-file source the Cache-Control middleware or `headers()` staged
|
|
24
|
+
* for it, which a direct request receives in place of the asset default and
|
|
25
|
+
* Next.js' internal source fetch reads.
|
|
26
|
+
*/
|
|
27
|
+
export declare function withStagedCacheControl(asset: Response, cacheControl: string | null): Response;
|
|
22
28
|
/**
|
|
23
29
|
* Return the public file a framework static-file signal selects, provided the
|
|
24
30
|
* pipeline answered with a body-bearing 2xx outcome. The file is fetched with middleware's
|
|
25
|
-
* request header overrides, as resolveStaticAssetSignal fetches it
|
|
31
|
+
* request header overrides, as resolveStaticAssetSignal fetches it, and keeps
|
|
32
|
+
* the Cache-Control the pipeline staged.
|
|
26
33
|
*/
|
|
27
34
|
export declare function fetchSignalledPublicFile(response: Response, sourceRequest: Request, assets: VinextAssetFetcher): Promise<Response> | null;
|
|
28
35
|
/**
|
|
29
36
|
* Serve the App Router image endpoint once the request handler admitted it
|
|
30
|
-
* through middleware and rewrites.
|
|
31
|
-
* the image, as Next.js does.
|
|
37
|
+
* through middleware and rewrites. Config and middleware response headers are
|
|
38
|
+
* sent with the image, as Next.js does.
|
|
32
39
|
*/
|
|
33
40
|
export declare function serveWorkerImageOptimization(request: Request, signal: ImageOptimizationSignal, allowedWidths: number[] | undefined, imageConfig: ImageConfig | undefined, options: WorkerImageSourceOptions): Promise<Response>;
|
|
34
41
|
//#endregion
|
|
@@ -2,7 +2,7 @@ import { VINEXT_PRERENDER_SPECIAL_ERROR_HEADER } from "./headers.js";
|
|
|
2
2
|
import { readStaticFileSignal, readStaticFileSignalRequestHeaders } from "./static-file-signal.js";
|
|
3
3
|
import { attachRequestCfMetadata, cloneRequestWithUrl } from "./request-pipeline.js";
|
|
4
4
|
import { isNextStaticPath } from "../utils/asset-prefix.js";
|
|
5
|
-
import { handleConfiguredImageOptimization, invalidImageSourceResponse, isImageSourceBodyStatus } from "./image-optimization.js";
|
|
5
|
+
import { handleConfiguredImageOptimization, invalidImageSourceResponse, isImageSourceBodyStatus, markImageBuildAsset } from "./image-optimization.js";
|
|
6
6
|
import { createStaticAssetRequest, mergeHeaders } from "./worker-utils.js";
|
|
7
7
|
import { resolveClientBuildFile } from "./client-build-files.js";
|
|
8
8
|
//#region src/server/worker-image-optimization.ts
|
|
@@ -53,33 +53,52 @@ async function fetchWorkerImageSource(imageUrl, request, options) {
|
|
|
53
53
|
} catch {
|
|
54
54
|
return invalidImageSourceResponse();
|
|
55
55
|
}
|
|
56
|
-
const
|
|
57
|
-
if (
|
|
56
|
+
const nextStaticFile = resolveNextStaticFile(decodedPathname, options);
|
|
57
|
+
if (nextStaticFile !== null) return markImageBuildAsset(await options.assets.fetch(new Request(new URL(nextStaticFile, request.url))));
|
|
58
|
+
const clientBuildFile = resolveClientBuildFile(sourceUrl.pathname, options.basePath, options.clientBuildFiles);
|
|
59
|
+
if (clientBuildFile !== null) return options.assets.fetch(new Request(new URL(clientBuildFile, request.url)));
|
|
58
60
|
const sourceResponse = await options.fetchPublicFile(attachRequestCfMetadata(new Request(sourceUrl, { signal: request.signal }), request));
|
|
59
61
|
if (sourceResponse && isImageSourceBodyStatus(sourceResponse.status)) return sourceResponse;
|
|
60
62
|
if (sourceResponse) cancelResponseBody(sourceResponse);
|
|
61
63
|
return invalidImageSourceResponse();
|
|
62
64
|
}
|
|
63
65
|
/**
|
|
66
|
+
* Give a public-file source the Cache-Control middleware or `headers()` staged
|
|
67
|
+
* for it, which a direct request receives in place of the asset default and
|
|
68
|
+
* Next.js' internal source fetch reads.
|
|
69
|
+
*/
|
|
70
|
+
function withStagedCacheControl(asset, cacheControl) {
|
|
71
|
+
if (cacheControl === null) return asset;
|
|
72
|
+
const headers = new Headers(asset.headers);
|
|
73
|
+
headers.set("Cache-Control", cacheControl);
|
|
74
|
+
return new Response(asset.body, {
|
|
75
|
+
status: asset.status,
|
|
76
|
+
statusText: asset.statusText,
|
|
77
|
+
headers
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
64
81
|
* Return the public file a framework static-file signal selects, provided the
|
|
65
82
|
* pipeline answered with a body-bearing 2xx outcome. The file is fetched with middleware's
|
|
66
|
-
* request header overrides, as resolveStaticAssetSignal fetches it
|
|
83
|
+
* request header overrides, as resolveStaticAssetSignal fetches it, and keeps
|
|
84
|
+
* the Cache-Control the pipeline staged.
|
|
67
85
|
*/
|
|
68
86
|
function fetchSignalledPublicFile(response, sourceRequest, assets) {
|
|
69
87
|
const signal = isImageSourceBodyStatus(response.status) ? readStaticFileSignal(response) : null;
|
|
70
88
|
const requestHeaders = readStaticFileSignalRequestHeaders(response);
|
|
89
|
+
const stagedCacheControl = response.headers.get("Cache-Control");
|
|
71
90
|
cancelResponseBody(response);
|
|
72
91
|
if (signal === null) return null;
|
|
73
92
|
let assetPath = signal;
|
|
74
93
|
try {
|
|
75
94
|
assetPath = decodeURIComponent(signal);
|
|
76
95
|
} catch {}
|
|
77
|
-
return Promise.resolve(assets.fetch(createStaticAssetRequest(assetPath, sourceRequest, requestHeaders)));
|
|
96
|
+
return Promise.resolve(assets.fetch(createStaticAssetRequest(assetPath, sourceRequest, requestHeaders))).then((asset) => withStagedCacheControl(asset, stagedCacheControl));
|
|
78
97
|
}
|
|
79
98
|
/**
|
|
80
99
|
* Serve the App Router image endpoint once the request handler admitted it
|
|
81
|
-
* through middleware and rewrites.
|
|
82
|
-
* the image, as Next.js does.
|
|
100
|
+
* through middleware and rewrites. Config and middleware response headers are
|
|
101
|
+
* sent with the image, as Next.js does.
|
|
83
102
|
*/
|
|
84
103
|
async function serveWorkerImageOptimization(request, signal, allowedWidths, imageConfig, options) {
|
|
85
104
|
const imageUrl = new URL(request.url);
|
|
@@ -93,7 +112,22 @@ async function serveWorkerImageOptimization(request, signal, allowedWidths, imag
|
|
|
93
112
|
});
|
|
94
113
|
const cookies = signal.middlewareHeaders.getSetCookie();
|
|
95
114
|
if (cookies.length > 0) middlewareHeaders["set-cookie"] = cookies;
|
|
96
|
-
|
|
115
|
+
const merged = mergeHeaders(response, middlewareHeaders);
|
|
116
|
+
if (response.status < 400) return merged;
|
|
117
|
+
const errorHeaders = new Headers(merged.headers);
|
|
118
|
+
let replaced = false;
|
|
119
|
+
for (const name of ["content-type", "content-encoding"]) {
|
|
120
|
+
const value = signal.middlewareHeaders.get(name);
|
|
121
|
+
if (value === null) continue;
|
|
122
|
+
errorHeaders.set(name, value);
|
|
123
|
+
replaced = true;
|
|
124
|
+
}
|
|
125
|
+
if (!replaced) return merged;
|
|
126
|
+
return new Response(merged.body, {
|
|
127
|
+
headers: errorHeaders,
|
|
128
|
+
status: merged.status,
|
|
129
|
+
statusText: merged.statusText
|
|
130
|
+
});
|
|
97
131
|
}
|
|
98
132
|
//#endregion
|
|
99
|
-
export { fetchSignalledPublicFile, fetchWorkerImageSource, serveWorkerImageOptimization };
|
|
133
|
+
export { fetchSignalledPublicFile, fetchWorkerImageSource, serveWorkerImageOptimization, withStagedCacheControl };
|
|
@@ -12,6 +12,7 @@ function deriveExecutionContext(base, dispatchPagesRevalidate, isInternalPagesRe
|
|
|
12
12
|
...base?.cache === void 0 ? {} : { cache: base.cache },
|
|
13
13
|
...base?.assets === void 0 ? {} : { assets: base.assets },
|
|
14
14
|
...base?.trustedRevalidateOrigin === void 0 ? {} : { trustedRevalidateOrigin: base.trustedRevalidateOrigin },
|
|
15
|
+
...base?.middlewareOrigin === void 0 ? {} : { middlewareOrigin: base.middlewareOrigin },
|
|
15
16
|
dispatchPagesRevalidate,
|
|
16
17
|
isInternalPagesRevalidation
|
|
17
18
|
};
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
//#region src/server/worker-utils.d.ts
|
|
2
2
|
export declare function finalizeMissingStaticAssetResponse(response: Response, missingBuildAsset: boolean): Response;
|
|
3
3
|
export declare function mergeHeaders(response: Response, extraHeaders: Record<string, string | string[]>, statusOverride?: number): Response;
|
|
4
|
+
/**
|
|
5
|
+
* Merge middleware/config headers into a file served from the asset layer.
|
|
6
|
+
* Its Cache-Control is only the layer's default (Workers Static Assets sends
|
|
7
|
+
* `public, max-age=0, must-revalidate` with every file), so one set by
|
|
8
|
+
* middleware or `headers()` wins, as Next.js's static file server sets its
|
|
9
|
+
* own only when the response has none.
|
|
10
|
+
*/
|
|
11
|
+
export declare function mergeStaticFileHeaders(response: Response, extraHeaders: Record<string, string | string[]>, statusOverride?: number): Response;
|
|
4
12
|
export declare function resolveStaticAssetSignal(signalResponse: Response, options: {
|
|
5
13
|
/** `requestHeaders` are the post-middleware request headers, when middleware set any. */
|
|
6
14
|
fetchAsset(path: string, requestHeaders: Headers | null): Promise<Response>;
|
|
@@ -82,6 +82,23 @@ function mergeHeaders(response, extraHeaders, statusOverride) {
|
|
|
82
82
|
headers: merged
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Merge middleware/config headers into a file served from the asset layer.
|
|
87
|
+
* Its Cache-Control is only the layer's default (Workers Static Assets sends
|
|
88
|
+
* `public, max-age=0, must-revalidate` with every file), so one set by
|
|
89
|
+
* middleware or `headers()` wins, as Next.js's static file server sets its
|
|
90
|
+
* own only when the response has none.
|
|
91
|
+
*/
|
|
92
|
+
function mergeStaticFileHeaders(response, extraHeaders, statusOverride) {
|
|
93
|
+
const merged = mergeHeaders(response, extraHeaders, statusOverride);
|
|
94
|
+
for (const [name, value] of Object.entries(extraHeaders)) {
|
|
95
|
+
if (name.toLowerCase() !== "cache-control") continue;
|
|
96
|
+
const cacheControl = (Array.isArray(value) ? value.join(", ") : value).trim();
|
|
97
|
+
if (!cacheControl) continue;
|
|
98
|
+
merged.headers.set(name, cacheControl);
|
|
99
|
+
}
|
|
100
|
+
return merged;
|
|
101
|
+
}
|
|
85
102
|
async function resolveStaticAssetSignal(signalResponse, options) {
|
|
86
103
|
const signal = readStaticFileSignal(signalResponse);
|
|
87
104
|
if (!signal) return null;
|
|
@@ -100,7 +117,7 @@ async function resolveStaticAssetSignal(signalResponse, options) {
|
|
|
100
117
|
const requestHeaders = readStaticFileSignalRequestHeaders(signalResponse);
|
|
101
118
|
cancelResponseBody(signalResponse);
|
|
102
119
|
const assetResponse = await options.fetchAsset(assetPath, requestHeaders);
|
|
103
|
-
return
|
|
120
|
+
return mergeStaticFileHeaders(assetResponse, extraHeaders, assetResponse.ok && assetResponse.status !== 206 && signalResponse.status !== 200 ? signalResponse.status : void 0);
|
|
104
121
|
}
|
|
105
122
|
/**
|
|
106
123
|
* Retarget a Worker asset request without dropping its conditional/range
|
|
@@ -116,4 +133,4 @@ function createStaticAssetRequest(assetPath, sourceRequest, headers = null) {
|
|
|
116
133
|
});
|
|
117
134
|
}
|
|
118
135
|
//#endregion
|
|
119
|
-
export { createStaticAssetRequest, finalizeMissingStaticAssetResponse, mergeHeaders, resolveStaticAssetSignal };
|
|
136
|
+
export { createStaticAssetRequest, finalizeMissingStaticAssetResponse, mergeHeaders, mergeStaticFileHeaders, resolveStaticAssetSignal };
|
|
@@ -6,6 +6,8 @@ export type ErrorBoundaryProps = {
|
|
|
6
6
|
reset: () => void;
|
|
7
7
|
}>;
|
|
8
8
|
children: React.ReactNode;
|
|
9
|
+
/** Whether this boundary renders global-error, at the root of the page. */
|
|
10
|
+
isGlobalErrorBoundary?: boolean;
|
|
9
11
|
resetKey?: string | null;
|
|
10
12
|
};
|
|
11
13
|
export type SerializedBoundaryError = {
|
|
@@ -38,6 +40,7 @@ type RedirectBoundaryProps = {
|
|
|
38
40
|
type ErrorBoundaryInnerProps = {
|
|
39
41
|
isImplicitRootErrorBoundary?: boolean;
|
|
40
42
|
pathname: string | null;
|
|
43
|
+
wrapsGlobalErrorBoundary?: boolean;
|
|
41
44
|
} & ErrorBoundaryProps;
|
|
42
45
|
export type ErrorBoundaryState = {
|
|
43
46
|
error: CapturedError | null;
|
|
@@ -66,13 +69,14 @@ export declare class ErrorBoundaryInner extends React.Component<ErrorBoundaryInn
|
|
|
66
69
|
reset: () => void;
|
|
67
70
|
render(): string | number | bigint | boolean | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | Iterable<React.ReactNode> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactPortal | null | undefined> | null | undefined;
|
|
68
71
|
}
|
|
69
|
-
export declare function ErrorBoundary({ fallback, children, resetKey }: ErrorBoundaryProps): React.JSX.Element;
|
|
70
|
-
export declare function GlobalErrorBoundary({ fallback, children }: {
|
|
72
|
+
export declare function ErrorBoundary({ fallback, children, isGlobalErrorBoundary, resetKey }: ErrorBoundaryProps): React.JSX.Element;
|
|
73
|
+
export declare function GlobalErrorBoundary({ fallback, children, wrapsGlobalErrorBoundary }: {
|
|
71
74
|
fallback: React.ComponentType<{
|
|
72
75
|
error: unknown;
|
|
73
76
|
reset: () => void;
|
|
74
77
|
}>;
|
|
75
78
|
children: React.ReactNode;
|
|
79
|
+
wrapsGlobalErrorBoundary?: boolean;
|
|
76
80
|
}): React.JSX.Element;
|
|
77
81
|
type NotFoundBoundaryProps = {
|
|
78
82
|
fallback: React.ReactNode;
|
|
@@ -174,21 +174,23 @@ var ErrorBoundaryInner = class extends React.Component {
|
|
|
174
174
|
return this.props.children;
|
|
175
175
|
}
|
|
176
176
|
};
|
|
177
|
-
function ErrorBoundary({ fallback, children, resetKey }) {
|
|
177
|
+
function ErrorBoundary({ fallback, children, isGlobalErrorBoundary, resetKey }) {
|
|
178
178
|
const pathname = useErrorBoundaryPathname();
|
|
179
179
|
return /* @__PURE__ */ jsx(ErrorBoundaryInner, {
|
|
180
180
|
pathname,
|
|
181
181
|
resetKey,
|
|
182
182
|
fallback,
|
|
183
|
+
isGlobalErrorBoundary,
|
|
183
184
|
children
|
|
184
185
|
});
|
|
185
186
|
}
|
|
186
|
-
function GlobalErrorBoundary({ fallback, children }) {
|
|
187
|
+
function GlobalErrorBoundary({ fallback, children, wrapsGlobalErrorBoundary }) {
|
|
187
188
|
const pathname = useErrorBoundaryPathname();
|
|
188
189
|
return /* @__PURE__ */ jsx(ErrorBoundaryInner, {
|
|
189
190
|
pathname,
|
|
190
191
|
fallback,
|
|
191
192
|
isImplicitRootErrorBoundary: fallback === DefaultGlobalError,
|
|
193
|
+
wrapsGlobalErrorBoundary,
|
|
192
194
|
children
|
|
193
195
|
});
|
|
194
196
|
}
|
|
@@ -71,6 +71,12 @@ export declare function resolveImageSource(v: {
|
|
|
71
71
|
* Configurable via `images.deviceSizes` in next.config.js.
|
|
72
72
|
*/
|
|
73
73
|
export declare const RESPONSIVE_WIDTHS: number[];
|
|
74
|
+
/**
|
|
75
|
+
* Parse a `quality` prop like Next.js's `getInt` (shared/lib/get-img-props.ts):
|
|
76
|
+
* finite numbers and digit-only strings pass, anything else becomes NaN, which
|
|
77
|
+
* the default loader treats as 75.
|
|
78
|
+
*/
|
|
79
|
+
export declare function parseImageQuality(quality: unknown): number | undefined;
|
|
74
80
|
/**
|
|
75
81
|
* Build a `/_next/image` optimization URL.
|
|
76
82
|
*
|
|
@@ -52,6 +52,14 @@ const __imageSizes = (() => {
|
|
|
52
52
|
];
|
|
53
53
|
}
|
|
54
54
|
})();
|
|
55
|
+
const __imageQualities = (() => {
|
|
56
|
+
try {
|
|
57
|
+
const qualities = JSON.parse(process.env.__VINEXT_IMAGE_QUALITIES ?? "null");
|
|
58
|
+
return Array.isArray(qualities) ? qualities.sort((a, b) => a - b) : null;
|
|
59
|
+
} catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
})();
|
|
55
63
|
/**
|
|
56
64
|
* Whether dangerouslyAllowSVG is enabled in next.config.js.
|
|
57
65
|
* When false (default), .svg sources auto-skip the optimization endpoint
|
|
@@ -195,6 +203,33 @@ function extractLocalDeploymentId(src) {
|
|
|
195
203
|
}
|
|
196
204
|
const __imageEndpoint = `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/_next/image${process.env.__VINEXT_TRAILING_SLASH === "true" ? "/" : ""}`;
|
|
197
205
|
/**
|
|
206
|
+
* Parse a `quality` prop like Next.js's `getInt` (shared/lib/get-img-props.ts):
|
|
207
|
+
* finite numbers and digit-only strings pass, anything else becomes NaN, which
|
|
208
|
+
* the default loader treats as 75.
|
|
209
|
+
*/
|
|
210
|
+
function parseImageQuality(quality) {
|
|
211
|
+
if (quality === void 0) return void 0;
|
|
212
|
+
if (typeof quality === "number") return Number.isFinite(quality) ? quality : NaN;
|
|
213
|
+
if (typeof quality === "string" && /^[0-9]+$/.test(quality)) return parseInt(quality, 10);
|
|
214
|
+
return NaN;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Round a `quality` prop to the closest entry of `images.qualities`, as the
|
|
218
|
+
* Next.js default loader does (shared/lib/find-closest-quality.ts), so the
|
|
219
|
+
* URL is one the optimization endpoint accepts.
|
|
220
|
+
*
|
|
221
|
+
* With no list configured the prop is used as written (75 when absent). This
|
|
222
|
+
* is deliberate: Next.js 16 defaults the list to `[75]` and would round every
|
|
223
|
+
* quality to 75, but vinext keeps the Next.js 14/15 behaviour for an unset
|
|
224
|
+
* list so migrating apps keep the qualities they ask for (see
|
|
225
|
+
* ImageConfig.qualities in server/image-optimization.ts).
|
|
226
|
+
*/
|
|
227
|
+
function findClosestQuality(quality) {
|
|
228
|
+
const q = quality || 75;
|
|
229
|
+
if (!__imageQualities?.length) return q;
|
|
230
|
+
return __imageQualities.reduce((prev, cur) => Math.abs(cur - q) < Math.abs(prev - q) ? cur : prev, __imageQualities[0]);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
198
233
|
* Build a `/_next/image` optimization URL.
|
|
199
234
|
*
|
|
200
235
|
* In production (Cloudflare Workers), the worker intercepts this path and uses
|
|
@@ -202,9 +237,10 @@ const __imageEndpoint = `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/_next/image
|
|
|
202
237
|
* server handles it as a passthrough (serves the original file).
|
|
203
238
|
*/
|
|
204
239
|
function imageOptimizationUrl(src, width, quality = 75) {
|
|
240
|
+
const q = findClosestQuality(quality);
|
|
205
241
|
const source = extractLocalDeploymentId(src);
|
|
206
242
|
const deploymentQuery = source.src.startsWith("/") && source.deploymentId ? `&dpl=${source.deploymentId}` : "";
|
|
207
|
-
return `${__imageEndpoint}?url=${encodeURIComponent(source.src)}&w=${width}&q=${
|
|
243
|
+
return `${__imageEndpoint}?url=${encodeURIComponent(source.src)}&w=${width}&q=${q}${deploymentQuery}`;
|
|
208
244
|
}
|
|
209
245
|
/**
|
|
210
246
|
* Generate a srcSet string for responsive images.
|
|
@@ -283,7 +319,7 @@ function getImageProps(props) {
|
|
|
283
319
|
}
|
|
284
320
|
}
|
|
285
321
|
}
|
|
286
|
-
const imgQuality =
|
|
322
|
+
const imgQuality = parseImageQuality(_quality) ?? 75;
|
|
287
323
|
const resolvedSrc = blockedInProd ? "" : loader ? loader({
|
|
288
324
|
src,
|
|
289
325
|
width: imgWidth ?? 0,
|
|
@@ -320,4 +356,4 @@ function getImageProps(props) {
|
|
|
320
356
|
return { props: Object.assign(imageProps, { "data-nimg": fill ? "fill" : "1" }) };
|
|
321
357
|
}
|
|
322
358
|
//#endregion
|
|
323
|
-
export { RESPONSIVE_WIDTHS, __dangerouslyAllowSVG, __globallyUnoptimized, __isDev, generateImageAttributes, getFillStyle, getImageProps, imageOptimizationUrl, isRemoteUrl, isSvgUrl, resolveImageSource, sanitizeBlurDataURL, validateRemoteUrl };
|
|
359
|
+
export { RESPONSIVE_WIDTHS, __dangerouslyAllowSVG, __globallyUnoptimized, __isDev, generateImageAttributes, getFillStyle, getImageProps, imageOptimizationUrl, isRemoteUrl, isSvgUrl, parseImageQuality, resolveImageSource, sanitizeBlurDataURL, validateRemoteUrl };
|
package/dist/shims/image.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useMergedRef } from "./use-merged-ref.js";
|
|
3
|
-
import { RESPONSIVE_WIDTHS, __dangerouslyAllowSVG, __globallyUnoptimized, __isDev, generateImageAttributes, getFillStyle, getImageProps, imageOptimizationUrl, isRemoteUrl, isSvgUrl, resolveImageSource, sanitizeBlurDataURL, validateRemoteUrl } from "./image-props.js";
|
|
3
|
+
import { RESPONSIVE_WIDTHS, __dangerouslyAllowSVG, __globallyUnoptimized, __isDev, generateImageAttributes, getFillStyle, getImageProps, imageOptimizationUrl, isRemoteUrl, isSvgUrl, parseImageQuality, resolveImageSource, sanitizeBlurDataURL, validateRemoteUrl } from "./image-props.js";
|
|
4
4
|
import { forwardRef, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
import * as ReactDOM from "react-dom";
|
|
@@ -197,7 +197,7 @@ const Image = forwardRef(function Image({ src: srcProp, alt, width, height, fill
|
|
|
197
197
|
});
|
|
198
198
|
}
|
|
199
199
|
if (loader) {
|
|
200
|
-
const resolvedQuality =
|
|
200
|
+
const resolvedQuality = parseImageQuality(quality) ?? 75;
|
|
201
201
|
const resolvedSrc = loader({
|
|
202
202
|
src,
|
|
203
203
|
width: imgWidth ?? 0,
|
|
@@ -293,7 +293,7 @@ const Image = forwardRef(function Image({ src: srcProp, alt, width, height, fill
|
|
|
293
293
|
});
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
|
-
const imgQuality =
|
|
296
|
+
const imgQuality = parseImageQuality(quality) ?? 75;
|
|
297
297
|
const skipOptimization = isSvgUrl(src) && !__dangerouslyAllowSVG;
|
|
298
298
|
const optimizedAttributes = imgWidth && !fill && !skipOptimization ? generateImageAttributes(src, imgWidth, imgQuality, sizes) : void 0;
|
|
299
299
|
const srcSet = optimizedAttributes ? optimizedAttributes.srcSet : imgWidth && !fill ? RESPONSIVE_WIDTHS.filter((w) => w <= imgWidth * 2).map((w) => `${src} ${w}w`).join(", ") || `${src} ${imgWidth}w` : void 0;
|
|
@@ -46,7 +46,9 @@ export type ExecutionContextLike = {
|
|
|
46
46
|
requestSignal?: AbortSignal;
|
|
47
47
|
/**
|
|
48
48
|
* Server-owned origin middleware runs against. Set by the Node production
|
|
49
|
-
* server
|
|
49
|
+
* server and by entries that srvx serves on Node (Nitro's Node presets,
|
|
50
|
+
* @vitejs/plugin-rsc's dev and preview handlers), whose request URL comes
|
|
51
|
+
* from the client's Host header. Without it
|
|
50
52
|
* middleware uses the request URL's origin, which Workers can trust because
|
|
51
53
|
* the platform routes by hostname.
|
|
52
54
|
*/
|
package/dist/shims/slot.d.ts
CHANGED
|
@@ -28,10 +28,13 @@ export declare function setAppElementsRenderedSearch(elements: AppElements, sear
|
|
|
28
28
|
* that arrives after the head (initial hydration) is still seen.
|
|
29
29
|
*/
|
|
30
30
|
export declare function bindAppElementsRenderedSearch(elements: AppElements, snapshot: Pick<ClientNavigationRenderSnapshot, "renderedSearch" | "search">): void;
|
|
31
|
+
export declare function isBfcacheIdentityRetained(identity: string): boolean;
|
|
31
32
|
export declare const BfcacheIdentityMapContext: React$1.Context<Readonly<Record<string, string>>>;
|
|
32
33
|
export type BfcacheSlotEntry = {
|
|
33
34
|
content: React$1.ReactNode;
|
|
34
35
|
elements?: AppElements;
|
|
36
|
+
/** Every entry key inside a hidden entry, its own included. */
|
|
37
|
+
retainedKeys?: readonly string[];
|
|
35
38
|
segmentId?: string;
|
|
36
39
|
stateKey: string;
|
|
37
40
|
stateKeyMap?: Readonly<Record<string, string>>;
|