@wular/pnext 0.0.1
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 +153 -0
- package/bin/pnext +67 -0
- package/config/lint/base.js +48 -0
- package/config/ts/base.json +26 -0
- package/config/ts/react.json +13 -0
- package/package.json +70 -0
- package/reference/compat.md +63 -0
- package/reference/config.md +120 -0
- package/reference/css.md +58 -0
- package/reference/dev.md +69 -0
- package/reference/env.md +40 -0
- package/reference/metadata.md +86 -0
- package/reference/navigation.md +149 -0
- package/reference/overview.md +35 -0
- package/reference/performance.md +97 -0
- package/reference/rendering.md +127 -0
- package/reference/routing.md +167 -0
- package/reference/typegen.md +64 -0
- package/src/api/cache.ts +80 -0
- package/src/api/client-cache.ts +9 -0
- package/src/api/client-navigation.ts +279 -0
- package/src/api/dynamic.tsx +102 -0
- package/src/api/link.tsx +119 -0
- package/src/api/navigation.ts +198 -0
- package/src/api/router/events.ts +53 -0
- package/src/api/router/history.ts +70 -0
- package/src/api/router/hub.ts +194 -0
- package/src/api/router/policies.ts +107 -0
- package/src/api/router/runtime.ts +5238 -0
- package/src/api/router/types.ts +299 -0
- package/src/api/router.ts +167 -0
- package/src/api/server.ts +323 -0
- package/src/api/suspense.ts +16 -0
- package/src/cache/context.ts +61 -0
- package/src/cli/adapters/vercel-warm.ts +375 -0
- package/src/cli/adapters/vercel.ts +1310 -0
- package/src/cli/analyze-print.ts +181 -0
- package/src/cli/analyze.ts +328 -0
- package/src/cli/boot-trace.ts +29 -0
- package/src/cli/build.ts +3114 -0
- package/src/cli/dev.ts +276 -0
- package/src/cli/index.ts +196 -0
- package/src/cli/named-bin.ts +119 -0
- package/src/cli/serve-ui.ts +160 -0
- package/src/cli/start.ts +1425 -0
- package/src/client/build.ts +2136 -0
- package/src/client/chunk-fold.ts +526 -0
- package/src/client/entry.ts +1525 -0
- package/src/client/paths.ts +22 -0
- package/src/client/prebuilt.ts +621 -0
- package/src/client/profile.ts +75 -0
- package/src/client/react-compiler.ts +94 -0
- package/src/client/reference-stub.ts +145 -0
- package/src/client/reference.ts +47 -0
- package/src/compat/actions/action-client.ts +531 -0
- package/src/compat/actions/action-dispatch.ts +676 -0
- package/src/compat/actions/action-router.ts +40 -0
- package/src/compat/actions/action-shared.ts +95 -0
- package/src/compat/actions/client-plugin.ts +135 -0
- package/src/compat/actions/client-stub.ts +65 -0
- package/src/compat/actions/config.ts +164 -0
- package/src/compat/actions/detect.ts +208 -0
- package/src/compat/actions/discovery.ts +244 -0
- package/src/compat/actions/early-submit.ts +40 -0
- package/src/compat/actions/endpoint.ts +602 -0
- package/src/compat/actions/flight.ts +52 -0
- package/src/compat/actions/form-state.ts +73 -0
- package/src/compat/actions/hoist.ts +485 -0
- package/src/compat/actions/ids.ts +39 -0
- package/src/compat/actions/index.ts +41 -0
- package/src/compat/actions/instances.ts +144 -0
- package/src/compat/actions/origin.ts +109 -0
- package/src/compat/actions/protocol.ts +125 -0
- package/src/compat/actions/registry.ts +74 -0
- package/src/compat/actions/rewrite.ts +282 -0
- package/src/compat/actions/serve.ts +414 -0
- package/src/compat/actions/server-tag.ts +21 -0
- package/src/compat/actions/unrecognized-error.ts +30 -0
- package/src/compat/adapter/build-complete.ts +257 -0
- package/src/compat/bundler/bun-externals.ts +53 -0
- package/src/compat/bundler/cjs-exports.ts +542 -0
- package/src/compat/bundler/config.ts +363 -0
- package/src/compat/bundler/externals.ts +34 -0
- package/src/compat/bundler/import-meta-url.ts +60 -0
- package/src/compat/bundler/modularize-imports.ts +119 -0
- package/src/compat/bundler/new-url-asset.ts +87 -0
- package/src/compat/bundler/optimize-package-imports.ts +273 -0
- package/src/compat/bundler/polyfill.ts +88 -0
- package/src/compat/bundler/react-compiler.ts +61 -0
- package/src/compat/bundler/react-profiler.tsx +25 -0
- package/src/compat/bundler/relay-transform.ts +116 -0
- package/src/compat/bundler/require-context.ts +281 -0
- package/src/compat/bundler/resolve-extensions.ts +75 -0
- package/src/compat/bundler/source-cache.ts +61 -0
- package/src/compat/bundler/static-imports.ts +25 -0
- package/src/compat/bundler/symlink-imports.ts +119 -0
- package/src/compat/bundler/tsconfig-paths.ts +50 -0
- package/src/compat/bundler/wasm.ts +153 -0
- package/src/compat/bundler/webpack-loaders.ts +685 -0
- package/src/compat/bundler/worker.ts +278 -0
- package/src/compat/cache/build-flags.ts +81 -0
- package/src/compat/cache/build-prerender-errors.ts +163 -0
- package/src/compat/cache/custom-handler.ts +159 -0
- package/src/compat/cache/fetch-patch.ts +745 -0
- package/src/compat/cache/handler.ts +100 -0
- package/src/compat/cache/modern-handler.ts +275 -0
- package/src/compat/cache/resume-data-cache.ts +143 -0
- package/src/compat/cache/revalidate.ts +759 -0
- package/src/compat/cache/runtime-error.ts +124 -0
- package/src/compat/cache/use-cache-transform.ts +961 -0
- package/src/compat/cache/use-cache.ts +1695 -0
- package/src/compat/cache-control.ts +269 -0
- package/src/compat/client/base-path.ts +64 -0
- package/src/compat/client/css-order.ts +36 -0
- package/src/compat/client/errors/control-flow.ts +92 -0
- package/src/compat/client/errors/error-boundary.ts +222 -0
- package/src/compat/client/errors/global-error.ts +238 -0
- package/src/compat/client/errors/install.ts +217 -0
- package/src/compat/client/errors/lazy.ts +53 -0
- package/src/compat/client/errors/primitive-throw.ts +126 -0
- package/src/compat/client/errors/soft-refresh.ts +14 -0
- package/src/compat/client/link-status.ts +86 -0
- package/src/compat/client/nav-compat-runtime.ts +57 -0
- package/src/compat/client/nav-compat.ts +42 -0
- package/src/compat/client/navigation-scroll.ts +154 -0
- package/src/compat/client/optimistic-routing.ts +206 -0
- package/src/compat/client/prefetch-cache.ts +111 -0
- package/src/compat/client/route-announcer.ts +72 -0
- package/src/compat/client/segment-cache-policy.ts +159 -0
- package/src/compat/client/segment-cache.ts +1077 -0
- package/src/compat/client/segment-prefetch.ts +375 -0
- package/src/compat/client/trailing-slash.ts +24 -0
- package/src/compat/css/chunking.ts +254 -0
- package/src/compat/css/inline-css.ts +73 -0
- package/src/compat/css/lightningcss.ts +90 -0
- package/src/compat/css/modules.ts +373 -0
- package/src/compat/css/nonce.ts +30 -0
- package/src/compat/css/sass-plugin.ts +65 -0
- package/src/compat/css/sass.ts +392 -0
- package/src/compat/css/styled-jsx-runtime.ts +80 -0
- package/src/compat/css/styled-jsx.ts +49 -0
- package/src/compat/edge-runtime.ts +71 -0
- package/src/compat/export/client.ts +112 -0
- package/src/compat/export/index.ts +272 -0
- package/src/compat/export/standalone.ts +207 -0
- package/src/compat/image-optimizer/cache.ts +119 -0
- package/src/compat/image-optimizer/detect.ts +143 -0
- package/src/compat/image-optimizer/index.ts +601 -0
- package/src/compat/image-optimizer/source.ts +243 -0
- package/src/compat/index.ts +458 -0
- package/src/compat/lifecycle/after-scope.ts +86 -0
- package/src/compat/lifecycle/after.ts +173 -0
- package/src/compat/lifecycle/error-funnel.ts +306 -0
- package/src/compat/lifecycle/error-serialize.ts +87 -0
- package/src/compat/lifecycle/error-ui.ts +167 -0
- package/src/compat/lifecycle/instrumentation-client.ts +138 -0
- package/src/compat/lifecycle/instrumentation.ts +277 -0
- package/src/compat/lifecycle/node-console.ts +19 -0
- package/src/compat/lifecycle/testmode.ts +263 -0
- package/src/compat/mdx/compile.ts +219 -0
- package/src/compat/mdx/next-mdx-stub.ts +46 -0
- package/src/compat/mdx/plugin.ts +37 -0
- package/src/compat/metadata-route-artifacts.ts +458 -0
- package/src/compat/metadata.ts +295 -0
- package/src/compat/middleware/manifest.ts +210 -0
- package/src/compat/misc/action-return.ts +173 -0
- package/src/compat/next/cache.ts +211 -0
- package/src/compat/next/canonical-url.ts +35 -0
- package/src/compat/next/client-cache.ts +57 -0
- package/src/compat/next/client-navigation.ts +313 -0
- package/src/compat/next/client-only.ts +3 -0
- package/src/compat/next/client-script.tsx +215 -0
- package/src/compat/next/client-server.ts +39 -0
- package/src/compat/next/config-loader.ts +569 -0
- package/src/compat/next/config.ts +29 -0
- package/src/compat/next/constants.cjs +6 -0
- package/src/compat/next/constants.ts +6 -0
- package/src/compat/next/custom-server.ts +236 -0
- package/src/compat/next/dist/client/components/app-router-headers.ts +32 -0
- package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +38 -0
- package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -0
- package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -0
- package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -0
- package/src/compat/next/dynamic.tsx +46 -0
- package/src/compat/next/error.tsx +148 -0
- package/src/compat/next/font/cache.ts +171 -0
- package/src/compat/next/font/google.ts +2 -0
- package/src/compat/next/font/index.ts +8 -0
- package/src/compat/next/font/local.ts +5 -0
- package/src/compat/next/font/runtime-client.ts +71 -0
- package/src/compat/next/font/runtime.ts +974 -0
- package/src/compat/next/font/shared.ts +281 -0
- package/src/compat/next/form.tsx +156 -0
- package/src/compat/next/head.tsx +10 -0
- package/src/compat/next/headers.ts +247 -0
- package/src/compat/next/image/config.ts +196 -0
- package/src/compat/next/image/optimizer.ts +96 -0
- package/src/compat/next/image/patterns.ts +103 -0
- package/src/compat/next/image/shared.ts +141 -0
- package/src/compat/next/image/static-metadata.ts +283 -0
- package/src/compat/next/image/validate.ts +269 -0
- package/src/compat/next/image-client.tsx +215 -0
- package/src/compat/next/image-props.ts +575 -0
- package/src/compat/next/image-usage.ts +102 -0
- package/src/compat/next/image.tsx +56 -0
- package/src/compat/next/index.ts +1 -0
- package/src/compat/next/legacy-image.tsx +97 -0
- package/src/compat/next/link-usage.ts +29 -0
- package/src/compat/next/link-validation-transform.ts +200 -0
- package/src/compat/next/link.tsx +466 -0
- package/src/compat/next/navigation.cjs +21 -0
- package/src/compat/next/navigation.ts +188 -0
- package/src/compat/next/offline.ts +51 -0
- package/src/compat/next/og.ts +324 -0
- package/src/compat/next/optimistic-route-state.ts +188 -0
- package/src/compat/next/preferred-region.ts +39 -0
- package/src/compat/next/redirects.ts +131 -0
- package/src/compat/next/resource-hints.ts +136 -0
- package/src/compat/next/rewrites.ts +350 -0
- package/src/compat/next/root-params.ts +142 -0
- package/src/compat/next/router.cjs +49 -0
- package/src/compat/next/router.ts +143 -0
- package/src/compat/next/script.tsx +355 -0
- package/src/compat/next/server-only.ts +3 -0
- package/src/compat/next/server.ts +28 -0
- package/src/compat/next/svgr.ts +58 -0
- package/src/compat/next/telemetry.ts +77 -0
- package/src/compat/next/user-agent.ts +100 -0
- package/src/compat/next/web-vitals.ts +56 -0
- package/src/compat/otel/api.ts +95 -0
- package/src/compat/otel/client-trace-metadata.ts +71 -0
- package/src/compat/otel/fetch-span.ts +77 -0
- package/src/compat/otel/tracer.ts +944 -0
- package/src/compat/pages/client-plugin.ts +108 -0
- package/src/compat/pages/index.ts +527 -0
- package/src/compat/pages/router-state.ts +94 -0
- package/src/compat/ppr/io.ts +38 -0
- package/src/compat/ppr/missing-root-params.ts +105 -0
- package/src/compat/ppr/root-params-scan.ts +164 -0
- package/src/compat/ppr/root-params-transform.ts +75 -0
- package/src/compat/ppr/root-params.ts +129 -0
- package/src/compat/ppr/segment-config-incompat.ts +34 -0
- package/src/compat/protocol.ts +202 -0
- package/src/compat/react/client.ts +59 -0
- package/src/compat/react/compiler-runtime.ts +60 -0
- package/src/compat/react/dom-client.ts +115 -0
- package/src/compat/react/dom-react-server.ts +20 -0
- package/src/compat/react/dom-server.ts +40 -0
- package/src/compat/react/dom.ts +154 -0
- package/src/compat/react/preact.ts +522 -0
- package/src/compat/react/react-server.ts +84 -0
- package/src/compat/react/router-shim.ts +26 -0
- package/src/compat/react/server-component-use.ts +48 -0
- package/src/compat/react/server-inserted-html.ts +87 -0
- package/src/compat/react/server.ts +156 -0
- package/src/compat/react/view-transition.ts +60 -0
- package/src/compat/register/actions.ts +875 -0
- package/src/compat/register/boot.ts +141 -0
- package/src/compat/register/build-tier.ts +11 -0
- package/src/compat/register/build.ts +182 -0
- package/src/compat/register/bundler.ts +587 -0
- package/src/compat/register/cache.ts +85 -0
- package/src/compat/register/client-errors.ts +18 -0
- package/src/compat/register/config.ts +17 -0
- package/src/compat/register/css-extras.ts +120 -0
- package/src/compat/register/edge-runtime.ts +6 -0
- package/src/compat/register/errors.ts +46 -0
- package/src/compat/register/export.ts +23 -0
- package/src/compat/register/font.ts +36 -0
- package/src/compat/register/hooks.ts +34 -0
- package/src/compat/register/image.ts +133 -0
- package/src/compat/register/index.ts +111 -0
- package/src/compat/register/instrumentation-client.ts +35 -0
- package/src/compat/register/lifecycle.ts +86 -0
- package/src/compat/register/mdx.ts +48 -0
- package/src/compat/register/middleware.ts +36 -0
- package/src/compat/register/misc.ts +44 -0
- package/src/compat/register/otel.ts +288 -0
- package/src/compat/register/pages-api.ts +473 -0
- package/src/compat/register/ppr.ts +56 -0
- package/src/compat/register/protocol.ts +57 -0
- package/src/compat/register/proxy.ts +127 -0
- package/src/compat/register/render.ts +268 -0
- package/src/compat/register/routing.ts +410 -0
- package/src/compat/register/segment.ts +1903 -0
- package/src/compat/register/static-image.ts +21 -0
- package/src/compat/register/typed-routes.ts +35 -0
- package/src/compat/register/usecache.ts +131 -0
- package/src/compat/register/validation.ts +56 -0
- package/src/compat/segment/loading-boundary.ts +113 -0
- package/src/compat/segment/page-slot.ts +200 -0
- package/src/compat/segment/tree.ts +481 -0
- package/src/compat/segment/vary-key.ts +102 -0
- package/src/compat/segment/vary-params.ts +551 -0
- package/src/compat/static-params.ts +33 -0
- package/src/compat/tsconfig-defaults.ts +301 -0
- package/src/compat/typecheck/index.ts +1481 -0
- package/src/compat/typecheck/worker.ts +26 -0
- package/src/compat/typed-routes/index.ts +92 -0
- package/src/compat/typed-routes/manifest.ts +356 -0
- package/src/compat/typed-routes/typegen.ts +566 -0
- package/src/compat/validation/errors.ts +159 -0
- package/src/compat/validation/index.ts +1770 -0
- package/src/compat/validation/prerender-diagnostics.ts +1508 -0
- package/src/compat-bootstrap.ts +67 -0
- package/src/config.ts +218 -0
- package/src/css/build.ts +697 -0
- package/src/css/index.ts +2 -0
- package/src/css/postcss.ts +236 -0
- package/src/css/worker.ts +34 -0
- package/src/dev/client-actions.ts +35 -0
- package/src/dev/client-chunk-store.ts +92 -0
- package/src/dev/client-key-cache.ts +178 -0
- package/src/dev/global-css-cache.ts +212 -0
- package/src/dev/imports.ts +2430 -0
- package/src/dev/module-cache.ts +721 -0
- package/src/dev/module-generations.ts +38 -0
- package/src/dev/module-transform.ts +188 -0
- package/src/dev/node-module-bundle-cache.ts +63 -0
- package/src/dev/restart-cache.ts +10 -0
- package/src/dev/route-bundle-key-cache.ts +154 -0
- package/src/dev/route-facts-cache.ts +223 -0
- package/src/dev/server.ts +1710 -0
- package/src/dynamic/source.ts +307 -0
- package/src/dynamic/tree-shake.ts +262 -0
- package/src/env.ts +92 -0
- package/src/extensions.ts +1898 -0
- package/src/index.ts +34 -0
- package/src/internal.ts +43 -0
- package/src/islands/boundary-error.ts +8 -0
- package/src/islands/static-children.ts +37 -0
- package/src/islands/static-slots.ts +106 -0
- package/src/ppr-postpone.ts +24 -0
- package/src/ppr.ts +784 -0
- package/src/proxy.ts +752 -0
- package/src/render/hooks.ts +384 -0
- package/src/render/index.ts +1 -0
- package/src/render/island-context.ts +47 -0
- package/src/render/metadata.ts +857 -0
- package/src/render/renderer.ts +7391 -0
- package/src/render/resource-hints.ts +44 -0
- package/src/render/slots.tsx +679 -0
- package/src/request/context.ts +396 -0
- package/src/resolve/engine.ts +219 -0
- package/src/resolve/imports.ts +1104 -0
- package/src/resolve/scan-facts.ts +474 -0
- package/src/resolve/source-text.ts +86 -0
- package/src/routing/forwarded.ts +41 -0
- package/src/routing/handler.ts +271 -0
- package/src/routing/href.ts +203 -0
- package/src/routing/metadata.ts +1018 -0
- package/src/routing/request-runtime.ts +43 -0
- package/src/routing/routes.ts +2560 -0
- package/src/routing/slots.ts +432 -0
- package/src/runtime/server.ts +3453 -0
- package/src/runtime/vendor.ts +1160 -0
- package/src/style-modules.d.ts +9 -0
- package/src/typegen.ts +151 -0
- package/src/types.ts +725 -0
- package/src/utils/ansi.ts +9 -0
- package/src/utils/content-type.ts +31 -0
- package/src/utils/decode.ts +7 -0
- package/src/utils/dev-profile.ts +31 -0
- package/src/utils/error-log.ts +29 -0
- package/src/utils/fs-cache.ts +31 -0
- package/src/utils/fs.ts +119 -0
- package/src/utils/html.ts +46 -0
- package/src/utils/serialize.ts +378 -0
- package/src/utils/source.ts +35 -0
- package/src/utils/verbose.ts +39 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { type ResolvedConfig } from '../../config';
|
|
3
|
+
import { setProxyExtensions, setProxyResponseProtocol } from '../../extensions';
|
|
4
|
+
import { findProxyFiles, setProxyRewriteObserver } from '../../proxy';
|
|
5
|
+
import { moduleExportNames } from '../../resolve/scan-facts';
|
|
6
|
+
import { readText, toPosixPath } from '../../utils/fs';
|
|
7
|
+
import { recordRewrite } from '../protocol';
|
|
8
|
+
import { recordCanonicalUrl } from '../next/canonical-url';
|
|
9
|
+
import { getNextConfig } from '../next/config-loader';
|
|
10
|
+
import { activateTestProxy } from '../lifecycle/testmode';
|
|
11
|
+
|
|
12
|
+
export function registerProxyExtensions(_config: ResolvedConfig): void {
|
|
13
|
+
setProxyResponseProtocol({
|
|
14
|
+
nextHeader: 'x-middleware-next',
|
|
15
|
+
rewriteHeader: 'x-middleware-rewrite',
|
|
16
|
+
});
|
|
17
|
+
setProxyExtensions({
|
|
18
|
+
names: ['proxy', 'middleware'],
|
|
19
|
+
validateFiles: validateNextProxyFiles,
|
|
20
|
+
handlerExport: module => module.proxy ?? module.default ?? module.middleware,
|
|
21
|
+
skipUrlNormalize: () => getNextConfig().skipProxyUrlNormalize === true,
|
|
22
|
+
locale: proxyLocale,
|
|
23
|
+
onExternalRewrite: request => activateTestProxy(request.headers),
|
|
24
|
+
clientMaxBodySize: proxyClientMaxBodySize,
|
|
25
|
+
});
|
|
26
|
+
// A same-origin middleware rewrite feeds the Next rewrite-tracking channel so
|
|
27
|
+
// RSC responses carry x-nextjs-rewritten-path/query (identical to next.config
|
|
28
|
+
// rewrites; the RSC-only emission gate lives in compat/protocol.ts). The
|
|
29
|
+
// ORIGINAL url is stashed too so usePathname/useSearchParams stay canonical.
|
|
30
|
+
setProxyRewriteObserver((from, to) => {
|
|
31
|
+
recordCanonicalUrl(from);
|
|
32
|
+
recordRewrite(from, to);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const DEFAULT_PROXY_CLIENT_MAX_BODY_SIZE = 10 * 1024 * 1024;
|
|
37
|
+
|
|
38
|
+
// experimental.proxyClientMaxBodySize accepts bytes (2097152) or a size string
|
|
39
|
+
// ('5mb'); experimental.middlewareClientMaxBodySize is the deprecated alias.
|
|
40
|
+
function proxyClientMaxBodySize(): number {
|
|
41
|
+
const experimental = (getNextConfig().experimental ?? {}) as Record<string, unknown>;
|
|
42
|
+
const raw = experimental.proxyClientMaxBodySize ?? experimental.middlewareClientMaxBodySize;
|
|
43
|
+
if (typeof raw === 'number' && raw > 0) return raw;
|
|
44
|
+
if (typeof raw === 'string') {
|
|
45
|
+
const match = /^(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)?$/i.exec(raw.trim());
|
|
46
|
+
if (match?.[1]) {
|
|
47
|
+
const unit = (match[2] ?? 'b').toLowerCase();
|
|
48
|
+
const multiplier =
|
|
49
|
+
unit === 'gb' ? 1024 ** 3 : unit === 'mb' ? 1024 ** 2 : unit === 'kb' ? 1024 : 1;
|
|
50
|
+
const bytes = Math.floor(Number(match[1]) * multiplier);
|
|
51
|
+
if (bytes > 0) return bytes;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return DEFAULT_PROXY_CLIENT_MAX_BODY_SIZE;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function proxyLocale(url: URL): string {
|
|
58
|
+
const i18n = getNextConfig().i18n as { locales?: unknown } | undefined;
|
|
59
|
+
if (!Array.isArray(i18n?.locales)) return '';
|
|
60
|
+
const locales = i18n.locales.filter((locale): locale is string => typeof locale === 'string');
|
|
61
|
+
const dataLocale = /^\/_next\/data\/[^/]+\/([^/]+)(?:\/|$)/.exec(url.pathname)?.[1];
|
|
62
|
+
const candidate = dataLocale ?? url.pathname.split('/')[1];
|
|
63
|
+
return locales.find(locale => locale.toLowerCase() === candidate?.toLowerCase()) ?? '';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function validateNextProxyFiles(config: ResolvedConfig) {
|
|
67
|
+
const files = findProxyFiles(config, ['proxy', 'middleware']);
|
|
68
|
+
const middleware = files.find(file => path.basename(file).startsWith('middleware.'));
|
|
69
|
+
const proxy = files.find(file => path.basename(file).startsWith('proxy.'));
|
|
70
|
+
if (middleware && proxy) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
`Both middleware file "${relativeProxyPath(config, middleware)}" and proxy file "${relativeProxyPath(config, proxy)}" are detected. Please use "${relativeProxyPath(config, proxy)}" only.`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
if (middleware && !proxy) {
|
|
76
|
+
console.warn(
|
|
77
|
+
'The "middleware" file convention is deprecated. Please use "proxy" instead.',
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
await Promise.all(files.map(file => validateNextProxyFile(config, file)));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function validateNextProxyFile(config: ResolvedConfig, file: string) {
|
|
84
|
+
const source = await readText(file);
|
|
85
|
+
const name = path.basename(file).split('.')[0];
|
|
86
|
+
const exports = moduleExportNames(source, file);
|
|
87
|
+
const validExport =
|
|
88
|
+
exports.includes('default') ||
|
|
89
|
+
(name === 'proxy' ? exports.includes('proxy') : exports.includes('middleware'));
|
|
90
|
+
if (!validExport) {
|
|
91
|
+
throw new Error(proxyMissingExportError(config, file));
|
|
92
|
+
}
|
|
93
|
+
if (name === 'proxy' && hasRuntimeConfig(source)) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`Route segment config is not allowed in Proxy file at "${relativeProxyPath(config, file)}". Proxy always runs on Node.js runtime. Learn more: https://nextjs.org/docs/messages/middleware-to-proxy`,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function proxyMissingExportError(config: ResolvedConfig, file: string) {
|
|
101
|
+
const name = path.basename(file).split('.')[0] === 'middleware' ? 'middleware' : 'proxy';
|
|
102
|
+
const migrationReason =
|
|
103
|
+
name === 'proxy'
|
|
104
|
+
? "- You are migrating from `middleware` to `proxy`, but haven't updated the exported function.\n"
|
|
105
|
+
: '';
|
|
106
|
+
const target = name === 'proxy' ? 'proxy (previously called middleware)' : 'middleware';
|
|
107
|
+
return `The file "${relativeProxyPath(config, file)}" must export a function, either as a default export or as a named "${name}" export.
|
|
108
|
+
This function is what Next.js runs for every request handled by this ${target}.
|
|
109
|
+
|
|
110
|
+
Why this happens:
|
|
111
|
+
${migrationReason}- The file exists but doesn't export a function.
|
|
112
|
+
- The export is not a function (e.g., an object or constant).
|
|
113
|
+
- There's a syntax error preventing the export from being recognized.
|
|
114
|
+
|
|
115
|
+
To fix it:
|
|
116
|
+
- Ensure this file has either a default or "${name}" function export.
|
|
117
|
+
|
|
118
|
+
Learn more: https://nextjs.org/docs/messages/middleware-to-proxy`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function hasRuntimeConfig(source: string) {
|
|
122
|
+
return /\bexport\s+const\s+config\s*=/.test(source) && /\bruntime\s*:/.test(source);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function relativeProxyPath(config: ResolvedConfig, file: string) {
|
|
126
|
+
return `./${toPosixPath(path.relative(config.root, file))}`;
|
|
127
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// Render extension registration (COMPAT - may import core freely).
|
|
2
|
+
//
|
|
3
|
+
// Wires the react/next render behaviors into the core render registries at the gated bootstrap seam. Two
|
|
4
|
+
// homes:
|
|
5
|
+
//
|
|
6
|
+
// src/extensions.ts (shared render registry):
|
|
7
|
+
// - wrapServerComponentInvoke <- invokeServerComponentWithUse (use()-thenable replay for synchronous
|
|
8
|
+
// server components).
|
|
9
|
+
// - onRenderInit <- optional compat one-time render init.
|
|
10
|
+
//
|
|
11
|
+
// src/render/hooks.ts (render-only companion registry):
|
|
12
|
+
// - fontExtensions <- runWithFontScope + fontAssets (next/font CSS + preloads). Next-compat only.
|
|
13
|
+
// - suspenseExtensions <- the preact/compat Suspense identity the streaming walker treats as a
|
|
14
|
+
// boundary. React-compat, loaded lazily.
|
|
15
|
+
//
|
|
16
|
+
// serializeServerActionProp, collectRenderMeta and the server-action module tagging hooks are populated
|
|
17
|
+
// by the actions and cache sub-registrars; this file owns the react and font/suspense hooks.
|
|
18
|
+
|
|
19
|
+
import type { ResolvedConfig } from '../../config';
|
|
20
|
+
import { onExtensionHostReset, setRenderExtensions } from '../../extensions';
|
|
21
|
+
import { setReactCompatActive } from '../react/preact';
|
|
22
|
+
|
|
23
|
+
// preact's global vnode hook cannot be uninstalled, so it follows the host.
|
|
24
|
+
onExtensionHostReset(() => setReactCompatActive(false));
|
|
25
|
+
import {
|
|
26
|
+
nextCompatEnabled,
|
|
27
|
+
reactCompatEnabled,
|
|
28
|
+
setDocumentScriptExtensions,
|
|
29
|
+
setFontExtensions,
|
|
30
|
+
setMetadataExtensions,
|
|
31
|
+
setStaticParamsExtensions,
|
|
32
|
+
setStreamRouteExtensions,
|
|
33
|
+
setSuspenseExtensions,
|
|
34
|
+
} from '../../render/hooks';
|
|
35
|
+
import { withAssetPrefix } from '../../css';
|
|
36
|
+
import { polyfillsChunkPath } from '../bundler/polyfill';
|
|
37
|
+
import { nextRouterShimScript } from '../react/router-shim';
|
|
38
|
+
import { renderPartytownHeadScripts } from '../next/script';
|
|
39
|
+
import { ensureCompatSuspense, compatSuspenseType } from '../../compat';
|
|
40
|
+
import { invokeServerComponentWithUse } from '../react/server-component-use';
|
|
41
|
+
import { fontAssets, fontPreloadDomScript, prewarmFonts, runWithFontScope } from '../next/font/runtime';
|
|
42
|
+
import {
|
|
43
|
+
hasRuntimeMetadata,
|
|
44
|
+
readNextModuleMetadata,
|
|
45
|
+
readNextModuleViewport,
|
|
46
|
+
shouldRenderMetadataInBody,
|
|
47
|
+
} from '../metadata';
|
|
48
|
+
import { aliasGenerateStaticParams } from '../static-params';
|
|
49
|
+
import { getNextConfig } from '../next/config-loader';
|
|
50
|
+
import {
|
|
51
|
+
renderServerInsertedHTML,
|
|
52
|
+
setServerInsertedHTMLScope,
|
|
53
|
+
} from '../react/server-inserted-html';
|
|
54
|
+
import { nextClientRouteState } from '../next/optimistic-route-state';
|
|
55
|
+
import { earlySubmitCaptureScript } from '../actions/early-submit';
|
|
56
|
+
import { getWorkUnit } from '../../request/context';
|
|
57
|
+
import {
|
|
58
|
+
createVaryParamsAccumulator,
|
|
59
|
+
createVaryingParams,
|
|
60
|
+
createVaryingSearchParams,
|
|
61
|
+
normalizeOptionalCatchAllParams,
|
|
62
|
+
} from '../segment/vary-params';
|
|
63
|
+
import type { VaryParamsTrackingContext } from '../../extensions';
|
|
64
|
+
|
|
65
|
+
export function registerRenderExtensions(config: ResolvedConfig): void {
|
|
66
|
+
// The react layer only matters when react/next compat is on. A next-only
|
|
67
|
+
// predicate would miss react-compat-only apps (which still render server
|
|
68
|
+
// components with use() and need the compat Suspense identity for streaming).
|
|
69
|
+
if (!reactCompatEnabled(config)) return;
|
|
70
|
+
|
|
71
|
+
setReactCompatActive(true);
|
|
72
|
+
|
|
73
|
+
setServerInsertedHTMLScope(() => {
|
|
74
|
+
const workUnit = getWorkUnit();
|
|
75
|
+
if (!workUnit) return undefined;
|
|
76
|
+
return (workUnit.compat ??= {});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
setRenderExtensions({
|
|
80
|
+
wrapServerComponentInvoke: invokeServerComponentWithUse,
|
|
81
|
+
genericErrorTitle: ({ dev }) => (dev ? undefined : 'This page couldn\u2019t load'),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
setSuspenseExtensions({ ensureCompatSuspense, compatSuspenseType });
|
|
85
|
+
|
|
86
|
+
// next/font is a next-compat feature; a react-only app renders no fonts.
|
|
87
|
+
if (nextCompatEnabled(config)) {
|
|
88
|
+
setStreamRouteExtensions({
|
|
89
|
+
canStreamRoute: canStreamNextRoute,
|
|
90
|
+
inlineSuspenseStream: needsInlineSuspenseStream,
|
|
91
|
+
});
|
|
92
|
+
setMetadataExtensions({
|
|
93
|
+
enabled: nextCompatEnabled,
|
|
94
|
+
hasRuntimeMetadata,
|
|
95
|
+
readModuleMetadata: readNextModuleMetadata,
|
|
96
|
+
readModuleViewport: readNextModuleViewport,
|
|
97
|
+
shouldRenderMetadataInBody,
|
|
98
|
+
});
|
|
99
|
+
setStaticParamsExtensions({ normalizeModule: aliasGenerateStaticParams });
|
|
100
|
+
setRenderExtensions({
|
|
101
|
+
clientRouteState: nextClientRouteState,
|
|
102
|
+
trackVaryParams: trackRenderVaryParams,
|
|
103
|
+
// Next asserts structural selectors (`body > p`) against the live DOM, so
|
|
104
|
+
// island hosts and the page slot travel as comment pairs and the inline
|
|
105
|
+
// bootstrap materializes them. Core ships the elements as final.
|
|
106
|
+
islandCommentWireFormat: () => true,
|
|
107
|
+
});
|
|
108
|
+
setDocumentScriptExtensions({
|
|
109
|
+
stylesheetPrecedence: cfg => (nextCompatEnabled(cfg) ? 'next' : undefined),
|
|
110
|
+
});
|
|
111
|
+
setFontExtensions({ runWithFontScope, collectFontAssets: fontAssets, prewarmFontAssets: prewarmFonts });
|
|
112
|
+
setDocumentScriptExtensions({
|
|
113
|
+
documentBodyScripts: cfg =>
|
|
114
|
+
`${flightDataBootstrapScript()}${renderPartytownHeadScripts()}${basePathScript(cfg.basePath)}${trailingSlashScript(cfg.trailingSlash)}${skipTrailingSlashScript(cfg.skipTrailingSlashRedirect)}${staleTimesScript()}${segmentSchedulerScript()}${appShellsScript()}${optimisticRoutingScript()}${nextRouterShimScript()}<script>${earlySubmitCaptureScript()}</script>${fontPreloadDomScript()}`,
|
|
115
|
+
documentHeadTags: () => `${polyfillsScript(config)}${renderServerInsertedHTML()}`,
|
|
116
|
+
streamInsertedHTML: renderServerInsertedHTML,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Hand a render's `params`/`searchParams` back wrapped in a tracking view when a vary-params scope is
|
|
123
|
+
* open (a segment-prefetch render). Each call allocates its OWN body-segment accumulator, tagged with the
|
|
124
|
+
* caller's segment kind so the response publishes the layout and page vary sets side by side instead of
|
|
125
|
+
* one union. Outside a scope the accumulator is null and the original object passes through untouched, so
|
|
126
|
+
* ordinary document renders pay nothing.
|
|
127
|
+
*/
|
|
128
|
+
function trackRenderVaryParams<T extends Record<string, unknown>>(
|
|
129
|
+
value: T,
|
|
130
|
+
context: VaryParamsTrackingContext,
|
|
131
|
+
): T {
|
|
132
|
+
const accumulator = createVaryParamsAccumulator(context.segment ?? 'page');
|
|
133
|
+
if (!accumulator) {
|
|
134
|
+
// Segment-M2 deliverable 5: Next's params shape (an EMPTY optional catch-all
|
|
135
|
+
// carries no key) applies to every render, not just tracked ones.
|
|
136
|
+
return context.kind === 'searchParams'
|
|
137
|
+
? value
|
|
138
|
+
: normalizeOptionalCatchAllParams(value, context.optionalCatchAllParam ?? null);
|
|
139
|
+
}
|
|
140
|
+
return context.kind === 'searchParams'
|
|
141
|
+
? createVaryingSearchParams(accumulator, value)
|
|
142
|
+
: createVaryingParams(accumulator, value, context.optionalCatchAllParam ?? null);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Next's flight transport inlines its RSC payload as `self.__next_f.push(...)` chunks, and app code (plus
|
|
147
|
+
* Next's own e2e assertions) treats the presence of that global as "this document carries inlined server
|
|
148
|
+
* data". pnext streams its payload through a different global, so nothing here reads `__next_f` - this
|
|
149
|
+
* declares the array and pushes an empty marker so the documented global exists with Next's shape. Inert
|
|
150
|
+
* by construction.
|
|
151
|
+
*/
|
|
152
|
+
function flightDataBootstrapScript(): string {
|
|
153
|
+
return `<script>(self.__next_f=self.__next_f||[]).push([0])</script>`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Next emits a `<script noModule>` tag referencing the polyfills chunk in the
|
|
157
|
+
// document head. It never executes in module-capable browsers; it exists so the
|
|
158
|
+
// served HTML carries the same polyfills tag Next does (the emitted chunk is
|
|
159
|
+
// written by the client build's static-chunk seam). assetPrefix is applied so a
|
|
160
|
+
// CDN-hosted asset base still resolves.
|
|
161
|
+
function polyfillsScript(config: ResolvedConfig): string {
|
|
162
|
+
return `<script src="${withAssetPrefix(config, polyfillsChunkPath())}" noModule=""></script>`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function canStreamNextRoute(input: {
|
|
166
|
+
config: ResolvedConfig;
|
|
167
|
+
route: { client?: boolean; stream?: unknown };
|
|
168
|
+
}) {
|
|
169
|
+
if (!nextCompatEnabled(input.config)) return true;
|
|
170
|
+
// Whole-page client routes stream through a single Preact render, preserving
|
|
171
|
+
// ancestor provider context across their Suspense boundaries.
|
|
172
|
+
if (input.route.client) return true;
|
|
173
|
+
const stream = input.route.stream as
|
|
174
|
+
| { hasLoadingBoundary?: boolean; ancestorClientReferences?: string[] }
|
|
175
|
+
| undefined;
|
|
176
|
+
// No stream metadata means a non-page route (handlers never reach the page
|
|
177
|
+
// renderer) — nothing to stream.
|
|
178
|
+
if (!stream) return false;
|
|
179
|
+
// Out-of-order streaming isolates each Suspense boundary and drops client-provider context inherited
|
|
180
|
+
// from ancestor layouts/templates. When no ancestor ships a client reference there is nothing to lose;
|
|
181
|
+
// when one does, the route still streams through the single-render inline-suspense path, which keeps the
|
|
182
|
+
// whole tree in one preact render so ancestor providers stay in scope.
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// A route whose ancestor layouts/templates ship client references streams in
|
|
187
|
+
// place (one preact render that suspends at each boundary) instead of flushing
|
|
188
|
+
// replacement chunks rendered from a fresh root, which would drop the ancestor
|
|
189
|
+
// islands' provider context around the boundary's content.
|
|
190
|
+
function needsInlineSuspenseStream(input: {
|
|
191
|
+
config: ResolvedConfig;
|
|
192
|
+
route: { client?: boolean; stream?: unknown };
|
|
193
|
+
}) {
|
|
194
|
+
if (!nextCompatEnabled(input.config) || input.route.client) return false;
|
|
195
|
+
const stream = input.route.stream as { ancestorClientReferences?: string[] } | undefined;
|
|
196
|
+
return (stream?.ancestorClientReferences?.length ?? 0) > 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Inline script exposing experimental.staleTimes so the client prefetch cache
|
|
200
|
+
// honors config overrides (defaults 30s dynamic / 300s static apply otherwise).
|
|
201
|
+
function staleTimesScript(): string {
|
|
202
|
+
const experimental = getNextConfig().experimental as
|
|
203
|
+
| { staleTimes?: { dynamic?: number; static?: number } }
|
|
204
|
+
| undefined;
|
|
205
|
+
const staleTimes = experimental?.staleTimes;
|
|
206
|
+
if (!staleTimes) return '';
|
|
207
|
+
return `<script>window.__PNEXT_STALE_TIMES__=${JSON.stringify(staleTimes)};</script>`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// The client prefetch bandwidth scheduler (concurrency limits + hover-reserved lanes) reproduces Next's
|
|
211
|
+
// SEGMENT-CACHE scheduler, which only exists under cacheComponents. A classic prefetch app must fire all
|
|
212
|
+
// visible prefetches without throttling - the app-client-cache full-prefetch tests clear their request
|
|
213
|
+
// listener between two staggered prefetches and would see the delayed one land as an unexpected request.
|
|
214
|
+
function segmentSchedulerScript(): string {
|
|
215
|
+
const config = getNextConfig() as { cacheComponents?: unknown };
|
|
216
|
+
return config.cacheComponents === true
|
|
217
|
+
? `<script>window.__PNEXT_SEGMENT_SCHEDULER__=true;</script>`
|
|
218
|
+
: '';
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// `experimental.appShells`: the client fires a SECOND, param-stripped prefetch
|
|
222
|
+
// per params-reading route to prime that route's shared App Shell (compat/
|
|
223
|
+
// client/segment-prefetch.ts). Strictly opt-in — without the flag the extra
|
|
224
|
+
// request would break the request-count contracts of every other suite.
|
|
225
|
+
function appShellsScript(): string {
|
|
226
|
+
const experimental = getNextConfig().experimental as { appShells?: unknown } | undefined;
|
|
227
|
+
return experimental?.appShells === true
|
|
228
|
+
? `<script>window.__PNEXT_APP_SHELLS__=true;</script>`
|
|
229
|
+
: '';
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// `experimental.optimisticRouting` defaults ON, so this is an OPT-OUT marker:
|
|
233
|
+
// only an app that explicitly disabled it stamps the document, and the client
|
|
234
|
+
// segment cache then stops letting one URL's entry satisfy another URL's
|
|
235
|
+
// PREFETCH (compat/client/segment-cache.ts). Navigation reuse is unaffected.
|
|
236
|
+
function optimisticRoutingScript(): string {
|
|
237
|
+
const experimental = getNextConfig().experimental as
|
|
238
|
+
| { optimisticRouting?: unknown }
|
|
239
|
+
| undefined;
|
|
240
|
+
return experimental?.optimisticRouting === false
|
|
241
|
+
? `<script>window.__PNEXT_NO_OPTIMISTIC_ROUTING__=true;</script>`
|
|
242
|
+
: '';
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Inline script exposing the configured basePath to the client. `next/form` and other compat client code
|
|
247
|
+
* read `window.__PNEXT_BASE_PATH__` to prefix soft-nav targets. Emitted only when a basePath is set - a
|
|
248
|
+
* bare app keeps the global undefined, treated as ''.
|
|
249
|
+
*/
|
|
250
|
+
function basePathScript(basePath: string): string {
|
|
251
|
+
if (!basePath) return '';
|
|
252
|
+
return `<script>window.__PNEXT_BASE_PATH__=${JSON.stringify(basePath)};</script>`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Inline script exposing skipTrailingSlashRedirect to the client so Link hrefs and client navigation
|
|
257
|
+
* preserve the author's exact trailing slash. Emitted only when the flag is set - a normal app keeps the
|
|
258
|
+
* global undefined, treated as false.
|
|
259
|
+
*/
|
|
260
|
+
function skipTrailingSlashScript(skip: boolean | undefined): string {
|
|
261
|
+
if (!skip) return '';
|
|
262
|
+
return `<script>window.__PNEXT_SKIP_TRAILING_SLASH__=true;</script>`;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function trailingSlashScript(trailingSlash: boolean | undefined): string {
|
|
266
|
+
if (trailingSlash !== true) return '';
|
|
267
|
+
return `<script>window.__PNEXT_TRAILING_SLASH__=true;</script>`;
|
|
268
|
+
}
|