mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-10 04:22:12 +00:00
[next] fix app dir edge functions with basePath (#10465)
x-ref: https://github.com/vercel/vercel/pull/10394
This commit is contained in:
5
.changeset/curvy-swans-tickle.md
Normal file
5
.changeset/curvy-swans-tickle.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@vercel/next": patch
|
||||
---
|
||||
|
||||
Fix Next.js with `basePath` + Edge runtime + App Router on a top level `page.jsx`
|
||||
@@ -91,6 +91,7 @@ import {
|
||||
getOperationType,
|
||||
isApiPage,
|
||||
getFunctionsConfigManifest,
|
||||
normalizeEdgeFunctionPath,
|
||||
} from './utils';
|
||||
|
||||
export const version = 2;
|
||||
@@ -2720,7 +2721,15 @@ async function getServerlessPages(params: {
|
||||
for (const edgeFunctionFile of Object.keys(
|
||||
middlewareManifest?.functions ?? {}
|
||||
)) {
|
||||
const edgePath = (edgeFunctionFile.slice(1) || 'index') + '.js';
|
||||
let edgePath =
|
||||
middlewareManifest?.functions?.[edgeFunctionFile].name ||
|
||||
edgeFunctionFile;
|
||||
|
||||
edgePath = normalizeEdgeFunctionPath(
|
||||
edgePath,
|
||||
params.appPathRoutesManifest || {}
|
||||
);
|
||||
edgePath = (edgePath || 'index') + '.js';
|
||||
delete normalizedAppPaths[edgePath];
|
||||
delete pages[edgePath];
|
||||
}
|
||||
|
||||
@@ -1245,10 +1245,9 @@ export async function serverBuild({
|
||||
if (ogRoute.endsWith('/route')) {
|
||||
continue;
|
||||
}
|
||||
route = path.posix.join(
|
||||
'./',
|
||||
entryDirectory,
|
||||
route === '/' ? '/index' : route
|
||||
route = normalizeIndexOutput(
|
||||
path.posix.join('./', entryDirectory, route === '/' ? '/index' : route),
|
||||
true
|
||||
);
|
||||
|
||||
if (lambdas[route]) {
|
||||
|
||||
@@ -2344,7 +2344,7 @@ export function normalizeIndexOutput(
|
||||
outputName: string,
|
||||
isServerMode: boolean
|
||||
) {
|
||||
if (outputName !== '/index' && isServerMode) {
|
||||
if (outputName !== 'index' && outputName !== '/index' && isServerMode) {
|
||||
return outputName.replace(/\/index$/, '');
|
||||
}
|
||||
return outputName;
|
||||
@@ -2521,6 +2521,29 @@ function normalizeRegions(regions: Regions): undefined | string | string[] {
|
||||
return newRegions;
|
||||
}
|
||||
|
||||
export function normalizeEdgeFunctionPath(
|
||||
shortPath: string,
|
||||
appPathRoutesManifest: Record<string, string>
|
||||
) {
|
||||
if (
|
||||
shortPath.startsWith('app/') &&
|
||||
(shortPath.endsWith('/page') ||
|
||||
shortPath.endsWith('/route') ||
|
||||
shortPath === 'app/_not-found')
|
||||
) {
|
||||
const ogRoute = shortPath.replace(/^app\//, '/');
|
||||
shortPath = (
|
||||
appPathRoutesManifest[ogRoute] ||
|
||||
shortPath.replace(/(^|\/)(page|route)$/, '')
|
||||
).replace(/^\//, '');
|
||||
|
||||
if (!shortPath || shortPath === '/') {
|
||||
shortPath = 'index';
|
||||
}
|
||||
}
|
||||
return shortPath;
|
||||
}
|
||||
|
||||
export async function getMiddlewareBundle({
|
||||
entryPath,
|
||||
outputDirectory,
|
||||
@@ -2699,27 +2722,19 @@ export async function getMiddlewareBundle({
|
||||
// app/index/page -> index/index
|
||||
if (shortPath.startsWith('pages/')) {
|
||||
shortPath = shortPath.replace(/^pages\//, '');
|
||||
} else if (
|
||||
shortPath.startsWith('app/') &&
|
||||
(shortPath.endsWith('/page') ||
|
||||
shortPath.endsWith('/route') ||
|
||||
shortPath === 'app/_not-found')
|
||||
) {
|
||||
const ogRoute = shortPath.replace(/^app\//, '/');
|
||||
shortPath = (
|
||||
appPathRoutesManifest[ogRoute] ||
|
||||
shortPath.replace(/(^|\/)(page|route)$/, '')
|
||||
).replace(/^\//, '');
|
||||
|
||||
if (!shortPath || shortPath === '/') {
|
||||
shortPath = 'index';
|
||||
}
|
||||
} else {
|
||||
shortPath = normalizeEdgeFunctionPath(shortPath, appPathRoutesManifest);
|
||||
}
|
||||
|
||||
if (routesManifest?.basePath) {
|
||||
shortPath = path.posix
|
||||
.join(routesManifest.basePath, shortPath)
|
||||
.replace(/^\//, '');
|
||||
shortPath = normalizeIndexOutput(
|
||||
path.posix.join(
|
||||
'./',
|
||||
routesManifest?.basePath,
|
||||
shortPath.replace(/^\//, '')
|
||||
),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
worker.edgeFunction.name = shortPath;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export const runtime = 'edge';
|
||||
|
||||
const Home = () => {
|
||||
return <div>another</div>;
|
||||
};
|
||||
|
||||
export default Home;
|
||||
@@ -0,0 +1,7 @@
|
||||
export const runtime = 'edge';
|
||||
|
||||
const Home = () => {
|
||||
return <div>dynamic</div>;
|
||||
};
|
||||
|
||||
export default Home;
|
||||
@@ -0,0 +1,11 @@
|
||||
export const runtime = 'edge';
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
return (
|
||||
<html>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
@@ -0,0 +1,7 @@
|
||||
export const runtime = 'edge';
|
||||
|
||||
const Home = () => {
|
||||
return <div>Home</div>;
|
||||
};
|
||||
|
||||
export default Home;
|
||||
@@ -0,0 +1,7 @@
|
||||
export const runtime = 'edge';
|
||||
|
||||
const Home = () => {
|
||||
return <div>test</div>;
|
||||
};
|
||||
|
||||
export default Home;
|
||||
@@ -0,0 +1,7 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
basePath: '/test',
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "latest",
|
||||
"react-dom": "latest"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "package.json", "use": "@vercel/next" }]
|
||||
}
|
||||
@@ -553,3 +553,52 @@ it('Should de-dupe correctly when limit is close (uncompressed)', async () => {
|
||||
expect(lambdas.size).toBe(2);
|
||||
expect(lambdas.size).toBeLessThan(totalLambdas);
|
||||
});
|
||||
|
||||
it('should handle edge functions in app with basePath', async () => {
|
||||
const {
|
||||
buildResult: { output },
|
||||
} = await runBuildLambda(path.join(__dirname, 'edge-app-dir-basepath'));
|
||||
|
||||
console.error(output);
|
||||
|
||||
expect(output['test']).toBeDefined();
|
||||
expect(output['test']).toBeDefined();
|
||||
expect(output['test'].type).toBe('EdgeFunction');
|
||||
expect(output['test'].type).toBe('EdgeFunction');
|
||||
|
||||
expect(output['test/another']).toBeDefined();
|
||||
expect(output['test/another.rsc']).toBeDefined();
|
||||
expect(output['test/another'].type).toBe('EdgeFunction');
|
||||
expect(output['test/another.rsc'].type).toBe('EdgeFunction');
|
||||
|
||||
expect(output['test/dynamic/[slug]']).toBeDefined();
|
||||
expect(output['test/dynamic/[slug].rsc']).toBeDefined();
|
||||
expect(output['test/dynamic/[slug]'].type).toBe('EdgeFunction');
|
||||
expect(output['test/dynamic/[slug].rsc'].type).toBe('EdgeFunction');
|
||||
|
||||
expect(output['test/dynamic/[slug]']).toBeDefined();
|
||||
expect(output['test/dynamic/[slug].rsc']).toBeDefined();
|
||||
expect(output['test/dynamic/[slug]'].type).toBe('EdgeFunction');
|
||||
expect(output['test/dynamic/[slug].rsc'].type).toBe('EdgeFunction');
|
||||
|
||||
expect(output['test/test']).toBeDefined();
|
||||
expect(output['test/test.rsc']).toBeDefined();
|
||||
expect(output['test/test'].type).toBe('EdgeFunction');
|
||||
expect(output['test/test.rsc'].type).toBe('EdgeFunction');
|
||||
|
||||
expect(output['test/_not-found']).toBeDefined();
|
||||
expect(output['test/_not-found'].type).toBe('Lambda');
|
||||
|
||||
const lambdas = new Set();
|
||||
const edgeFunctions = new Set();
|
||||
|
||||
for (const item of Object.values(output)) {
|
||||
if (item.type === 'Lambda') {
|
||||
lambdas.add(item);
|
||||
} else if (item.type === 'EdgeFunction') {
|
||||
edgeFunctions.add(item);
|
||||
}
|
||||
}
|
||||
expect(lambdas.size).toBe(1);
|
||||
expect(edgeFunctions.size).toBe(4);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user