Skip to content

Commit 7d7d5a7

Browse files
authored
Fix shared layer bundling in Edge Runtime (#51348)
Our shared layer matcher doesn't contain `next/dist/esm`, which breaks Server Actions when there're cookie/header accesses. Closes #50099. Fix NEXT-1229
1 parent a806f1a commit 7d7d5a7

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

packages/next/src/build/webpack-config.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ const babelIncludeRegexes: RegExp[] = [
9797
const reactPackagesRegex = /^(react|react-dom|react-server-dom-webpack)($|\/)/
9898

9999
const asyncStoragesRegex =
100-
/next[\\/]dist[\\/]client[\\/]components[\\/](static-generation-async-storage|action-async-storage|request-async-storage)/
100+
/next[\\/]dist[\\/](esm[\\/])?client[\\/]components[\\/](static-generation-async-storage|action-async-storage|request-async-storage)/
101101

102102
// exports.<conditionName>
103103
const edgeConditionNames = [
@@ -1894,6 +1894,12 @@ export default async function getBaseWebpackConfig(
18941894
rules: [
18951895
...(hasAppDir
18961896
? [
1897+
{
1898+
// Make sure that AsyncLocalStorage module instance is shared between server and client
1899+
// layers.
1900+
layer: WEBPACK_LAYERS.shared,
1901+
test: asyncStoragesRegex,
1902+
},
18971903
{
18981904
// All app dir layers need to use this configured resolution logic
18991905
issuerLayer: {
@@ -1957,12 +1963,6 @@ export default async function getBaseWebpackConfig(
19571963
loader: 'next-flight-loader',
19581964
},
19591965
},
1960-
{
1961-
// Make sure that AsyncLocalStorage module instance is shared between server and client
1962-
// layers.
1963-
layer: WEBPACK_LAYERS.shared,
1964-
test: asyncStoragesRegex,
1965-
},
19661966
]
19671967
: []),
19681968
// TODO: FIXME: do NOT webpack 5 support with this

test/e2e/app-dir/actions/app-action.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,23 @@ createNextDescribe(
351351
return browser.eval('window.location.toString()')
352352
}, 'https://example.com/')
353353
})
354+
355+
it('should allow cookie and header async storages', async () => {
356+
const browser = await next.browser('/client/edge')
357+
358+
const currentTestCookie = await browser.eval(
359+
`document.cookie.match(/test-cookie=(\\d+)/)?.[1]`
360+
)
361+
362+
await browser.elementByCss('#get-headers').click()
363+
364+
await check(async () => {
365+
const newTestCookie = await browser.eval(
366+
`document.cookie.match(/test-cookie=(\\d+)/)?.[1]`
367+
)
368+
return newTestCookie !== currentTestCookie ? 'success' : 'failure'
369+
}, 'success')
370+
})
354371
})
355372

356373
describe('fetch actions', () => {

test/e2e/app-dir/actions/app/client/edge/page.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useState } from 'react'
44

5-
import double, { inc, dec, redirectAction } from '../actions'
5+
import double, { inc, dec, redirectAction, getHeaders } from '../actions'
66

77
export default function Counter() {
88
const [count, setCount] = useState(0)
@@ -52,6 +52,11 @@ export default function Counter() {
5252
redirect external
5353
</button>
5454
</form>
55+
<form>
56+
<button id="get-headers" formAction={() => getHeaders()}>
57+
get headers
58+
</button>
59+
</form>
5560
</div>
5661
)
5762
}

0 commit comments

Comments
 (0)