Skip to content

Commit 7f20cbd

Browse files
authored
Turbopack: symlinks and parent globs in outputFileTracingIncludes (#82528)
1. Don't resolve symlinks in `outputFileTracingIncludes`. Otherwise if you specify `node_modules/foo/*` in there, it will resolve to `node_modules/.pnpm/foo/*` and `require("foo")` won't work anymore because there no symlink in `node_modules/foo` anymore. This is also what happens with Webpack 2. Align `read_glob` with `read_dir` in that the hashmap keys only contain the path segment, and not the full path. 3. Support globing parents of the start folder: if the glob can match `..`, then also try to match `directory.parent_folder().read_glob(glob)` Closes PACK-5219
1 parent bd802d1 commit 7f20cbd

File tree

13 files changed

+224
-63
lines changed

13 files changed

+224
-63
lines changed

crates/next-api/src/nft_json.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ async fn apply_includes(
104104
) -> Result<BTreeSet<RcStr>> {
105105
debug_assert_eq!(project_root_path.fs, ident_folder.fs);
106106
// Read files matching the glob pattern from the project root
107+
// This result itself has random order, but the BTreeSet will ensure a deterministic ordering.
107108
let glob_result = project_root_path.read_glob(glob).await?;
108109

109110
// Walk the full glob_result using an explicit stack to avoid async recursion overheads.
@@ -113,15 +114,15 @@ async fn apply_includes(
113114
while let Some(glob_result) = stack.pop_back() {
114115
// Process direct results (files and directories at this level)
115116
for entry in glob_result.results.values() {
116-
let DirectoryEntry::File(file_path) = entry else {
117+
let (DirectoryEntry::File(file_path) | DirectoryEntry::Symlink(file_path)) = entry
118+
else {
117119
continue;
118120
};
119121

120-
let file_path_ref = file_path;
121122
// Convert to relative path from ident_folder to the file
122123
// unwrap is safe because project_root_path and ident_folder have the same filesystem
123124
// and paths produced by read_glob stay in the filesystem
124-
let relative_path = ident_folder.get_relative_path_to(file_path_ref).unwrap();
125+
let relative_path = ident_folder.get_relative_path_to(file_path).unwrap();
125126
result.insert(relative_path);
126127
}
127128

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const dynamic = 'force-dynamic'
2+
3+
export async function GET() {
4+
return new Response('foo')
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
outputFileTracingIncludes: {
3+
'/route1': ['../other/included.txt'],
4+
},
5+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
data
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* eslint-env jest */
2+
3+
import fs from 'fs-extra'
4+
import { join } from 'path'
5+
import { nextBuild } from 'next-test-utils'
6+
7+
const appDir = join(__dirname, '../app')
8+
9+
describe('build trace with extra entries in monorepo', () => {
10+
;(process.env.TURBOPACK_DEV ? describe.skip : describe)(
11+
'production mode',
12+
() => {
13+
it('should build and trace correctly', async () => {
14+
const result = await nextBuild(appDir, undefined, {
15+
cwd: appDir,
16+
stderr: true,
17+
stdout: true,
18+
})
19+
expect(result.code).toBe(0)
20+
console.log(result.stderr)
21+
console.log(result.stdout)
22+
23+
const appDirRoute1Trace = await fs.readJSON(
24+
join(appDir, '.next/server/app/route1/route.js.nft.json')
25+
)
26+
27+
expect(appDirRoute1Trace.files).toContain(
28+
'../../../../../other/included.txt'
29+
)
30+
})
31+
}
32+
)
33+
})

test/integration/build-trace-extra-entries/app/include-me-global.txt

Whitespace-only changes.

test/integration/build-trace-extra-entries/app/next.config.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ const path = require('path')
22

33
module.exports = {
44
webpack(cfg, { isServer, nextRuntime }) {
5-
console.log(cfg.entry)
65
const origEntry = cfg.entry
76
cfg.entry = async () => {
87
const origEntries = await origEntry()
@@ -13,15 +12,15 @@ module.exports = {
1312
path.join(__dirname, 'lib/get-data.js'),
1413
...curEntry,
1514
]
16-
console.log(origEntries)
1715
}
1816
return origEntries
1917
}
2018
return cfg
2119
},
2220
outputFileTracingIncludes: {
2321
'/index': ['include-me/**/*'],
24-
'/route1': ['./include-me/**/*'],
22+
'/route1': ['./include-me/**/*', 'node_modules/pkg-behind-symlink/*'],
23+
'/*': ['include-me-global.txt'],
2524
},
2625
outputFileTracingExcludes: {
2726
'/index': ['public/exclude-me/**/*'],

test/integration/build-trace-extra-entries/app/node_modules/pkg-behind-symlink

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/integration/build-trace-extra-entries/app/node_modules/pkg/index.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/integration/build-trace-extra-entries/app/node_modules/pkg/package.json

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)