Skip to content

Commit 8d6ea82

Browse files
committed
Current behavior of import conditions
1 parent d7d5117 commit 8d6ea82

File tree

21 files changed

+522
-0
lines changed

21 files changed

+522
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use client'
2+
import * as React from 'react'
3+
import * as react from 'library-with-exports/react'
4+
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
5+
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'
6+
7+
export default function ClientPage({
8+
action,
9+
server,
10+
}: {
11+
action: () => Promise<Record<string, string>>
12+
server: unknown
13+
}) {
14+
const [actionValue, formAction, isPending] = React.useActionState(
15+
action,
16+
undefined
17+
)
18+
const [client, setClient] = React.useState<unknown | null>(null)
19+
React.useEffect(() => {
20+
setClient({
21+
react: react.condition,
22+
serverFavoringBrowser: serverFavoringBrowser.condition,
23+
serverFavoringEdge: serverFavoringEdge.condition,
24+
})
25+
}, [])
26+
27+
return (
28+
<form action={formAction}>
29+
<input type="submit" />
30+
<output aria-busy={client === null || isPending}>
31+
{client === null ? (
32+
<pre>{JSON.stringify({ server }, null, 2)}</pre>
33+
) : (
34+
<pre>
35+
{JSON.stringify({ server, client, action: actionValue }, null, 2)}
36+
</pre>
37+
)}
38+
</output>
39+
</form>
40+
)
41+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as react from 'library-with-exports/react'
2+
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
3+
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'
4+
import ClientPage from '../ClientPage'
5+
6+
export const runtime = 'edge'
7+
8+
async function action() {
9+
'use server'
10+
return {
11+
react: react.condition,
12+
serverFavoringBrowser: serverFavoringBrowser.condition,
13+
serverFavoringEdge: serverFavoringEdge.condition,
14+
}
15+
}
16+
17+
export default function Page() {
18+
return (
19+
<ClientPage
20+
action={action}
21+
server={{
22+
react: react.condition,
23+
serverFavoringBrowser: serverFavoringBrowser.condition,
24+
serverFavoringEdge: serverFavoringEdge.condition,
25+
}}
26+
/>
27+
)
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as react from 'library-with-exports/react'
2+
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
3+
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'
4+
import ClientPage from '../ClientPage'
5+
6+
export const runtime = 'nodejs'
7+
8+
async function action() {
9+
'use server'
10+
return {
11+
react: react.condition,
12+
serverFavoringBrowser: serverFavoringBrowser.condition,
13+
serverFavoringEdge: serverFavoringEdge.condition,
14+
}
15+
}
16+
17+
export default function Page() {
18+
return (
19+
<ClientPage
20+
action={action}
21+
server={{
22+
react: react.condition,
23+
serverFavoringBrowser: serverFavoringBrowser.condition,
24+
serverFavoringEdge: serverFavoringEdge.condition,
25+
}}
26+
/>
27+
)
28+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as react from 'library-with-exports/react'
2+
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
3+
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'
4+
5+
export const runtime = 'edge'
6+
7+
export function GET() {
8+
return Response.json({
9+
react: react.condition,
10+
serverFavoringBrowser: serverFavoringBrowser.condition,
11+
serverFavoringEdge: serverFavoringEdge.condition,
12+
})
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function Root({ children }: { children: React.ReactNode }) {
2+
return (
3+
<html>
4+
<body>{children}</body>
5+
</html>
6+
)
7+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as react from 'library-with-exports/react'
2+
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
3+
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'
4+
5+
export const runtime = 'nodejs'
6+
7+
export function GET() {
8+
return Response.json({
9+
react: react.condition,
10+
serverFavoringBrowser: serverFavoringBrowser.condition,
11+
serverFavoringEdge: serverFavoringEdge.condition,
12+
})
13+
}
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
import { nextTestSetup } from 'e2e-utils'
2+
3+
describe('react version', () => {
4+
const { next } = nextTestSetup({
5+
files: __dirname,
6+
dependencies: {
7+
'library-with-exports': 'link:./library-with-exports',
8+
},
9+
})
10+
11+
it('Pages Router page headers with edge runtime', async () => {
12+
const response = await next.fetch('/pages/edge-page')
13+
14+
const middlewareHeaders = {
15+
react: response.headers.get('x-react-condition'),
16+
serverFavoringBrowser: response.headers.get(
17+
'x-server-favoring-browser-condition'
18+
),
19+
serverFavoringEdge: response.headers.get(
20+
'x-server-favoring-edge-condition'
21+
),
22+
}
23+
expect(middlewareHeaders).toEqual({
24+
react: 'react-server',
25+
serverFavoringBrowser: 'worker',
26+
serverFavoringEdge: 'worker',
27+
})
28+
})
29+
30+
it('Pages Router page with edge runtime', async () => {
31+
const browser = await next.browser('/pages/edge-page')
32+
33+
const json = await browser.elementByCss('output').text()
34+
expect(JSON.parse(json)).toEqual({
35+
server: {
36+
react: 'default',
37+
serverFavoringBrowser: 'worker',
38+
serverFavoringEdge: 'worker',
39+
},
40+
client: {
41+
react: 'default',
42+
serverFavoringBrowser: 'browser',
43+
serverFavoringEdge: 'browser',
44+
},
45+
})
46+
})
47+
48+
it('Pages Router page headers with nodejs runtime', async () => {
49+
const response = await next.fetch('/pages/node-page')
50+
51+
const middlewareHeaders = {
52+
react: response.headers.get('x-react-condition'),
53+
serverFavoringBrowser: response.headers.get(
54+
'x-server-favoring-browser-condition'
55+
),
56+
serverFavoringEdge: response.headers.get(
57+
'x-server-favoring-edge-condition'
58+
),
59+
}
60+
expect(middlewareHeaders).toEqual({
61+
react: 'react-server',
62+
serverFavoringBrowser: 'worker',
63+
serverFavoringEdge: 'worker',
64+
})
65+
})
66+
67+
it('Pages Router page with nodejs runtime after hydration', async () => {
68+
const browser = await next.browser('/pages/node-page')
69+
70+
const json = await browser.elementByCss('output').text()
71+
expect(JSON.parse(json)).toEqual({
72+
server: {
73+
react: 'default',
74+
serverFavoringBrowser: 'node',
75+
serverFavoringEdge: 'node',
76+
},
77+
client: {
78+
react: 'default',
79+
serverFavoringBrowser: 'browser',
80+
serverFavoringEdge: 'browser',
81+
},
82+
})
83+
})
84+
85+
it('App Router page headers with edge runtime', async () => {
86+
const response = await next.fetch('/app/edge-page')
87+
88+
const middlewareHeaders = {
89+
react: response.headers.get('x-react-condition'),
90+
serverFavoringBrowser: response.headers.get(
91+
'x-server-favoring-browser-condition'
92+
),
93+
serverFavoringEdge: response.headers.get(
94+
'x-server-favoring-edge-condition'
95+
),
96+
}
97+
expect(middlewareHeaders).toEqual({
98+
react: 'react-server',
99+
serverFavoringBrowser: 'worker',
100+
serverFavoringEdge: 'worker',
101+
})
102+
})
103+
104+
it('App Router page with edge runtime', async () => {
105+
const browser = await next.browser('/app/edge-page')
106+
107+
await browser.waitForElementByCss('input[type="submit"]').click()
108+
await browser.waitForElementByCss('output[aria-busy="false"]')
109+
110+
const json = await browser.elementByCss('output').text()
111+
expect(JSON.parse(json)).toEqual({
112+
server: {
113+
react: 'react-server',
114+
serverFavoringBrowser: 'worker',
115+
serverFavoringEdge: 'worker',
116+
},
117+
client: {
118+
react: 'default',
119+
serverFavoringBrowser: 'browser',
120+
serverFavoringEdge: 'browser',
121+
},
122+
action: {
123+
react: 'react-server',
124+
serverFavoringBrowser: 'worker',
125+
serverFavoringEdge: 'worker',
126+
},
127+
})
128+
})
129+
130+
it('App Router page headers with nodejs runtime', async () => {
131+
const response = await next.fetch('/app/node-page')
132+
133+
const middlewareHeaders = {
134+
react: response.headers.get('x-react-condition'),
135+
serverFavoringBrowser: response.headers.get(
136+
'x-server-favoring-browser-condition'
137+
),
138+
serverFavoringEdge: response.headers.get(
139+
'x-server-favoring-edge-condition'
140+
),
141+
}
142+
expect(middlewareHeaders).toEqual({
143+
react: 'react-server',
144+
serverFavoringBrowser: 'worker',
145+
serverFavoringEdge: 'worker',
146+
})
147+
})
148+
149+
it('App Router page with nodejs runtime', async () => {
150+
const browser = await next.browser('/app/node-page')
151+
152+
await browser.waitForElementByCss('input[type="submit"]').click()
153+
await browser.waitForElementByCss('output[aria-busy="false"]')
154+
155+
const json = await browser.elementByCss('output').text()
156+
expect(JSON.parse(json)).toEqual({
157+
server: {
158+
react: 'react-server',
159+
serverFavoringBrowser: 'node',
160+
serverFavoringEdge: 'node',
161+
},
162+
client: {
163+
react: 'default',
164+
serverFavoringBrowser: 'browser',
165+
serverFavoringEdge: 'browser',
166+
},
167+
action: {
168+
react: 'react-server',
169+
serverFavoringBrowser: 'node',
170+
serverFavoringEdge: 'node',
171+
},
172+
})
173+
})
174+
175+
it('App Router Route Handler with nodejs runtime', async () => {
176+
const response = await next.fetch('/node-route')
177+
178+
const middlewareHeaders = {
179+
react: response.headers.get('x-react-condition'),
180+
serverFavoringBrowser: response.headers.get(
181+
'x-server-favoring-browser-condition'
182+
),
183+
serverFavoringEdge: response.headers.get(
184+
'x-server-favoring-edge-condition'
185+
),
186+
}
187+
const data = await response.json()
188+
expect({ middlewareHeaders, data }).toEqual({
189+
middlewareHeaders: {
190+
react: 'react-server',
191+
serverFavoringBrowser: 'worker',
192+
serverFavoringEdge: 'worker',
193+
},
194+
data: {
195+
react: 'react-server',
196+
serverFavoringBrowser: 'node',
197+
serverFavoringEdge: 'node',
198+
},
199+
})
200+
})
201+
202+
it('App Router Route Handler with edge runtime', async () => {
203+
const response = await next.fetch('/edge-route')
204+
205+
const middlewareHeaders = {
206+
react: response.headers.get('x-react-condition'),
207+
serverFavoringBrowser: response.headers.get(
208+
'x-server-favoring-browser-condition'
209+
),
210+
serverFavoringEdge: response.headers.get(
211+
'x-server-favoring-edge-condition'
212+
),
213+
}
214+
const data = await response.json()
215+
expect({ middlewareHeaders, data }).toEqual({
216+
middlewareHeaders: {
217+
react: 'react-server',
218+
serverFavoringBrowser: 'worker',
219+
serverFavoringEdge: 'worker',
220+
},
221+
data: {
222+
react: 'react-server',
223+
serverFavoringBrowser: 'worker',
224+
serverFavoringEdge: 'worker',
225+
},
226+
})
227+
})
228+
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const condition = 'browser'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const condition = 'default'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const condition = 'edge-light'
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
declare module 'library-with-exports/react' {
2+
export const condition: string
3+
}
4+
5+
declare module 'library-with-exports/server-favoring-edge' {
6+
export const condition: string
7+
}
8+
9+
declare module 'library-with-exports/server-favoring-browser' {
10+
export const condition: string
11+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const condition = 'netlify'
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
throw new Error(
2+
'Imported entrypoint that should never be used. This is a bug in Next.js'
3+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const condition = 'node'

0 commit comments

Comments
 (0)