mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-09 21:07:46 +00:00
Revert "[next] Reland add .action handling for dynamic routes" (#11509)
Reverts vercel/vercel#11487. This feature will be relanded behind a feature flag.
This commit is contained in:
5
.changeset/neat-plants-fix.md
Normal file
5
.changeset/neat-plants-fix.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@vercel/next": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
[next]: Revert .action handling for dynamic routes
|
||||||
@@ -1928,7 +1928,6 @@ export const build: BuildV2 = async ({
|
|||||||
bypassToken: prerenderManifest.bypassToken || '',
|
bypassToken: prerenderManifest.bypassToken || '',
|
||||||
isServerMode,
|
isServerMode,
|
||||||
experimentalPPRRoutes,
|
experimentalPPRRoutes,
|
||||||
hasActionOutputSupport: false,
|
|
||||||
}).then(arr =>
|
}).then(arr =>
|
||||||
localizeDynamicRoutes(
|
localizeDynamicRoutes(
|
||||||
arr,
|
arr,
|
||||||
@@ -1959,7 +1958,6 @@ export const build: BuildV2 = async ({
|
|||||||
bypassToken: prerenderManifest.bypassToken || '',
|
bypassToken: prerenderManifest.bypassToken || '',
|
||||||
isServerMode,
|
isServerMode,
|
||||||
experimentalPPRRoutes,
|
experimentalPPRRoutes,
|
||||||
hasActionOutputSupport: false,
|
|
||||||
}).then(arr =>
|
}).then(arr =>
|
||||||
arr.map(route => {
|
arr.map(route => {
|
||||||
route.src = route.src.replace('^', `^${dynamicPrefix}`);
|
route.src = route.src.replace('^', `^${dynamicPrefix}`);
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ import {
|
|||||||
normalizePrefetches,
|
normalizePrefetches,
|
||||||
CreateLambdaFromPseudoLayersOptions,
|
CreateLambdaFromPseudoLayersOptions,
|
||||||
getPostponeResumePathname,
|
getPostponeResumePathname,
|
||||||
LambdaGroup,
|
|
||||||
MAX_UNCOMPRESSED_LAMBDA_SIZE,
|
MAX_UNCOMPRESSED_LAMBDA_SIZE,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import {
|
import {
|
||||||
@@ -69,7 +68,6 @@ const CORRECT_NOT_FOUND_ROUTES_VERSION = 'v12.0.1';
|
|||||||
const CORRECT_MIDDLEWARE_ORDER_VERSION = 'v12.1.7-canary.29';
|
const CORRECT_MIDDLEWARE_ORDER_VERSION = 'v12.1.7-canary.29';
|
||||||
const NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION = 'v12.1.7-canary.33';
|
const NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION = 'v12.1.7-canary.33';
|
||||||
const EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION = 'v12.2.0';
|
const EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION = 'v12.2.0';
|
||||||
const ACTION_OUTPUT_SUPPORT_VERSION = 'v14.2.2';
|
|
||||||
const CORRECTED_MANIFESTS_VERSION = 'v12.2.0';
|
const CORRECTED_MANIFESTS_VERSION = 'v12.2.0';
|
||||||
|
|
||||||
// Ideally this should be in a Next.js manifest so we can change it in
|
// Ideally this should be in a Next.js manifest so we can change it in
|
||||||
@@ -201,10 +199,6 @@ export async function serverBuild({
|
|||||||
nextVersion,
|
nextVersion,
|
||||||
EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION
|
EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION
|
||||||
);
|
);
|
||||||
const hasActionOutputSupport = semver.gte(
|
|
||||||
nextVersion,
|
|
||||||
ACTION_OUTPUT_SUPPORT_VERSION
|
|
||||||
);
|
|
||||||
const projectDir = requiredServerFilesManifest.relativeAppDir
|
const projectDir = requiredServerFilesManifest.relativeAppDir
|
||||||
? path.join(baseDir, requiredServerFilesManifest.relativeAppDir)
|
? path.join(baseDir, requiredServerFilesManifest.relativeAppDir)
|
||||||
: requiredServerFilesManifest.appDir || entryPath;
|
: requiredServerFilesManifest.appDir || entryPath;
|
||||||
@@ -932,23 +926,11 @@ export async function serverBuild({
|
|||||||
inversedAppPathManifest,
|
inversedAppPathManifest,
|
||||||
});
|
});
|
||||||
|
|
||||||
const appRouterStreamingActionLambdaGroups: LambdaGroup[] = [];
|
|
||||||
|
|
||||||
for (const group of appRouterLambdaGroups) {
|
for (const group of appRouterLambdaGroups) {
|
||||||
if (!group.isPrerenders || group.isExperimentalPPR) {
|
if (!group.isPrerenders || group.isExperimentalPPR) {
|
||||||
group.isStreaming = true;
|
group.isStreaming = true;
|
||||||
}
|
}
|
||||||
group.isAppRouter = true;
|
group.isAppRouter = true;
|
||||||
|
|
||||||
// We create a streaming variant of the Prerender lambda group
|
|
||||||
// to support actions that are part of a Prerender
|
|
||||||
if (hasActionOutputSupport) {
|
|
||||||
appRouterStreamingActionLambdaGroups.push({
|
|
||||||
...group,
|
|
||||||
isActionLambda: true,
|
|
||||||
isStreaming: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const group of appRouteHandlersLambdaGroups) {
|
for (const group of appRouteHandlersLambdaGroups) {
|
||||||
@@ -1000,13 +982,6 @@ export async function serverBuild({
|
|||||||
pseudoLayerBytes: group.pseudoLayerBytes,
|
pseudoLayerBytes: group.pseudoLayerBytes,
|
||||||
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
|
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
|
||||||
})),
|
})),
|
||||||
appRouterStreamingPrerenderLambdaGroups:
|
|
||||||
appRouterStreamingActionLambdaGroups.map(group => ({
|
|
||||||
pages: group.pages,
|
|
||||||
isPrerender: group.isPrerenders,
|
|
||||||
pseudoLayerBytes: group.pseudoLayerBytes,
|
|
||||||
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
|
|
||||||
})),
|
|
||||||
appRouteHandlersLambdaGroups: appRouteHandlersLambdaGroups.map(
|
appRouteHandlersLambdaGroups: appRouteHandlersLambdaGroups.map(
|
||||||
group => ({
|
group => ({
|
||||||
pages: group.pages,
|
pages: group.pages,
|
||||||
@@ -1024,7 +999,6 @@ export async function serverBuild({
|
|||||||
const combinedGroups = [
|
const combinedGroups = [
|
||||||
...pageLambdaGroups,
|
...pageLambdaGroups,
|
||||||
...appRouterLambdaGroups,
|
...appRouterLambdaGroups,
|
||||||
...appRouterStreamingActionLambdaGroups,
|
|
||||||
...apiLambdaGroups,
|
...apiLambdaGroups,
|
||||||
...appRouteHandlersLambdaGroups,
|
...appRouteHandlersLambdaGroups,
|
||||||
];
|
];
|
||||||
@@ -1234,11 +1208,6 @@ export async function serverBuild({
|
|||||||
|
|
||||||
let outputName = path.posix.join(entryDirectory, pageName);
|
let outputName = path.posix.join(entryDirectory, pageName);
|
||||||
|
|
||||||
if (group.isActionLambda) {
|
|
||||||
// give the streaming prerenders a .action suffix
|
|
||||||
outputName = `${outputName}.action`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is a PPR page, then we should prefix the output name.
|
// If this is a PPR page, then we should prefix the output name.
|
||||||
if (isPPR) {
|
if (isPPR) {
|
||||||
if (!revalidate) {
|
if (!revalidate) {
|
||||||
@@ -1409,7 +1378,6 @@ export async function serverBuild({
|
|||||||
isServerMode: true,
|
isServerMode: true,
|
||||||
dynamicMiddlewareRouteMap: middleware.dynamicRouteMap,
|
dynamicMiddlewareRouteMap: middleware.dynamicRouteMap,
|
||||||
experimentalPPRRoutes,
|
experimentalPPRRoutes,
|
||||||
hasActionOutputSupport,
|
|
||||||
}).then(arr =>
|
}).then(arr =>
|
||||||
localizeDynamicRoutes(
|
localizeDynamicRoutes(
|
||||||
arr,
|
arr,
|
||||||
@@ -1937,72 +1905,7 @@ export async function serverBuild({
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
...(hasActionOutputSupport
|
|
||||||
? [
|
|
||||||
// Create rewrites for streaming prerenders (.action routes)
|
|
||||||
// This contains separate rewrites for each possible "has" (action header, or content-type)
|
|
||||||
// Also includes separate handling for index routes which should match to /index.action.
|
|
||||||
// This follows the same pattern as the rewrites for .rsc files.
|
|
||||||
{
|
|
||||||
src: `^${path.posix.join('/', entryDirectory, '/')}`,
|
|
||||||
dest: path.posix.join('/', entryDirectory, '/index.action'),
|
|
||||||
has: [
|
|
||||||
{
|
|
||||||
type: 'header',
|
|
||||||
key: 'next-action',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
continue: true,
|
|
||||||
override: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: `^${path.posix.join('/', entryDirectory, '/')}`,
|
|
||||||
dest: path.posix.join('/', entryDirectory, '/index.action'),
|
|
||||||
has: [
|
|
||||||
{
|
|
||||||
type: 'header',
|
|
||||||
key: 'content-type',
|
|
||||||
value: 'multipart/form-data;.*',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
continue: true,
|
|
||||||
override: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: `^${path.posix.join(
|
|
||||||
'/',
|
|
||||||
entryDirectory,
|
|
||||||
'/((?!.+\\.action).+?)(?:/)?$'
|
|
||||||
)}`,
|
|
||||||
dest: path.posix.join('/', entryDirectory, '/$1.action'),
|
|
||||||
has: [
|
|
||||||
{
|
|
||||||
type: 'header',
|
|
||||||
key: 'next-action',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
continue: true,
|
|
||||||
override: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: `^${path.posix.join(
|
|
||||||
'/',
|
|
||||||
entryDirectory,
|
|
||||||
'/((?!.+\\.action).+?)(?:/)?$'
|
|
||||||
)}`,
|
|
||||||
dest: path.posix.join('/', entryDirectory, '/$1.action'),
|
|
||||||
has: [
|
|
||||||
{
|
|
||||||
type: 'header',
|
|
||||||
key: 'content-type',
|
|
||||||
value: 'multipart/form-data;.*',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
continue: true,
|
|
||||||
override: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
{
|
{
|
||||||
src: `^${path.posix.join('/', entryDirectory, '/')}`,
|
src: `^${path.posix.join('/', entryDirectory, '/')}`,
|
||||||
has: [
|
has: [
|
||||||
|
|||||||
@@ -321,7 +321,6 @@ export async function getDynamicRoutes({
|
|||||||
isServerMode,
|
isServerMode,
|
||||||
dynamicMiddlewareRouteMap,
|
dynamicMiddlewareRouteMap,
|
||||||
experimentalPPRRoutes,
|
experimentalPPRRoutes,
|
||||||
hasActionOutputSupport,
|
|
||||||
}: {
|
}: {
|
||||||
entryPath: string;
|
entryPath: string;
|
||||||
entryDirectory: string;
|
entryDirectory: string;
|
||||||
@@ -334,7 +333,6 @@ export async function getDynamicRoutes({
|
|||||||
isServerMode?: boolean;
|
isServerMode?: boolean;
|
||||||
dynamicMiddlewareRouteMap?: ReadonlyMap<string, RouteWithSrc>;
|
dynamicMiddlewareRouteMap?: ReadonlyMap<string, RouteWithSrc>;
|
||||||
experimentalPPRRoutes: ReadonlySet<string>;
|
experimentalPPRRoutes: ReadonlySet<string>;
|
||||||
hasActionOutputSupport: boolean;
|
|
||||||
}): Promise<RouteWithSrc[]> {
|
}): Promise<RouteWithSrc[]> {
|
||||||
if (routesManifest) {
|
if (routesManifest) {
|
||||||
switch (routesManifest.version) {
|
switch (routesManifest.version) {
|
||||||
@@ -425,25 +423,14 @@ export async function getDynamicRoutes({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasActionOutputSupport) {
|
routes.push({
|
||||||
routes.push({
|
...route,
|
||||||
...route,
|
src: route.src.replace(
|
||||||
src: route.src.replace(
|
new RegExp(escapeStringRegexp('(?:/)?$')),
|
||||||
new RegExp(escapeStringRegexp('(?:/)?$')),
|
'(?:\\.rsc)(?:/)?$'
|
||||||
'(?<nxtsuffix>(?:\\.action|\\.rsc))(?:/)?$'
|
),
|
||||||
),
|
dest: route.dest?.replace(/($|\?)/, '.rsc$1'),
|
||||||
dest: route.dest?.replace(/($|\?)/, '$nxtsuffix$1'),
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
routes.push({
|
|
||||||
...route,
|
|
||||||
src: route.src.replace(
|
|
||||||
new RegExp(escapeStringRegexp('(?:/)?$')),
|
|
||||||
'(?:\\.rsc)(?:/)?$'
|
|
||||||
),
|
|
||||||
dest: route.dest?.replace(/($|\?)/, '.rsc$1'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
routes.push(route);
|
routes.push(route);
|
||||||
}
|
}
|
||||||
@@ -1500,7 +1487,6 @@ export type LambdaGroup = {
|
|||||||
isStreaming?: boolean;
|
isStreaming?: boolean;
|
||||||
isPrerenders?: boolean;
|
isPrerenders?: boolean;
|
||||||
isExperimentalPPR?: boolean;
|
isExperimentalPPR?: boolean;
|
||||||
isActionLambda?: boolean;
|
|
||||||
isPages?: boolean;
|
isPages?: boolean;
|
||||||
isApiLambda: boolean;
|
isApiLambda: boolean;
|
||||||
pseudoLayer: PseudoLayer;
|
pseudoLayer: PseudoLayer;
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ export default function Root({ children }) {
|
|||||||
<body>{children}</body>
|
<body>{children}</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,6 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
).then(res => res.json());
|
).then(res => res.json());
|
||||||
|
|
||||||
ctx.actionManifest = actionManifest;
|
ctx.actionManifest = actionManifest;
|
||||||
|
|
||||||
Object.assign(ctx, info);
|
Object.assign(ctx, info);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -58,8 +57,8 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
const body = await res.text();
|
const body = await res.text();
|
||||||
expect(body).toContain('1338');
|
expect(body).toContain('1338');
|
||||||
expect(res.headers.get('x-matched-path')).toBe(path + '.action');
|
expect(res.headers.get('x-matched-path')).toBe(path);
|
||||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
expect(res.headers.get('x-vercel-cache')).toBe('BYPASS');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bypass the static cache for a server action on a page with dynamic params', async () => {
|
it('should bypass the static cache for a server action on a page with dynamic params', async () => {
|
||||||
@@ -78,8 +77,8 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
const body = await res.text();
|
const body = await res.text();
|
||||||
expect(body).toContain('1338');
|
expect(body).toContain('1338');
|
||||||
expect(res.headers.get('x-matched-path')).toBe(path + '.action');
|
expect(res.headers.get('x-matched-path')).toBe(path);
|
||||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
expect(res.headers.get('x-vercel-cache')).toBe('BYPASS');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should properly invoke the action on a dynamic page', async () => {
|
it('should properly invoke the action on a dynamic page', async () => {
|
||||||
@@ -98,7 +97,7 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
const body = await res.text();
|
const body = await res.text();
|
||||||
expect(body).toContain('1338');
|
expect(body).toContain('1338');
|
||||||
expect(res.headers.get('x-matched-path')).toBe(path + '.action');
|
expect(res.headers.get('x-matched-path')).toBe(path);
|
||||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -114,9 +113,9 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
expect(res.headers.get('x-matched-path')).toBe(path + '.action');
|
expect(res.headers.get('x-matched-path')).toBe(path);
|
||||||
expect(res.headers.get('content-type')).toBe('text/x-component');
|
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
expect(res.headers.get('x-vercel-cache')).toBe('BYPASS');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bypass the static cache for a server action on a page with dynamic params', async () => {
|
it('should bypass the static cache for a server action on a page with dynamic params', async () => {
|
||||||
@@ -129,9 +128,9 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
expect(res.headers.get('x-matched-path')).toBe(path + '.action');
|
expect(res.headers.get('x-matched-path')).toBe(path);
|
||||||
expect(res.headers.get('content-type')).toBe('text/x-component');
|
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
expect(res.headers.get('x-vercel-cache')).toBe('BYPASS');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should properly invoke the action on a dynamic page', async () => {
|
it('should properly invoke the action on a dynamic page', async () => {
|
||||||
@@ -144,7 +143,7 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
expect(res.headers.get('x-matched-path')).toBe(path + '.action');
|
expect(res.headers.get('x-matched-path')).toBe(path);
|
||||||
expect(res.headers.get('content-type')).toBe('text/x-component');
|
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
||||||
});
|
});
|
||||||
@@ -162,11 +161,9 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
expect(res.headers.get('x-matched-path')).toBe(
|
expect(res.headers.get('x-matched-path')).toBe(path);
|
||||||
'/rsc/static/generate-static-params/[slug].action'
|
|
||||||
);
|
|
||||||
expect(res.headers.get('content-type')).toBe('text/x-component');
|
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
expect(res.headers.get('x-vercel-cache')).toBe('BYPASS');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bypass the static cache for a server action when not pre-generated', async () => {
|
it('should bypass the static cache for a server action when not pre-generated', async () => {
|
||||||
@@ -179,9 +176,9 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
expect(res.headers.get('x-matched-path')).toBe(page + '.action');
|
expect(res.headers.get('x-matched-path')).toBe(page);
|
||||||
expect(res.headers.get('content-type')).toBe('text/x-component');
|
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
expect(res.headers.get('x-vercel-cache')).toBe('BYPASS');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
module.exports = {};
|
|
||||||
@@ -428,7 +428,7 @@ it('should handle edge functions in app with basePath', async () => {
|
|||||||
edgeFunctions.add(item);
|
edgeFunctions.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect(lambdas.size).toBe(2);
|
expect(lambdas.size).toBe(1);
|
||||||
expect(edgeFunctions.size).toBe(4);
|
expect(edgeFunctions.size).toBe(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -452,5 +452,5 @@ it('should not generate lambdas that conflict with static index route in app wit
|
|||||||
lambdas.add(item);
|
lambdas.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect(lambdas.size).toBe(3);
|
expect(lambdas.size).toBe(1);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user