Skip to content

Commit c4c3aee

Browse files
authored
Fix --no-mangling for "use cache" functions (vercel#78993)
When mangling is disabled with `next build --no-mangling`, the function names of `"use cache"` functions are currently still mangled. The reason is that those functions are transformed to inline function expressions whose names are removed by the SWC minifier even if `mangle` is `false`. Original: ```js 'use cache' export async function getCachedData() { return functionThatMightThrow() } ``` Transformed by the Next.js compiler during `next dev`: ```js export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "<id>", 0, async function getCachedData() { return functionThatMightThrow() }); ``` Transformed by the Next.js compiler during `next build`: ```js export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "<id>", 0, async function () { return functionThatMightThrow() }); ``` By setting `keep_fnames` to `true` in SWC's `compress` options, we can ensure that those function expression names are preserved when building with `--no-mangling`, which is helpful when looking at error stacks or traces.
1 parent 2086975 commit c4c3aee

File tree

5 files changed

+32
-1
lines changed

5 files changed

+32
-1
lines changed

packages/next/src/build/webpack/plugins/minify-webpack-plugin/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ export class MinifyPlugin {
145145
global_defs: {
146146
'process.env.__NEXT_PRIVATE_MINIMIZE_MACRO_FALSE': false,
147147
},
148+
keep_classnames: this.options.noMangling,
149+
keep_fnames: this.options.noMangling,
148150
},
149151
mangle,
150152
module: 'unknown',
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use cache'
2+
3+
export default async function CachedPage() {
4+
throw new Error('Kaputt!')
5+
return <p>hello world</p>
6+
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
/**
22
* @type {import('next').NextConfig}
33
*/
4-
const nextConfig = {}
4+
const nextConfig = {
5+
experimental: {
6+
useCache: true,
7+
prerenderEarlyExit: false,
8+
},
9+
}
510

611
module.exports = nextConfig

test/production/app-dir/no-mangling/no-mangling.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,21 @@ Error: Kaputt!
4646
Error: Kaputt!
4747
at Page`)
4848
})
49+
50+
describe('with "use cache" functions', () => {
51+
it('should show original function names in stack traces', async () => {
52+
try {
53+
await next.build()
54+
} catch {
55+
// we expect the build to fail
56+
}
57+
58+
// `CachedPage` is the original function name that would be mangled if
59+
// `next build` was called without `--no-mangling`.
60+
expect(next.cliOutput).toInclude(`
61+
Error: Kaputt!
62+
at CachedPage`)
63+
})
64+
})
4965
})
5066
})

turbopack/crates/turbopack-ecmascript/src/minify.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ pub fn minify(code: &Code, source_maps: bool, mangle: Option<MangleType>) -> Res
8585
// Only run 2 passes, this is a tradeoff between performance and
8686
// compression size. Default is 3 passes.
8787
passes: 2,
88+
keep_classnames: mangle.is_none(),
89+
keep_fnames: mangle.is_none(),
8890
..Default::default()
8991
}),
9092
mangle: mangle.map(|mangle| {

0 commit comments

Comments
 (0)