Skip to content

Commit 87e183b

Browse files
feat: new routing system runtime implementation and changes (#206)
* feat: new routing system runtime changes * fix: pages `/index` route matching * fix: .rsc bugs * fix: typo + test * chore: update supported doc * apply suggestions * Update src/buildApplication/processVercelOutput.ts Co-authored-by: Dario Piotrowicz <dario.piotrowicz@gmail.com> * Apply suggestions from code review Co-authored-by: Dario Piotrowicz <dario.piotrowicz@gmail.com> * apply suggestions * apply suggestions * Apply suggestions from code review Co-authored-by: Dario Piotrowicz <dario.piotrowicz@gmail.com> * apply suggestions * feat: use classes for router and matcher * Apply suggestions from code review Co-authored-by: Dario Piotrowicz <dario.piotrowicz@gmail.com> * apply suggestions + new tests * rename `matcher.ts` to `routes-matcher.ts` * fix: invalid function squashing Fixes invalid routes not getting squashed by route paths. The relative path is needed in the `invalidFunctions` map so that when `tryToFixInvalidFunctions` is called, it is able to match the squashed path, instead of just the file name. * fix: invalid functions string in tests * feat: generate worker when no functions are found * update mode of bin file * run prettier:fix * fix: test failing from change to minify * Update src/buildApplication/buildApplication.ts Co-authored-by: Dario Piotrowicz <dario.piotrowicz@gmail.com> * fix broken console.log * run prettier:fix * fix: rewrite phase not entering after fs maps $1 to $1 with check: true fixes #70 * fix: request parameters not always applied * fix: rewritten paths not matching rsc route * fix: search params not applied to new request instance in `createRouteRequest` * chore: improve test name + comment * expose a router.handle() method --------- Co-authored-by: Dario Piotrowicz <dario.piotrowicz@gmail.com> Co-authored-by: Dario Piotrowicz <dario@cloudflare.com>
1 parent bb23b60 commit 87e183b

37 files changed

+2876
-1076
lines changed

.changeset/orange-sloths-love.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@cloudflare/next-on-pages': minor
3+
---
4+
5+
New routing system runtime handling and implementation.
6+
7+
Improves support for advanced routing with Next.js applications on Pages, through leveraging the Vercel build output configuration. The Vercel build output specifies the relevant routing steps that are taken during the lifetime of a request, and this change implements a new system that handles these steps.

docs/supported.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ Earlier and Later versions might be only partially supported, we don't fully kno
1616
| ----------------------- | ------- |
1717
| version | `3` |
1818
| routes `src` ||
19-
| routes `dest` | 🔄 |
20-
| routes `headers` | 🔄 |
19+
| routes `dest` | |
20+
| routes `headers` | |
2121
| routes `methods` ||
22-
| routes `continue` | 🔄 |
22+
| routes `continue` | |
2323
| routes `caseSensitive` ||
24-
| routes `check` | 🔄 |
25-
| routes `status` | 🔄 |
24+
| routes `check` | |
25+
| routes `status` | |
2626
| routes `has` ||
2727
| routes `missing` ||
2828
| routes `locale` | 🔄 |
@@ -47,9 +47,9 @@ Earlier and Later versions might be only partially supported, we don't fully kno
4747
| ------------------------------------------ | ------- |
4848
| environment variables | 🔄 |
4949
| base path ||
50-
| rewrites | 🔄 |
51-
| redirects | 🔄 |
52-
| custom headers | 🔄 |
50+
| rewrites | |
51+
| redirects | |
52+
| custom headers | |
5353
| custom page extensions ||
5454
| CDN support with asset prefix | 🔄 |
5555
| custom Image loader config | 🔄 |

package-lock.json

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"cookie": "^0.5.0",
2929
"esbuild": "^0.15.3",
3030
"js-yaml": "^4.1.0",
31+
"pcre-to-regexp": "^1.1.0",
3132
"zod": "^3.21.4",
3233
"zodcli": "^0.0.4"
3334
},

src/buildApplication/buildApplication.ts

+20-38
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ import { exit } from 'process';
22
import { resolve } from 'path';
33
import type { CliOptions } from '../cli';
44
import { cliError, cliLog } from '../cli';
5-
import type { MiddlewareManifestData } from './middlewareManifest';
6-
import { getParsedMiddlewareManifest } from './middlewareManifest';
7-
import { getNextJsConfigs } from './nextJsConfigs';
85
import { getVercelConfig } from './getVercelConfig';
96
import { buildWorkerFile } from './buildWorkerFile';
7+
import type { DirectoryProcessingResults } from './generateFunctionsMap';
108
import { generateFunctionsMap } from './generateFunctionsMap';
119
import {
1210
buildVercelOutput,
@@ -77,58 +75,42 @@ async function prepareAndBuildWorker(
7775
exit(1);
7876
}
7977

80-
const nextJsConfigs = await getNextJsConfigs();
81-
82-
if (nextJsConfigs.basePath) {
83-
cliLog(`Using basePath ${nextJsConfigs.basePath}`);
84-
}
78+
let generatedFunctionsMaps: DirectoryProcessingResults | undefined;
8579

8680
const functionsDir = resolve('.vercel', 'output', 'functions');
8781
if (!(await validateDir(functionsDir))) {
88-
cliLog('No functions detected.');
89-
return;
90-
}
91-
92-
const { invalidFunctions, functionsMap, prerenderedRoutes } =
93-
await generateFunctionsMap(functionsDir, options.disableChunksDedup);
94-
95-
if (invalidFunctions.size > 0) {
96-
printInvalidFunctionsErrorMessage(Array.from(invalidFunctions));
97-
exit(1);
98-
}
99-
100-
if (functionsMap.size === 0) {
101-
cliLog('No functions detected.');
102-
return;
103-
}
82+
cliLog(
83+
'No functions detected (no functions directory generated by Vercel).'
84+
);
85+
} else {
86+
generatedFunctionsMaps = await generateFunctionsMap(
87+
functionsDir,
88+
options.disableChunksDedup
89+
);
10490

105-
// NOTE: Middleware manifest logic will be removed in the new routing system. (see issue #129)
106-
let middlewareManifestData: MiddlewareManifestData;
91+
if (generatedFunctionsMaps.invalidFunctions.size > 0) {
92+
printInvalidFunctionsErrorMessage(
93+
Array.from(generatedFunctionsMaps.invalidFunctions)
94+
);
95+
exit(1);
96+
}
10797

108-
try {
109-
middlewareManifestData = await getParsedMiddlewareManifest(
110-
functionsMap,
111-
nextJsConfigs
112-
);
113-
} catch (e: unknown) {
114-
if (e instanceof Error) {
115-
cliError(e.message, { showReport: true });
98+
if (generatedFunctionsMaps.functionsMap.size === 0) {
99+
cliLog('No functions detected.');
116100
}
117-
exit(1);
118101
}
119102

120103
const staticAssets = await getVercelStaticAssets();
121104

122105
const processedVercelOutput = processVercelOutput(
123106
vercelConfig,
124107
staticAssets,
125-
prerenderedRoutes,
126-
middlewareManifestData
108+
generatedFunctionsMaps?.prerenderedRoutes,
109+
generatedFunctionsMaps?.functionsMap
127110
);
128111

129112
await buildWorkerFile(
130113
processedVercelOutput,
131-
nextJsConfigs,
132114
!options.disableWorkerMinification
133115
);
134116
}

src/buildApplication/buildWorkerFile.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { Plugin } from 'esbuild';
44
import { build } from 'esbuild';
55
import { tmpdir } from 'os';
66
import { cliSuccess } from '../cli';
7-
import type { NextJsConfigs } from './nextJsConfigs';
87
import { generateGlobalJs } from './generateGlobalJs';
98
import type { ProcessedVercelOutput } from './processVercelOutput';
109

@@ -14,7 +13,7 @@ import type { ProcessedVercelOutput } from './processVercelOutput';
1413
* @param item The build output item to construct a record for.
1514
* @returns Record for the build output map.
1615
*/
17-
function constructBuildOutputRecord(item: BuildOutputItem) {
16+
export function constructBuildOutputRecord(item: BuildOutputItem) {
1817
return item.type === 'static'
1918
? `{ type: ${JSON.stringify(item.type)} }`
2019
: item.type === 'override'
@@ -25,15 +24,12 @@ function constructBuildOutputRecord(item: BuildOutputItem) {
2524
}`
2625
: `{
2726
type: ${JSON.stringify(item.type)},
28-
entrypoint: AsyncLocalStoragePromise.then(() => import('${item.entrypoint}')),
29-
matchers: ${JSON.stringify(item.matchers)}
27+
entrypoint: AsyncLocalStoragePromise.then(() => import('${item.entrypoint}'))
3028
}`;
3129
}
3230

33-
// NOTE: `nextJsConfigs`, and accompanying logic will be removed in the new routing system. (see issue #129)
3431
export async function buildWorkerFile(
3532
{ vercelConfig, vercelOutput }: ProcessedVercelOutput,
36-
nextJsConfigs: NextJsConfigs,
3733
minify: boolean
3834
) {
3935
const functionsFile = join(
@@ -67,7 +63,6 @@ export async function buildWorkerFile(
6763
external: ['node:async_hooks', 'node:buffer'],
6864
define: {
6965
__CONFIG__: JSON.stringify(vercelConfig),
70-
__BASE_PATH__: JSON.stringify(nextJsConfigs.basePath ?? ''),
7166
},
7267
outfile: outputFile,
7368
minify,

src/buildApplication/generateFunctionsMap.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ async function processFuncDirectory(
180180
return {};
181181
}
182182
return {
183-
invalidFunctions: new Set([file]),
183+
invalidFunctions: new Set([relativePath]),
184184
};
185185
}
186186

@@ -205,7 +205,7 @@ async function processFuncDirectory(
205205
}
206206

207207
return {
208-
invalidFunctions: new Set([file]),
208+
invalidFunctions: new Set([relativePath]),
209209
};
210210
}
211211

@@ -403,7 +403,7 @@ type ProcessingSetup = {
403403
disableChunksDedup: boolean;
404404
};
405405

406-
type DirectoryProcessingResults = {
406+
export type DirectoryProcessingResults = {
407407
invalidFunctions: Set<string>;
408408
functionsMap: Map<string, string>;
409409
webpackChunks: Map<number, string>;

src/buildApplication/middlewareManifest.ts

-150
This file was deleted.

0 commit comments

Comments
 (0)