Skip to content

Commit 730aeae

Browse files
authored
fix Next.js static routes with server actions (#6664)
1 parent 06220c3 commit 730aeae

File tree

7 files changed

+187
-6
lines changed

7 files changed

+187
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
- Fix demo projects + web frameworks with emulators (#6737)
2+
- Fix Next.js static routes with server actions (#6664)

src/frameworks/next/constants.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import type {
77
PRERENDER_MANIFEST as PRERENDER_MANIFEST_TYPE,
88
ROUTES_MANIFEST as ROUTES_MANIFEST_TYPE,
99
APP_PATHS_MANIFEST as APP_PATHS_MANIFEST_TYPE,
10+
SERVER_REFERENCE_MANIFEST as SERVER_REFERENCE_MANIFEST_TYPE,
1011
} from "next/constants";
12+
import type { WEBPACK_LAYERS as NEXTJS_WEBPACK_LAYERS } from "next/dist/lib/constants";
1113

1214
export const APP_PATH_ROUTES_MANIFEST: typeof APP_PATH_ROUTES_MANIFEST_TYPE =
1315
"app-path-routes-manifest.json";
@@ -18,5 +20,68 @@ export const PAGES_MANIFEST: typeof PAGES_MANIFEST_TYPE = "pages-manifest.json";
1820
export const PRERENDER_MANIFEST: typeof PRERENDER_MANIFEST_TYPE = "prerender-manifest.json";
1921
export const ROUTES_MANIFEST: typeof ROUTES_MANIFEST_TYPE = "routes-manifest.json";
2022
export const APP_PATHS_MANIFEST: typeof APP_PATHS_MANIFEST_TYPE = "app-paths-manifest.json";
23+
export const SERVER_REFERENCE_MANIFEST: `${typeof SERVER_REFERENCE_MANIFEST_TYPE}.json` =
24+
"server-reference-manifest.json";
2125

2226
export const ESBUILD_VERSION = "0.19.2";
27+
28+
// This is copied from Next.js source code to keep WEBPACK_LAYERS in sync with the Next.js definition.
29+
const WEBPACK_LAYERS_NAMES = {
30+
/**
31+
* The layer for the shared code between the client and server bundles.
32+
*/ shared: "shared",
33+
/**
34+
* React Server Components layer (rsc).
35+
*/ reactServerComponents: "rsc",
36+
/**
37+
* Server Side Rendering layer for app (ssr).
38+
*/ serverSideRendering: "ssr",
39+
/**
40+
* The browser client bundle layer for actions.
41+
*/ actionBrowser: "action-browser",
42+
/**
43+
* The layer for the API routes.
44+
*/ api: "api",
45+
/**
46+
* The layer for the middleware code.
47+
*/ middleware: "middleware",
48+
/**
49+
* The layer for assets on the edge.
50+
*/ edgeAsset: "edge-asset",
51+
/**
52+
* The browser client bundle layer for App directory.
53+
*/ appPagesBrowser: "app-pages-browser",
54+
/**
55+
* The server bundle layer for metadata routes.
56+
*/ appMetadataRoute: "app-metadata-route",
57+
/**
58+
* The layer for the server bundle for App Route handlers.
59+
*/ appRouteHandler: "app-route-handler",
60+
} as const;
61+
62+
// This is copied from Next.js source code to keep WEBPACK_LAYERS in sync with the Next.js definition.
63+
export const WEBPACK_LAYERS: typeof NEXTJS_WEBPACK_LAYERS = {
64+
...WEBPACK_LAYERS_NAMES,
65+
GROUP: {
66+
server: [
67+
WEBPACK_LAYERS_NAMES.reactServerComponents,
68+
WEBPACK_LAYERS_NAMES.actionBrowser,
69+
WEBPACK_LAYERS_NAMES.appMetadataRoute,
70+
WEBPACK_LAYERS_NAMES.appRouteHandler,
71+
],
72+
nonClientServerTarget: [
73+
// plus middleware and pages api
74+
WEBPACK_LAYERS_NAMES.middleware,
75+
WEBPACK_LAYERS_NAMES.api,
76+
],
77+
app: [
78+
WEBPACK_LAYERS_NAMES.reactServerComponents,
79+
WEBPACK_LAYERS_NAMES.actionBrowser,
80+
WEBPACK_LAYERS_NAMES.appMetadataRoute,
81+
WEBPACK_LAYERS_NAMES.appRouteHandler,
82+
WEBPACK_LAYERS_NAMES.serverSideRendering,
83+
WEBPACK_LAYERS_NAMES.appPagesBrowser,
84+
WEBPACK_LAYERS_NAMES.shared,
85+
],
86+
},
87+
};

src/frameworks/next/index.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import {
5454
cleanI18n,
5555
getNextVersion,
5656
hasStaticAppNotFoundComponent,
57+
getRoutesWithServerAction,
5758
} from "./utils";
5859
import { NODE_VERSION, NPM_COMMAND_TIMEOUT_MILLIES, SHARP_VERSION, I18N_ROOT } from "../constants";
5960
import type {
@@ -63,6 +64,7 @@ import type {
6364
RoutesManifest,
6465
NpmLsDepdendency,
6566
MiddlewareManifest,
67+
ActionManifest,
6668
} from "./interfaces";
6769
import {
6870
MIDDLEWARE_MANIFEST,
@@ -72,6 +74,7 @@ import {
7274
APP_PATH_ROUTES_MANIFEST,
7375
APP_PATHS_MANIFEST,
7476
ESBUILD_VERSION,
77+
SERVER_REFERENCE_MANIFEST,
7578
} from "./constants";
7679
import { getAllSiteDomains, getDeploymentDomain } from "../../hosting/api";
7780
import { logger } from "../../logger";
@@ -220,13 +223,16 @@ export async function build(
220223
headers,
221224
}));
222225

223-
const [appPathsManifest, appPathRoutesManifest] = await Promise.all([
226+
const [appPathsManifest, appPathRoutesManifest, serverReferenceManifest] = await Promise.all([
224227
readJSON<AppPathsManifest>(join(dir, distDir, "server", APP_PATHS_MANIFEST)).catch(
225228
() => undefined,
226229
),
227230
readJSON<AppPathRoutesManifest>(join(dir, distDir, APP_PATH_ROUTES_MANIFEST)).catch(
228231
() => undefined,
229232
),
233+
readJSON<ActionManifest>(join(dir, distDir, "server", SERVER_REFERENCE_MANIFEST)).catch(
234+
() => undefined,
235+
),
230236
]);
231237

232238
if (appPathRoutesManifest) {
@@ -257,6 +263,17 @@ export async function build(
257263
reasonsForBackend.add(`non-static component ${key}`);
258264
}
259265
}
266+
267+
if (serverReferenceManifest) {
268+
const routesWithServerAction = getRoutesWithServerAction(
269+
serverReferenceManifest,
270+
appPathRoutesManifest,
271+
);
272+
273+
for (const key of routesWithServerAction) {
274+
reasonsForBackend.add(`route with server action ${key}`);
275+
}
276+
}
260277
}
261278

262279
const isEveryRedirectSupported = nextJsRedirects
@@ -385,6 +402,7 @@ export async function ɵcodegenPublicDirectory(
385402
routesManifest,
386403
pagesManifest,
387404
appPathRoutesManifest,
405+
serverReferenceManifest,
388406
] = await Promise.all([
389407
readJSON<MiddlewareManifest>(join(sourceDir, distDir, "server", MIDDLEWARE_MANIFEST)),
390408
readJSON<PrerenderManifest>(join(sourceDir, distDir, PRERENDER_MANIFEST)),
@@ -393,6 +411,9 @@ export async function ɵcodegenPublicDirectory(
393411
readJSON<AppPathRoutesManifest>(join(sourceDir, distDir, APP_PATH_ROUTES_MANIFEST)).catch(
394412
() => ({}),
395413
),
414+
readJSON<ActionManifest>(join(sourceDir, distDir, "server", SERVER_REFERENCE_MANIFEST)).catch(
415+
() => ({ node: {}, edge: {}, encryptionKey: "" }),
416+
),
396417
]);
397418

398419
const appPathRoutesEntries = Object.entries(appPathRoutesManifest);
@@ -423,6 +444,11 @@ export async function ɵcodegenPublicDirectory(
423444
...headersRegexesNotSupportedByHosting,
424445
];
425446

447+
const staticRoutesUsingServerActions = getRoutesWithServerAction(
448+
serverReferenceManifest,
449+
appPathRoutesManifest,
450+
);
451+
426452
const pagesManifestLikePrerender: PrerenderManifest["routes"] = Object.fromEntries(
427453
Object.entries(pagesManifest)
428454
.filter(([, srcRoute]) => srcRoute.endsWith(".html"))
@@ -457,6 +483,12 @@ export async function ɵcodegenPublicDirectory(
457483
);
458484
return;
459485
}
486+
487+
if (staticRoutesUsingServerActions.some((it) => path === it)) {
488+
logger.debug(`skipping ${path} due to server action`);
489+
return;
490+
}
491+
460492
const appPathRoute =
461493
route.srcRoute && appPathRoutesEntries.find(([, it]) => it === route.srcRoute)?.[0];
462494
const contentDist = join(sourceDir, distDir, "server", appPathRoute ? "app" : "pages");

src/frameworks/next/interfaces.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,29 @@ export interface AppPathsManifest {
130130
[key: string]: string;
131131
}
132132

133-
export interface AppPathRoutesManifest {
134-
[key: string]: string;
135-
}
136-
137133
export interface HostingHeadersWithSource {
138134
source: string;
139135
headers: HostingHeaders["headers"];
140136
}
137+
138+
export type AppPathRoutesManifest = Record<string, string>;
139+
140+
/**
141+
* Note: This is a copy of the type from `next/dist/build/webpack/plugins/flight-client-entry-plugin`.
142+
* It's copied here due to type errors caused by internal dependencies of Next.js when importing that file.
143+
*/
144+
export type ActionManifest = {
145+
encryptionKey: string;
146+
node: Actions;
147+
edge: Actions;
148+
};
149+
type Actions = {
150+
[actionId: string]: {
151+
workers: {
152+
[name: string]: string | number;
153+
};
154+
layer: {
155+
[name: string]: string;
156+
};
157+
};
158+
};

src/frameworks/next/utils.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@ import type {
1919
MiddlewareManifestV1,
2020
MiddlewareManifestV2,
2121
AppPathsManifest,
22-
AppPathRoutesManifest,
2322
HostingHeadersWithSource,
23+
AppPathRoutesManifest,
24+
ActionManifest,
2425
} from "./interfaces";
2526
import {
2627
APP_PATH_ROUTES_MANIFEST,
2728
EXPORT_MARKER,
2829
IMAGES_MANIFEST,
2930
MIDDLEWARE_MANIFEST,
31+
WEBPACK_LAYERS,
3032
} from "./constants";
3133
import { dirExistsSync, fileExistsSync } from "../../fsutils";
3234

@@ -421,3 +423,31 @@ export async function hasStaticAppNotFoundComponent(
421423
): Promise<boolean> {
422424
return pathExists(join(sourceDir, distDir, "server", "app", "_not-found.html"));
423425
}
426+
427+
/**
428+
* Find routes using server actions by checking the server-reference-manifest.json
429+
*/
430+
export function getRoutesWithServerAction(
431+
serverReferenceManifest: ActionManifest,
432+
appPathRoutesManifest: AppPathRoutesManifest,
433+
): string[] {
434+
const routesWithServerAction = new Set<string>();
435+
436+
for (const key of Object.keys(serverReferenceManifest)) {
437+
if (key !== "edge" && key !== "node") continue;
438+
439+
const edgeOrNode = serverReferenceManifest[key];
440+
441+
for (const actionId of Object.keys(edgeOrNode)) {
442+
if (!edgeOrNode[actionId].layer) continue;
443+
444+
for (const [route, type] of Object.entries(edgeOrNode[actionId].layer)) {
445+
if (type === WEBPACK_LAYERS.actionBrowser) {
446+
routesWithServerAction.add(appPathRoutesManifest[route.replace("app", "")]);
447+
}
448+
}
449+
}
450+
}
451+
452+
return Array.from(routesWithServerAction);
453+
}

src/test/frameworks/next/helpers/app.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { PrerenderManifest } from "next/dist/build";
22
import type { PagesManifest } from "next/dist/build/webpack/plugins/pages-manifest-plugin";
33
import type {
4+
ActionManifest,
45
AppPathRoutesManifest,
56
AppPathsManifest,
67
} from "../../../../frameworks/next/interfaces";
@@ -15,6 +16,10 @@ export const appPathRoutesManifest: AppPathRoutesManifest = {
1516
"/api/test/route": "/api/test",
1617
"/api/static/route": "/api/static",
1718
"/page": "/",
19+
"/another-s-a/page": "/another-s-a",
20+
"/server-action/page": "/server-action",
21+
"/ssr/page": "/ssr",
22+
"/server-action/edge/page": "/server-action/edge",
1823
};
1924

2025
export const pagesManifest: PagesManifest = {
@@ -69,3 +74,23 @@ globalThis.__RSC_MANIFEST["/page"] =
6974
export const clientReferenceManifestWithImage = `{"ssrModuleMapping":{"2306":{"*":{"id":"7833","name":"*","chunks":[],"async":false}},"2353":{"*":{"id":"8709","name":"*","chunks":[],"async":false}},"3029":{"*":{"id":"9556","name":"*","chunks":[],"async":false}},"7330":{"*":{"id":"7734","name":"*","chunks":[],"async":false}},"8531":{"*":{"id":"9150","name":"*","chunks":[],"async":false}},"9180":{"*":{"id":"2698","name":"*","chunks":[],"async":false}}},"edgeSSRModuleMapping":{},"clientModules":{"/app-path/node_modules/next/dist/client/components/app-router.js":{"id":2353,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/app-router.js":{"id":2353,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/client/components/layout-router.js":{"id":9180,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/layout-router.js":{"id":9180,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/client/components/render-from-template-context.js":{"id":2306,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/render-from-template-context.js":{"id":2306,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/client/components/static-generation-searchparams-bailout-provider.js":{"id":8531,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/static-generation-searchparams-bailout-provider.js":{"id":8531,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/client/components/error-boundary.js":{"id":7330,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/error-boundary.js":{"id":7330,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/client/image-component.js":{"id":3029,"name":"*","chunks":["931:static/chunks/app/page-8d47763b987bba19.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/image-component.js":{"id":3029,"name":"*","chunks":["931:static/chunks/app/page-8d47763b987bba19.js"],"async":false},"/app-path/node_modules/next/font/google/target.css?{\"path\":\"src/app/layout.tsx\",\"import\":\"Inter\",\"arguments\":[{\"subsets\":[\"latin\"]}],\"variableName\":\"inter\"}":{"id":670,"name":"*","chunks":["185:static/chunks/app/layout-09ef1f5c8b0e56d1.js"],"async":false},"/app-path/src/app/globals.css":{"id":8410,"name":"*","chunks":["185:static/chunks/app/layout-09ef1f5c8b0e56d1.js"],"async":false}},"entryCSSFiles":{"/app-path/src/app/page":[],"/app-path/src/app/layout":["static/css/110a35ea7c81b899.css"]}}`;
7075

7176
export const clientReferenceManifestWithoutImage = `{"ssrModuleMapping":{"2306":{"*":{"id":"7833","name":"*","chunks":[],"async":false}},"2353":{"*":{"id":"8709","name":"*","chunks":[],"async":false}},"3029":{"*":{"id":"9556","name":"*","chunks":[],"async":false}},"7330":{"*":{"id":"7734","name":"*","chunks":[],"async":false}},"8531":{"*":{"id":"9150","name":"*","chunks":[],"async":false}},"9180":{"*":{"id":"2698","name":"*","chunks":[],"async":false}}},"edgeSSRModuleMapping":{},"clientModules":{"/app-path/node_modules/next/dist/client/components/app-router.js":{"id":2353,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/app-router.js":{"id":2353,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/client/components/layout-router.js":{"id":9180,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/layout-router.js":{"id":9180,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/client/components/render-from-template-context.js":{"id":2306,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/render-from-template-context.js":{"id":2306,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/client/components/static-generation-searchparams-bailout-provider.js":{"id":8531,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/static-generation-searchparams-bailout-provider.js":{"id":8531,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/client/components/error-boundary.js":{"id":7330,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/dist/esm/client/components/error-boundary.js":{"id":7330,"name":"*","chunks":["272:static/chunks/webpack-76fd8b39fe914c29.js","253:static/chunks/bce60fc1-8c4748991edb1ec4.js","698:static/chunks/698-1321e6d13d35448d.js"],"async":false},"/app-path/node_modules/next/font/google/target.css?{\"path\":\"src/app/layout.tsx\",\"import\":\"Inter\",\"arguments\":[{\"subsets\":[\"latin\"]}],\"variableName\":\"inter\"}":{"id":670,"name":"*","chunks":["185:static/chunks/app/layout-09ef1f5c8b0e56d1.js"],"async":false},"/app-path/src/app/globals.css":{"id":8410,"name":"*","chunks":["185:static/chunks/app/layout-09ef1f5c8b0e56d1.js"],"async":false}},"entryCSSFiles":{"/app-path/src/app/page":[],"/app-path/src/app/layout":["static/css/110a35ea7c81b899.css"]}}`;
77+
78+
export const serverReferenceManifest: ActionManifest = {
79+
node: {
80+
"123": {
81+
workers: { "app/another-s-a/page": 123, "app/server-action/page": 123 },
82+
layer: {
83+
"app/another-s-a/page": "action-browser",
84+
"app/server-action/page": "action-browser",
85+
"app/ssr/page": "rsc",
86+
},
87+
},
88+
},
89+
edge: {
90+
"123": {
91+
workers: { "app/server-action/edge/page": 123 },
92+
layer: { "app/server-action/edge/page": "action-browser" },
93+
},
94+
},
95+
encryptionKey: "456",
96+
};

src/test/frameworks/next/utils.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
getHeadersFromMetaFiles,
3333
isUsingNextImageInAppDirectory,
3434
getNextVersion,
35+
getRoutesWithServerAction,
3536
} from "../../../frameworks/next/utils";
3637

3738
import * as frameworksUtils from "../../../frameworks/utils";
@@ -63,6 +64,7 @@ import {
6364
pageClientReferenceManifestWithoutImage,
6465
clientReferenceManifestWithImage,
6566
clientReferenceManifestWithoutImage,
67+
serverReferenceManifest,
6668
} from "./helpers";
6769
import { pathsWithCustomRoutesInternalPrefix } from "./helpers/i18n";
6870

@@ -523,4 +525,12 @@ describe("Next.js utils", () => {
523525
expect(getNextVersion("")).to.be.undefined;
524526
});
525527
});
528+
529+
describe("getRoutesWithServerAction", () => {
530+
it("should get routes with server action", () => {
531+
expect(
532+
getRoutesWithServerAction(serverReferenceManifest, appPathRoutesManifest),
533+
).to.deep.equal(["/another-s-a", "/server-action", "/server-action/edge"]);
534+
});
535+
});
526536
});

0 commit comments

Comments
 (0)