diff --git a/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs b/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs
index fdb7dc3193efe..dd086933bb530 100644
--- a/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs
+++ b/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs
@@ -81,7 +81,6 @@ pub async fn get_app_page_entry(
indexmap! {
"VAR_DEFINITION_PAGE" => page.to_string(),
"VAR_DEFINITION_PATHNAME" => pathname.clone(),
- "VAR_ORIGINAL_PATHNAME" => original_name.clone(),
// TODO(alexkirsz) Support custom global error.
"VAR_MODULE_GLOBAL_ERROR" => "next/dist/client/components/error-boundary".to_string(),
},
diff --git a/packages/next-swc/crates/next-core/src/next_app/app_route_entry.rs b/packages/next-swc/crates/next-core/src/next_app/app_route_entry.rs
index 3031fbab4cafc..0971d581fe68a 100644
--- a/packages/next-swc/crates/next-core/src/next_app/app_route_entry.rs
+++ b/packages/next-swc/crates/next-core/src/next_app/app_route_entry.rs
@@ -84,7 +84,6 @@ pub async fn get_app_route_entry(
"VAR_DEFINITION_FILENAME" => path.file_stem().await?.as_ref().unwrap().clone(),
// TODO(alexkirsz) Is this necessary?
"VAR_DEFINITION_BUNDLE_PATH" => "".to_string(),
- "VAR_ORIGINAL_PATHNAME" => original_name.clone(),
"VAR_RESOLVED_PAGE_PATH" => path.to_string().await?.clone_value(),
"VAR_USERLAND" => INNER.to_string(),
},
diff --git a/packages/next/src/build/templates/app-page.ts b/packages/next/src/build/templates/app-page.ts
index 9879f48eda27c..fb8bb173d33d2 100644
--- a/packages/next/src/build/templates/app-page.ts
+++ b/packages/next/src/build/templates/app-page.ts
@@ -29,7 +29,6 @@ declare const __next_app_load_chunk__: any
// INJECT:__next_app_require__
// INJECT:__next_app_load_chunk__
-export const originalPathname = 'VAR_ORIGINAL_PATHNAME'
export const __next_app__ = {
require: __next_app_require__,
loadChunk: __next_app_load_chunk__,
diff --git a/packages/next/src/build/templates/app-route.ts b/packages/next/src/build/templates/app-route.ts
index 4aaea88b9a4d9..099fc7d5fb779 100644
--- a/packages/next/src/build/templates/app-route.ts
+++ b/packages/next/src/build/templates/app-route.ts
@@ -35,8 +35,6 @@ const routeModule = new AppRouteRouteModule({
const { requestAsyncStorage, staticGenerationAsyncStorage, serverHooks } =
routeModule
-const originalPathname = 'VAR_ORIGINAL_PATHNAME'
-
function patchFetch() {
return _patchFetch({ serverHooks, staticGenerationAsyncStorage })
}
@@ -46,6 +44,5 @@ export {
requestAsyncStorage,
staticGenerationAsyncStorage,
serverHooks,
- originalPathname,
patchFetch,
}
diff --git a/packages/next/src/build/utils.ts b/packages/next/src/build/utils.ts
index a422c3bf046c0..7999bd21438f2 100644
--- a/packages/next/src/build/utils.ts
+++ b/packages/next/src/build/utils.ts
@@ -1385,9 +1385,8 @@ export async function buildAppStaticPaths({
return StaticGenerationAsyncStorageWrapper.wrap(
ComponentMod.staticGenerationAsyncStorage,
{
- url: { pathname: page },
+ page,
renderOpts: {
- originalPathname: page,
incrementalCache,
supportsDynamicHTML: true,
isRevalidate: false,
diff --git a/packages/next/src/build/webpack/loaders/next-app-loader.ts b/packages/next/src/build/webpack/loaders/next-app-loader.ts
index b2f4d6279adae..fdfb3ebafe509 100644
--- a/packages/next/src/build/webpack/loaders/next-app-loader.ts
+++ b/packages/next/src/build/webpack/loaders/next-app-loader.ts
@@ -145,7 +145,6 @@ async function createAppRouteCode({
VAR_DEFINITION_FILENAME: filename,
VAR_DEFINITION_BUNDLE_PATH: bundlePath,
VAR_RESOLVED_PAGE_PATH: resolvedPagePath,
- VAR_ORIGINAL_PATHNAME: page,
},
{
nextConfigOutput: JSON.stringify(nextConfigOutput),
@@ -773,7 +772,6 @@ const nextAppLoader: AppLoader = async function nextAppLoader() {
VAR_DEFINITION_PAGE: page,
VAR_DEFINITION_PATHNAME: pathname,
VAR_MODULE_GLOBAL_ERROR: treeCodeResult.globalError,
- VAR_ORIGINAL_PATHNAME: page,
},
{
tree: treeCodeResult.treeCode,
diff --git a/packages/next/src/client/components/static-generation-async-storage.external.ts b/packages/next/src/client/components/static-generation-async-storage.external.ts
index 6ed246b8497a8..f426f7ff8f52d 100644
--- a/packages/next/src/client/components/static-generation-async-storage.external.ts
+++ b/packages/next/src/client/components/static-generation-async-storage.external.ts
@@ -12,12 +12,27 @@ import { staticGenerationAsyncStorage } from './static-generation-async-storage-
export interface StaticGenerationStore {
readonly isStaticGeneration: boolean
- readonly pagePath?: string
+ /**
+ * The page that is being rendered. This is the path to the page file.
+ */
+ readonly page: string
+
/**
* The URL of the request. This only specifies the pathname and the search
- * part of the URL. The other parts aren't accepted so they shouldn't be used.
+ * part of the URL.
*/
- readonly url: { readonly pathname: string; readonly search: string }
+ readonly url?: {
+ /**
+ * The pathname of the requested URL.
+ */
+ readonly pathname: string
+
+ /**
+ * The search part of the requested URL. If the request did not provide a
+ * search part, this will be undefined.
+ */
+ readonly search?: string
+ }
readonly incrementalCache?: IncrementalCache
readonly isOnDemandRevalidate?: boolean
readonly isPrerendering?: boolean
diff --git a/packages/next/src/export/routes/app-route.ts b/packages/next/src/export/routes/app-route.ts
index 189b307c28fd0..01050f407b9ee 100644
--- a/packages/next/src/export/routes/app-route.ts
+++ b/packages/next/src/export/routes/app-route.ts
@@ -64,7 +64,6 @@ export async function exportAppRoute(
notFoundRoutes: [],
},
renderOpts: {
- originalPathname: page,
nextExport: true,
supportsDynamicHTML: false,
incrementalCache,
diff --git a/packages/next/src/export/worker.ts b/packages/next/src/export/worker.ts
index 7f973ffae3764..417909c9acc48 100644
--- a/packages/next/src/export/worker.ts
+++ b/packages/next/src/export/worker.ts
@@ -269,7 +269,6 @@ async function exportPageImpl(
fontManifest: optimizeFonts ? requireFontManifest(distDir) : undefined,
locale,
supportsDynamicHTML: false,
- originalPathname: page,
experimental: {
...input.renderOpts.experimental,
isRoutePPREnabled,
diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx
index d812044245594..d6ef01b98d78a 100644
--- a/packages/next/src/server/app-render/app-render.tsx
+++ b/packages/next/src/server/app-render/app-render.tsx
@@ -312,7 +312,7 @@ async function generateFlight(
},
getDynamicParamFromSegment,
appUsingSizeAdjustment,
- staticGenerationStore: { url },
+ staticGenerationStore: { page, url },
query,
requestId,
flightRouterState,
@@ -321,7 +321,7 @@ async function generateFlight(
if (!options?.skipFlight) {
const [MetadataTree, MetadataOutlet] = createMetadataComponents({
tree: loaderTree,
- pathname: url.pathname,
+ pathname: url?.pathname ?? page,
trailingSlash: ctx.renderOpts.trailingSlash,
query,
getDynamicParamFromSegment,
@@ -434,7 +434,7 @@ async function ReactServerApp({ tree, ctx, asNotFound }: ReactServerAppProps) {
GlobalError,
createDynamicallyTrackedSearchParams,
},
- staticGenerationStore: { url },
+ staticGenerationStore: { page, url },
} = ctx
const initialTree = createFlightRouterStateFromLoaderTree(
tree,
@@ -445,7 +445,7 @@ async function ReactServerApp({ tree, ctx, asNotFound }: ReactServerAppProps) {
const [MetadataTree, MetadataOutlet] = createMetadataComponents({
tree,
errorType: asNotFound ? 'not-found' : undefined,
- pathname: url.pathname,
+ pathname: url?.pathname ?? page,
trailingSlash: ctx.renderOpts.trailingSlash,
query,
getDynamicParamFromSegment: getDynamicParamFromSegment,
@@ -481,7 +481,7 @@ async function ReactServerApp({ tree, ctx, asNotFound }: ReactServerAppProps) {
,
loadingData,
],
diff --git a/packages/next/src/server/app-render/dynamic-rendering.ts b/packages/next/src/server/app-render/dynamic-rendering.ts
index 7a247bed95120..76781fd39f64d 100644
--- a/packages/next/src/server/app-render/dynamic-rendering.ts
+++ b/packages/next/src/server/app-render/dynamic-rendering.ts
@@ -75,7 +75,8 @@ export function markCurrentScopeAsDynamic(
store: StaticGenerationStore,
expression: string
): void {
- const { pathname } = store.url
+ const { page, url } = store
+ const pathname = url?.pathname ?? page
if (store.isUnstableCacheCallback) {
// inside cache scopes marking a scope as dynamic has no effect because the outer cache scope
// creates a cache boundary. This is subtly different from reading a dynamic data source which is
@@ -122,7 +123,8 @@ export function trackDynamicDataAccessed(
store: StaticGenerationStore,
expression: string
): void {
- const { pathname } = store.url
+ const { page, url } = store
+ const pathname = url?.pathname ?? page
if (store.isUnstableCacheCallback) {
throw new Error(
`Route ${pathname} used "${expression}" inside a function cached with "unstable_cache(...)". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use "${expression}" outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`
@@ -183,7 +185,11 @@ export function trackDynamicFetch(
// don't need to postpone.
if (!store.prerenderState || store.isUnstableCacheCallback) return
- postponeWithTracking(store.prerenderState, expression, store.url.pathname)
+ postponeWithTracking(
+ store.prerenderState,
+ expression,
+ store.url?.pathname ?? store.page
+ )
}
function postponeWithTracking(
diff --git a/packages/next/src/server/app-render/types.ts b/packages/next/src/server/app-render/types.ts
index b1287d261049a..88b74f6ccc383 100644
--- a/packages/next/src/server/app-render/types.ts
+++ b/packages/next/src/server/app-render/types.ts
@@ -141,7 +141,6 @@ export interface RenderOptsPartial {
nextExport?: boolean
nextConfigOutput?: 'standalone' | 'export'
appDirDevErrorLogger?: (err: any) => Promise
- originalPathname?: string
isDraftMode?: boolean
deploymentId?: string
onUpdateCookies?: (cookies: string[]) => void
diff --git a/packages/next/src/server/async-storage/static-generation-async-storage-wrapper.ts b/packages/next/src/server/async-storage/static-generation-async-storage-wrapper.ts
index 84defb92d333d..1d28c20d21736 100644
--- a/packages/next/src/server/async-storage/static-generation-async-storage-wrapper.ts
+++ b/packages/next/src/server/async-storage/static-generation-async-storage-wrapper.ts
@@ -8,11 +8,27 @@ import { createPrerenderState } from '../../server/app-render/dynamic-rendering'
import type { FetchMetric } from '../base-http'
export type StaticGenerationContext = {
+ /**
+ * The page that is being rendered. This relates to the path to the page file.
+ */
+ page: string
+
/**
* The URL of the request. This only specifies the pathname and the search
- * part of the URL. The other parts aren't accepted so they shouldn't be used.
+ * part of the URL.
*/
- url: { pathname: string; search?: string }
+ url?: {
+ /**
+ * The pathname of the requested URL.
+ */
+ pathname: string
+
+ /**
+ * The search part of the requested URL. If the request did not provide a
+ * search part, this will be an empty string.
+ */
+ search?: string
+ }
requestEndedState?: { ended?: boolean }
renderOpts: {
incrementalCache?: IncrementalCache
@@ -40,7 +56,6 @@ export type StaticGenerationContext = {
// Pull some properties from RenderOptsPartial so that the docs are also
// mirrored.
RenderOptsPartial,
- | 'originalPathname'
| 'supportsDynamicHTML'
| 'isRevalidate'
| 'nextExport'
@@ -55,7 +70,7 @@ export const StaticGenerationAsyncStorageWrapper: AsyncStorageWrapper<
> = {
wrap(
storage: AsyncLocalStorage,
- { url, renderOpts, requestEndedState }: StaticGenerationContext,
+ { page, url, renderOpts, requestEndedState }: StaticGenerationContext,
callback: (store: StaticGenerationStore) => Result
): Result {
/**
@@ -87,14 +102,13 @@ export const StaticGenerationAsyncStorageWrapper: AsyncStorageWrapper<
const store: StaticGenerationStore = {
isStaticGeneration,
+ page,
// Rather than just using the whole `url` here, we pull the parts we want
// to ensure we don't use parts of the URL that we shouldn't. This also
// lets us avoid requiring an empty string for `search` in the type.
- url: {
- pathname: url.pathname,
- search: url.search ?? '',
- },
- pagePath: renderOpts.originalPathname,
+ url: url
+ ? { pathname: url.pathname, search: url.search ?? '' }
+ : undefined,
incrementalCache:
// we fallback to a global incremental cache for edge-runtime locally
// so that it can access the fs cache without mocks
diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts
index fb8da83c9824b..9d82a5f25734f 100644
--- a/packages/next/src/server/base-server.ts
+++ b/packages/next/src/server/base-server.ts
@@ -2281,7 +2281,6 @@ export default abstract class Server<
// it is not a dynamic RSC request then it is a revalidation
// request.
isRevalidate: isSSG && !postponed && !isDynamicRSCRequest,
- originalPathname: components.ComponentMod.originalPathname,
serverActions: this.nextConfig.experimental.serverActions,
}
: {}),
@@ -2344,7 +2343,6 @@ export default abstract class Server<
params: opts.params,
prerenderManifest,
renderOpts: {
- originalPathname: components.ComponentMod.originalPathname,
supportsDynamicHTML,
incrementalCache,
isRevalidate: isSSG,
diff --git a/packages/next/src/server/future/route-modules/app-route/module.ts b/packages/next/src/server/future/route-modules/app-route/module.ts
index cfb37d03a7ce1..9d0d84f0f97c4 100644
--- a/packages/next/src/server/future/route-modules/app-route/module.ts
+++ b/packages/next/src/server/future/route-modules/app-route/module.ts
@@ -257,6 +257,7 @@ export class AppRouteRouteModule extends RouteModule<
// Get the context for the static generation.
const staticGenerationContext: StaticGenerationContext = {
+ page: this.definition.page,
url: rawRequest.nextUrl,
renderOpts: context.renderOpts,
}
diff --git a/packages/next/src/server/lib/patch-fetch.ts b/packages/next/src/server/lib/patch-fetch.ts
index 20bfea528c97b..660096bbbcd96 100644
--- a/packages/next/src/server/lib/patch-fetch.ts
+++ b/packages/next/src/server/lib/patch-fetch.ts
@@ -129,17 +129,14 @@ const getDerivedTags = (pathname: string): string[] => {
export function addImplicitTags(staticGenerationStore: StaticGenerationStore) {
const newTags: string[] = []
- const {
- pagePath,
- url: { pathname },
- } = staticGenerationStore
+ const { page, url } = staticGenerationStore
if (!Array.isArray(staticGenerationStore.tags)) {
staticGenerationStore.tags = []
}
- if (pagePath) {
- const derivedTags = getDerivedTags(pagePath)
+ if (page) {
+ const derivedTags = getDerivedTags(page)
for (let tag of derivedTags) {
tag = `${NEXT_CACHE_IMPLICIT_TAG_ID}${tag}`
@@ -150,6 +147,8 @@ export function addImplicitTags(staticGenerationStore: StaticGenerationStore) {
}
}
+ // TODO: verify that this is the correct behavior
+ const pathname = url?.pathname ?? page
if (pathname) {
const tag = `${NEXT_CACHE_IMPLICIT_TAG_ID}${pathname}`
if (!staticGenerationStore.tags?.includes(tag)) {
@@ -332,7 +331,10 @@ function createPatchedFetcher(
// we only want to warn if the user is explicitly setting a cache value
if (!(isRequestInput && _cache === 'default')) {
Log.warn(
- `fetch for ${fetchUrl} on ${staticGenerationStore.url.pathname} specified "cache: ${_cache}" and "revalidate: ${curRevalidate}", only one should be specified.`
+ `fetch for ${fetchUrl} on ${
+ staticGenerationStore.url?.pathname ??
+ staticGenerationStore.page
+ } specified "cache: ${_cache}" and "revalidate: ${curRevalidate}", only one should be specified.`
)
}
_cache = undefined
@@ -361,7 +363,7 @@ function createPatchedFetcher(
revalidate = validateRevalidate(
curRevalidate,
- staticGenerationStore.url.pathname
+ staticGenerationStore.url?.pathname ?? staticGenerationStore.page
)
const _headers = getRequestMeta('headers')
@@ -687,9 +689,7 @@ function createPatchedFetcher(
if (!staticGenerationStore.forceStatic && cache === 'no-store') {
const dynamicUsageReason = `no-store fetch ${input}${
- staticGenerationStore.url.pathname
- ? ` ${staticGenerationStore.url.pathname}`
- : ''
+ staticGenerationStore.url?.pathname ?? staticGenerationStore.page
}`
// If enabled, we should bail out of static generation.
@@ -723,9 +723,8 @@ function createPatchedFetcher(
next.revalidate === 0
) {
const dynamicUsageReason = `revalidate: 0 fetch ${input}${
- staticGenerationStore.url.pathname
- ? ` ${staticGenerationStore.url.pathname}`
- : ''
+ staticGenerationStore.url?.pathname ??
+ staticGenerationStore.page
}`
// If enabled, we should bail out of static generation.
diff --git a/packages/next/src/server/load-components.ts b/packages/next/src/server/load-components.ts
index 3e43beaef8372..c395ee4f94e79 100644
--- a/packages/next/src/server/load-components.ts
+++ b/packages/next/src/server/load-components.ts
@@ -64,7 +64,7 @@ export type LoadComponentsReturnType = {
getStaticPaths?: GetStaticPaths
getServerSideProps?: GetServerSideProps
ComponentMod: NextModule
- routeModule?: RouteModule
+ routeModule: RouteModule
isAppPath?: boolean
page: string
}
diff --git a/packages/next/src/server/load-default-error-components.ts b/packages/next/src/server/load-default-error-components.ts
index bbd703709047e..b836aa0aa2e92 100644
--- a/packages/next/src/server/load-default-error-components.ts
+++ b/packages/next/src/server/load-default-error-components.ts
@@ -40,7 +40,7 @@ export type LoadComponentsReturnType = {
getStaticPaths?: GetStaticPaths
getServerSideProps?: GetServerSideProps
ComponentMod: any
- routeModule?: RouteModule
+ routeModule: RouteModule
isAppPath?: boolean
page: string
}
diff --git a/packages/next/src/server/web/spec-extension/revalidate.ts b/packages/next/src/server/web/spec-extension/revalidate.ts
index 93e93bff4777a..db8755edd2fd2 100644
--- a/packages/next/src/server/web/spec-extension/revalidate.ts
+++ b/packages/next/src/server/web/spec-extension/revalidate.ts
@@ -50,7 +50,9 @@ function revalidate(tag: string, expression: string) {
if (store.isUnstableCacheCallback) {
throw new Error(
- `Route ${store.url.pathname} used "${expression}" inside a function cached with "unstable_cache(...)" which is unsupported. To ensure revalidation is performed consistently it must always happen outside of renders and cached functions. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`
+ `Route ${
+ store.url?.pathname ?? store.page
+ } used "${expression}" inside a function cached with "unstable_cache(...)" which is unsupported. To ensure revalidation is performed consistently it must always happen outside of renders and cached functions. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`
)
}
diff --git a/packages/next/src/server/web/spec-extension/unstable-cache.ts b/packages/next/src/server/web/spec-extension/unstable-cache.ts
index 8e670ad46abdb..7f783239cfcee 100644
--- a/packages/next/src/server/web/spec-extension/unstable-cache.ts
+++ b/packages/next/src/server/web/spec-extension/unstable-cache.ts
@@ -305,6 +305,7 @@ export function unstable_cache(
// when the unstable_cache call is revalidated
fetchCache: 'force-no-store',
isUnstableCacheCallback: true,
+ page: '/',
url: { pathname: '/', search: '' },
isStaticGeneration: false,
prerenderState: null,