Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/next/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -947,5 +947,8 @@
"946": "Failed to deserialize errors.",
"947": "Expected `sendErrorsToBrowser` to be defined in renderOpts.",
"948": "Failed to serialize errors.",
"949": "Route %s errored during %s. These errors are normally ignored and may not prevent the route from prerendering but are logged here because build debugging is enabled.\n \nOriginal Error: %s"
"949": "Route %s errored during %s. These errors are normally ignored and may not prevent the route from prerendering but are logged here because build debugging is enabled.\n \nOriginal Error: %s",
"950": "The manifests singleton was not initialized.",
"951": "The client reference manifest for route \"%s\" does not exist.",
"952": "Cannot access \"%s\" without a work store."
}
10 changes: 2 additions & 8 deletions packages/next/src/build/templates/app-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ import {
createOpaqueFallbackRouteParams,
type OpaqueFallbackRouteParams,
} from '../../server/request/fallback-params'
import { setReferenceManifestsSingleton } from '../../server/app-render/encryption-utils'
import { setManifestsSingleton } from '../../server/app-render/manifests-singleton'
import {
isHtmlBotRequest,
shouldServeStreamingMetadata,
} from '../../server/lib/streaming-metadata'
import { createServerModuleMap } from '../../server/app-render/action-utils'
import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths'
import { getIsPossibleServerAction } from '../../server/lib/server-action-request-meta'
import {
Expand Down Expand Up @@ -400,13 +399,10 @@ export async function handler(
// set the reference manifests to our global store so Server Action's
// encryption util can access to them at the top level of the page module.
if (serverActionsManifest && clientReferenceManifest) {
setReferenceManifestsSingleton({
setManifestsSingleton({
page: srcPage,
clientReferenceManifest,
serverActionsManifest,
serverModuleMap: createServerModuleMap({
serverActionsManifest,
}),
})
}

Expand Down Expand Up @@ -540,8 +536,6 @@ export async function handler(
nextFontManifest,
reactLoadableManifest,
subresourceIntegrityManifest,
serverActionsManifest,
clientReferenceManifest,
setCacheStatus: routerServerContext?.setCacheStatus,
setIsrStatus: routerServerContext?.setIsrStatus,
setReactDebugChannel: routerServerContext?.setReactDebugChannel,
Expand Down
8 changes: 2 additions & 6 deletions packages/next/src/build/templates/app-route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'
import type { IncomingMessage, ServerResponse } from 'node:http'
import { addRequestMeta, getRequestMeta } from '../../server/request-meta'
import { getTracer, type Span, SpanKind } from '../../server/lib/trace/tracer'
import { setReferenceManifestsSingleton } from '../../server/app-render/encryption-utils'
import { createServerModuleMap } from '../../server/app-render/action-utils'
import { setManifestsSingleton } from '../../server/app-render/manifests-singleton'
import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths'
import { NodeNextRequest, NodeNextResponse } from '../../server/base-http/node'
import {
Expand Down Expand Up @@ -185,13 +184,10 @@ export async function handler(
// set the reference manifests to our global store so Server Action's
// encryption util can access to them at the top level of the page module.
if (serverActionsManifest && clientReferenceManifest) {
setReferenceManifestsSingleton({
setManifestsSingleton({
page: srcPage,
clientReferenceManifest,
serverActionsManifest,
serverModuleMap: createServerModuleMap({
serverActionsManifest,
}),
})
}

Expand Down
8 changes: 2 additions & 6 deletions packages/next/src/build/templates/edge-app-route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createServerModuleMap } from '../../server/app-render/action-utils'
import { setReferenceManifestsSingleton } from '../../server/app-render/encryption-utils'
import { setManifestsSingleton } from '../../server/app-render/manifests-singleton'
import type { NextConfigComplete } from '../../server/config-shared'
import { EdgeRouteModuleWrapper } from '../../server/web/edge-route-module-wrapper'

Expand All @@ -16,13 +15,10 @@ const rscManifest = self.__RSC_MANIFEST?.['VAR_PAGE']
const rscServerManifest = maybeJSONParse(self.__RSC_SERVER_MANIFEST)

if (rscManifest && rscServerManifest) {
setReferenceManifestsSingleton({
setManifestsSingleton({
page: 'VAR_PAGE',
clientReferenceManifest: rscManifest,
serverActionsManifest: rscServerManifest,
serverModuleMap: createServerModuleMap({
serverActionsManifest: rscServerManifest,
}),
})
}

Expand Down
12 changes: 2 additions & 10 deletions packages/next/src/build/templates/edge-ssr-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import * as pageMod from 'VAR_USERLAND'

import type { RequestData } from '../../server/web/types'
import type { NextConfigComplete } from '../../server/config-shared'
import { setReferenceManifestsSingleton } from '../../server/app-render/encryption-utils'
import { createServerModuleMap } from '../../server/app-render/action-utils'
import { setManifestsSingleton } from '../../server/app-render/manifests-singleton'
import { initializeCacheHandlers } from '../../server/use-cache/handlers'
import { BaseServerSpan } from '../../server/lib/trace/constants'
import { getTracer, SpanKind, type Span } from '../../server/lib/trace/tracer'
Expand Down Expand Up @@ -40,13 +39,10 @@ const rscManifest = self.__RSC_MANIFEST?.['VAR_PAGE']
const rscServerManifest = maybeJSONParse(self.__RSC_SERVER_MANIFEST)

if (rscManifest && rscServerManifest) {
setReferenceManifestsSingleton({
setManifestsSingleton({
page: 'VAR_PAGE',
clientReferenceManifest: rscManifest,
serverActionsManifest: rscServerManifest,
serverModuleMap: createServerModuleMap({
serverActionsManifest: rscServerManifest,
}),
})
}

Expand Down Expand Up @@ -81,12 +77,10 @@ async function requestHandler(
buildManifest,
prerenderManifest,
reactLoadableManifest,
clientReferenceManifest,
subresourceIntegrityManifest,
dynamicCssManifest,
nextFontManifest,
resolvedPathname,
serverActionsManifest,
interceptionRoutePatterns,
routerServerContext,
} = prepareResult
Expand Down Expand Up @@ -129,8 +123,6 @@ async function requestHandler(
reactLoadableManifest,
subresourceIntegrityManifest,
dynamicCssManifest,
serverActionsManifest,
clientReferenceManifest,
setIsrStatus: routerServerContext?.setIsrStatus,

dir: pageRouteModule.relativeProjectDir,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,14 @@ const nextAppLoader: AppLoader = async function nextAppLoader() {

const buildInfo = getModuleBuildInfo((this as any)._module)
const collectedDeclarations: [string, string][] = []
const page = name.replace(/^app/, '')

// Use the page from loaderOptions directly instead of deriving it from name.
// The name (bundlePath) may have been normalized with normalizePagePath()
// which is designed for Pages Router and incorrectly duplicates /index paths
// (e.g., /index/page -> /index/index/page). The page parameter contains the
// correct unnormalized value.
const page = loaderOptions.page

const middlewareConfig: ProxyConfig = JSON.parse(
Buffer.from(middlewareConfigBase64, 'base64').toString()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ interface Options {
type ModuleId = string | number /*| null*/

// double indexed chunkId, filename
export type ManifestChunks = Array<string>
export type ManifestChunks = ReadonlyArray<string>

const pluginState = getProxiedPluginState({
ssrModules: {} as { [ssrModuleId: string]: ModuleInfo },
Expand Down
5 changes: 0 additions & 5 deletions packages/next/src/export/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,11 +385,6 @@ async function exportAppImpl(
join(distDir, 'server', `${NEXT_FONT_MANIFEST}.json`)
),
images: nextConfig.images,
...(enabledDirectories.app
? {
serverActionsManifest,
}
: {}),
deploymentId: nextConfig.deploymentId,
htmlLimitedBots: nextConfig.htmlLimitedBots.source,
experimental: {
Expand Down
25 changes: 6 additions & 19 deletions packages/next/src/server/app-render/action-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import { warn } from '../../build/output/log'
import { RequestCookies, ResponseCookies } from '../web/spec-extension/cookies'
import { HeadersAdapter } from '../web/spec-extension/adapters/headers'
import { fromNodeOutgoingHttpHeaders } from '../web/utils'
import { selectWorkerForForwarding } from './action-utils'
import { selectWorkerForForwarding, type ServerModuleMap } from './action-utils'
import { isNodeNextRequest, isWebNextRequest } from '../base-http/helpers'
import { RedirectStatusCode } from '../../client/components/redirect-status-code'
import { synchronizeMutableCookies } from '../async-storage/request-store'
Expand All @@ -59,7 +59,7 @@ import { InvariantError } from '../../shared/lib/invariant-error'
import { executeRevalidates } from '../revalidation-utils'
import { getRequestMeta } from '../request-meta'
import { setCacheBustingSearchParam } from '../../client/components/router-reducer/set-cache-busting-search-param'
import { getServerModuleMap } from './encryption-utils'
import { getServerModuleMap } from './manifests-singleton'

function formDataFromSearchQueryString(query: string) {
const searchParams = new URLSearchParams(query)
Expand Down Expand Up @@ -473,15 +473,6 @@ export function parseHostHeader(
: undefined
}

type ServerModuleMap = Record<
string,
{
id: string
chunks: string[]
name: string
}
>

type ServerActionsConfig = {
bodySizeLimit?: SizeLimit
allowedOrigins?: string[]
Expand Down Expand Up @@ -522,7 +513,7 @@ export async function handleAction({
metadata: AppPageRenderResultMetadata
}): Promise<HandleActionResult> {
const contentType = req.headers['content-type']
const { serverActionsManifest, page } = ctx.renderOpts
const { page } = ctx.renderOpts
const serverModuleMap = getServerModuleMap()

const {
Expand Down Expand Up @@ -640,11 +631,7 @@ export async function handleAction({
const actionWasForwarded = Boolean(req.headers['x-action-forwarded'])

if (actionId) {
const forwardedWorker = selectWorkerForForwarding(
actionId,
page,
serverActionsManifest
)
const forwardedWorker = selectWorkerForForwarding(actionId, page)

// If forwardedWorker is truthy, it means there isn't a worker for the action
// in the current handler, so we forward the request to a worker that has the action.
Expand Down Expand Up @@ -685,7 +672,7 @@ export async function handleAction({
{ isAction: true },
async (): Promise<HandleActionResult> => {
// We only use these for fetch actions -- MPA actions handle them inside `decodeAction`.
let actionModId: string | undefined
let actionModId: string | number | undefined
let boundActionArguments: unknown[] = []

if (
Expand Down Expand Up @@ -1214,7 +1201,7 @@ async function executeActionAndPrepareForRender<
function getActionModIdOrError(
actionId: string | null,
serverModuleMap: ServerModuleMap
): string {
): string | number {
// if we're missing the action ID header, we can't do any further processing
if (!actionId) {
throw new InvariantError("Missing 'next-action' header.")
Expand Down
19 changes: 13 additions & 6 deletions packages/next/src/server/app-render/action-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@ import type { ActionManifest } from '../../build/webpack/plugins/flight-client-e
import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths'
import { pathHasPrefix } from '../../shared/lib/router/utils/path-has-prefix'
import { removePathPrefix } from '../../shared/lib/router/utils/remove-path-prefix'
import { getServerActionsManifest } from './manifests-singleton'
import { workAsyncStorage } from './work-async-storage.external'

export interface ServerModuleMap {
readonly [name: string]: {
readonly id: string | number
readonly name: string
readonly chunks: Readonly<Array<string>> // currently not used
readonly async?: boolean
}
}

// This function creates a Flight-acceptable server module map proxy from our
// Server Reference Manifest similar to our client module map.
// This is because our manifest contains a lot of internal Next.js data that
Expand All @@ -12,7 +22,7 @@ export function createServerModuleMap({
serverActionsManifest,
}: {
serverActionsManifest: ActionManifest
}) {
}): ServerModuleMap {
return new Proxy(
{},
{
Expand Down Expand Up @@ -61,11 +71,8 @@ export function createServerModuleMap({
* Checks if the requested action has a worker for the current page.
* If not, it returns the first worker that has a handler for the action.
*/
export function selectWorkerForForwarding(
actionId: string,
pageName: string,
serverActionsManifest: ActionManifest
) {
export function selectWorkerForForwarding(actionId: string, pageName: string) {
const serverActionsManifest = getServerActionsManifest()
const workers =
serverActionsManifest[
process.env.NEXT_RUNTIME === 'edge' ? 'edge' : 'node'
Expand Down
Loading
Loading