diff --git a/packages/runtime/src/helpers/edge.ts b/packages/runtime/src/helpers/edge.ts index bdaa21664f..59b9b85cb0 100644 --- a/packages/runtime/src/helpers/edge.ts +++ b/packages/runtime/src/helpers/edge.ts @@ -263,7 +263,7 @@ export const writeDevEdgeFunction = async ({ * Writes an edge function that routes RSC data requests to the `.rsc` route */ -export const writeRscDataEdgeFunction = async ({ +export const generateRscDataEdgeManifest = async ({ prerenderManifest, appPathRoutesManifest, }: { @@ -275,14 +275,14 @@ export const writeRscDataEdgeFunction = async ({ } const staticAppdirRoutes: Array = [] for (const [path, route] of Object.entries(prerenderManifest.routes)) { - if (isAppDirRoute(route.srcRoute, appPathRoutesManifest)) { + if (isAppDirRoute(route.srcRoute, appPathRoutesManifest) && route.dataRoute) { staticAppdirRoutes.push(path, route.dataRoute) } } const dynamicAppDirRoutes: Array = [] for (const [path, route] of Object.entries(prerenderManifest.dynamicRoutes)) { - if (isAppDirRoute(path, appPathRoutesManifest)) { + if (isAppDirRoute(path, appPathRoutesManifest) && route.dataRouteRegex) { dynamicAppDirRoutes.push(route.routeRegex, route.dataRouteRegex) } } @@ -368,7 +368,7 @@ export const writeEdgeFunctions = async ({ return } - const rscFunctions = await writeRscDataEdgeFunction({ + const rscFunctions = await generateRscDataEdgeManifest({ prerenderManifest: await loadPrerenderManifest(netlifyConfig), appPathRoutesManifest: await loadAppPathRoutesManifest(netlifyConfig), }) diff --git a/test/edge.spec.ts b/test/edge.spec.ts new file mode 100644 index 0000000000..80d6d782ce --- /dev/null +++ b/test/edge.spec.ts @@ -0,0 +1,118 @@ +import { generateRscDataEdgeManifest } from '../packages/runtime/src/helpers/edge' +import type { PrerenderManifest } from 'next/dist/build' + +const basePrerenderManifest: PrerenderManifest = { + version: 3, + routes: {}, + dynamicRoutes: {}, + notFoundRoutes: [], + preview: { + previewModeId: '', + previewModeSigningKey: '', + previewModeEncryptionKey: '', + }, +} + +describe('generateRscDataEdgeManifest', () => { + it('should return manifest entries for static appDir routes', async () => { + const prerenderManifest: PrerenderManifest = { + ...basePrerenderManifest, + routes: { + '/': { + initialRevalidateSeconds: false, + srcRoute: '/', + dataRoute: '/index.rsc', + }, + }, + } + const appPathRoutesManifest = { + '/page': '/', + } + const edgeManifest = await generateRscDataEdgeManifest({ prerenderManifest, appPathRoutesManifest }) + + expect(edgeManifest).toEqual([ + { + function: 'rsc-data', + name: 'RSC data routing', + path: '/', + }, + { + function: 'rsc-data', + name: 'RSC data routing', + path: '/index.rsc', + }, + ]) + }) + + it('should not return manifest entries for static appDir routes without dataRoutes', async () => { + const prerenderManifest: PrerenderManifest = { + ...basePrerenderManifest, + routes: { + '/api/hello': { + initialRevalidateSeconds: false, + srcRoute: '/api/hello', + dataRoute: null, + }, + }, + } + const appPathRoutesManifest = { + '/api/hello/route': '/api/hello', + } + const edgeManifest = await generateRscDataEdgeManifest({ prerenderManifest, appPathRoutesManifest }) + + expect(edgeManifest).toEqual([]) + }) + + it('should return manifest entries for dynamic appDir routes', async () => { + const prerenderManifest: PrerenderManifest = { + ...basePrerenderManifest, + dynamicRoutes: { + '/blog/[author]': { + routeRegex: '^/blog/([^/]+?)(?:/)?$', + dataRoute: '/blog/[author].rsc', + fallback: null, + dataRouteRegex: '^/blog/([^/]+?)\\.rsc$', + }, + }, + } + + const appPathRoutesManifest = { + '/blog/[author]/page': '/blog/[author]', + } + const edgeManifest = await generateRscDataEdgeManifest({ prerenderManifest, appPathRoutesManifest }) + + expect(edgeManifest).toEqual([ + { + function: 'rsc-data', + name: 'RSC data routing', + pattern: '^/blog/([^/]+?)(?:/)?$', + }, + { + function: 'rsc-data', + name: 'RSC data routing', + pattern: '^/blog/([^/]+?)\\.rsc$', + }, + ]) + }) + + it('should not return manifest entries for dynamic appDir routes without dataRouteRegex', async () => { + const prerenderManifest: PrerenderManifest = { + ...basePrerenderManifest, + dynamicRoutes: { + '/api/[endpoint]': { + routeRegex: '^/api/([^/]+?)(?:/)?$', + dataRoute: '/api/[endpoint].rsc', + fallback: null, + dataRouteRegex: null, + }, + }, + } + + const appPathRoutesManifest = { + '/api/[endpoint]/route': '/api/[endpoint]', + } + const edgeManifest = await generateRscDataEdgeManifest({ prerenderManifest, appPathRoutesManifest }) + + expect(edgeManifest).toEqual([]) + }) +})