Skip to content

Commit

Permalink
[next] Fix functions config with App Router (#9889)
Browse files Browse the repository at this point in the history
We added appDir support in #9811 so that users can customize `memory`/`maxDuration` for routes in appDir.

But since RSC is enabled by default in Next.js 13, `vercel build` still reports some warning messages, such as:

```json
"functions": {
  "app/**/*": {
    "maxDuration": 5,
    "memory": 512
  }
}
```
```
WARNING: Unable to find source file for page hello.js with extensions: ts, tsx, js, jsx, md, mdx, this can cause functions config from `vercel.json` to not be applied
WARNING: Unable to find source file for page index.js with extensions: ts, tsx, js, jsx, md, mdx, this can cause functions config from `vercel.json` to not be applied
```

To suppress these errors and properly apply `functions` setting to those routes, updating the current detection logic to also search `page.${ext}` files.
  • Loading branch information
smaeda-ks committed May 25, 2023
1 parent 96b2502 commit c6c1935
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/funny-garlics-refuse.md
@@ -0,0 +1,5 @@
---
"@vercel/next": patch
---

[next] Fix `functions` config with App Router
53 changes: 43 additions & 10 deletions packages/next/src/utils.ts
Expand Up @@ -1235,10 +1235,22 @@ let _usesSrcCache: boolean | undefined;

async function usesSrcDirectory(workPath: string): Promise<boolean> {
if (!_usesSrcCache) {
const source = path.join(workPath, 'src', 'pages');
const sourcePages = path.join(workPath, 'src', 'pages');

try {
if ((await fs.stat(source)).isDirectory()) {
if ((await fs.stat(sourcePages)).isDirectory()) {
_usesSrcCache = true;
}
} catch (_err) {
_usesSrcCache = false;
}
}

if (!_usesSrcCache) {
const sourceAppdir = path.join(workPath, 'src', 'app');

try {
if ((await fs.stat(sourceAppdir)).isDirectory()) {
_usesSrcCache = true;
}
} catch (_err) {
Expand All @@ -1258,13 +1270,14 @@ async function getSourceFilePathFromPage({
page: string;
pageExtensions?: string[];
}) {
const usesSrcDir = await usesSrcDirectory(workPath);
// TODO: this should be updated to get the pageExtensions
// value used during next build
const extensionsToTry = pageExtensions || ['js', 'jsx', 'ts', 'tsx'];

for (const pageType of ['pages', 'app']) {
let fsPath = path.join(workPath, pageType, page);
if (await usesSrcDirectory(workPath)) {
if (usesSrcDir) {
fsPath = path.join(workPath, 'src', pageType, page);
}

Expand All @@ -1275,20 +1288,40 @@ async function getSourceFilePathFromPage({

for (const ext of extensionsToTry) {
fsPath = `${extensionless}.${ext}`;
// for appDir, we need to treat "index.js" as root-level "page.js"
if (
pageType === 'app' &&
extensionless ===
path.join(workPath, `${usesSrcDir ? 'src/' : ''}app/index`)
) {
fsPath = `${extensionless.replace(/index$/, 'page')}.${ext}`;
}
if (fs.existsSync(fsPath)) {
return path.relative(workPath, fsPath);
}
}

if (isDirectory(extensionless)) {
for (const ext of extensionsToTry) {
fsPath = path.join(extensionless, `index.${ext}`);
if (fs.existsSync(fsPath)) {
return path.relative(workPath, fsPath);
if (pageType === 'pages') {
for (const ext of extensionsToTry) {
fsPath = path.join(extensionless, `index.${ext}`);
if (fs.existsSync(fsPath)) {
return path.relative(workPath, fsPath);
}
}
fsPath = path.join(extensionless, `route.${ext}`);
if (fs.existsSync(fsPath)) {
return path.relative(workPath, fsPath);
// appDir
} else {
for (const ext of extensionsToTry) {
// RSC
fsPath = path.join(extensionless, `page.${ext}`);
if (fs.existsSync(fsPath)) {
return path.relative(workPath, fsPath);
}
// Route Handlers
fsPath = path.join(extensionless, `route.${ext}`);
if (fs.existsSync(fsPath)) {
return path.relative(workPath, fsPath);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/next/test/fixtures/00-app-dir/vercel.json
Expand Up @@ -5,7 +5,7 @@
"use": "@vercel/next",
"config": {
"functions": {
"app/api/**/*": {
"app/**/*": {
"maxDuration": 5,
"memory": 512
},
Expand Down
7 changes: 7 additions & 0 deletions packages/next/test/integration/integration-1.test.js
Expand Up @@ -73,6 +73,13 @@ if (parseInt(process.versions.node.split('.')[0], 10) >= 16) {
).toBeFalsy();

expect(lambdas.size).toBe(4);

// RSC, root-level page.js
expect(buildResult.output['index']).toBeDefined();
expect(buildResult.output['index'].type).toBe('Lambda');
expect(buildResult.output['index'].memory).toBe(512);
expect(buildResult.output['index'].maxDuration).toBe(5);

expect(buildResult.output['dashboard']).toBeDefined();
expect(buildResult.output['dashboard/another']).toBeDefined();
expect(buildResult.output['dashboard/changelog']).toBeDefined();
Expand Down

0 comments on commit c6c1935

Please sign in to comment.