Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Current behavior of import conditions #66829

Merged
merged 1 commit into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions test/e2e/import-conditions/app/app/ClientPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use client'
import * as React from 'react'
import * as react from 'library-with-exports/react'
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'

export default function ClientPage({
action,
server,
}: {
action: () => Promise<Record<string, string>>
server: unknown
}) {
const [actionValue, formAction, isPending] = React.useActionState(
action,
undefined
)
const [client, setClient] = React.useState<unknown | null>(null)
React.useEffect(() => {
setClient({
react: react.condition,
serverFavoringBrowser: serverFavoringBrowser.condition,
serverFavoringEdge: serverFavoringEdge.condition,
})
}, [])

return (
<form action={formAction}>
<input type="submit" />
<output aria-busy={client === null || isPending}>
{client === null ? (
<pre>{JSON.stringify({ server }, null, 2)}</pre>
) : (
<pre>
{JSON.stringify({ server, client, action: actionValue }, null, 2)}
</pre>
)}
</output>
</form>
)
}
28 changes: 28 additions & 0 deletions test/e2e/import-conditions/app/app/edge-page/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as react from 'library-with-exports/react'
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'
import ClientPage from '../ClientPage'

export const runtime = 'edge'

async function action() {
'use server'
return {
react: react.condition,
serverFavoringBrowser: serverFavoringBrowser.condition,
serverFavoringEdge: serverFavoringEdge.condition,
}
}

export default function Page() {
return (
<ClientPage
action={action}
server={{
react: react.condition,
serverFavoringBrowser: serverFavoringBrowser.condition,
serverFavoringEdge: serverFavoringEdge.condition,
}}
/>
)
}
28 changes: 28 additions & 0 deletions test/e2e/import-conditions/app/app/node-page/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as react from 'library-with-exports/react'
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'
import ClientPage from '../ClientPage'

export const runtime = 'nodejs'

async function action() {
'use server'
return {
react: react.condition,
serverFavoringBrowser: serverFavoringBrowser.condition,
serverFavoringEdge: serverFavoringEdge.condition,
}
}

export default function Page() {
return (
<ClientPage
action={action}
server={{
react: react.condition,
serverFavoringBrowser: serverFavoringBrowser.condition,
serverFavoringEdge: serverFavoringEdge.condition,
}}
/>
)
}
13 changes: 13 additions & 0 deletions test/e2e/import-conditions/app/edge-route/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as react from 'library-with-exports/react'
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'

export const runtime = 'edge'

export function GET() {
return Response.json({
react: react.condition,
serverFavoringBrowser: serverFavoringBrowser.condition,
serverFavoringEdge: serverFavoringEdge.condition,
})
}
7 changes: 7 additions & 0 deletions test/e2e/import-conditions/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function Root({ children }: { children: React.ReactNode }) {
return (
<html>
<body>{children}</body>
</html>
)
}
13 changes: 13 additions & 0 deletions test/e2e/import-conditions/app/node-route/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as react from 'library-with-exports/react'
import * as serverFavoringBrowser from 'library-with-exports/server-favoring-browser'
import * as serverFavoringEdge from 'library-with-exports/server-favoring-edge'

export const runtime = 'nodejs'

export function GET() {
return Response.json({
react: react.condition,
serverFavoringBrowser: serverFavoringBrowser.condition,
serverFavoringEdge: serverFavoringEdge.condition,
})
}
228 changes: 228 additions & 0 deletions test/e2e/import-conditions/import-conditions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import { nextTestSetup } from 'e2e-utils'

describe('react version', () => {
const { next } = nextTestSetup({
files: __dirname,
dependencies: {
'library-with-exports': 'link:./library-with-exports',
},
})

it('Pages Router page headers with edge runtime', async () => {
const response = await next.fetch('/pages/edge-page')

const middlewareHeaders = {
react: response.headers.get('x-react-condition'),
serverFavoringBrowser: response.headers.get(
'x-server-favoring-browser-condition'
),
serverFavoringEdge: response.headers.get(
'x-server-favoring-edge-condition'
),
}
expect(middlewareHeaders).toEqual({
react: 'react-server',
serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
})
})

it('Pages Router page with edge runtime', async () => {
const browser = await next.browser('/pages/edge-page')

const json = await browser.elementByCss('output').text()
expect(JSON.parse(json)).toEqual({
server: {
react: 'default',
serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
},
client: {
react: 'default',
serverFavoringBrowser: 'browser',
serverFavoringEdge: 'browser',
},
})
})

it('Pages Router page headers with nodejs runtime', async () => {
const response = await next.fetch('/pages/node-page')

const middlewareHeaders = {
react: response.headers.get('x-react-condition'),
serverFavoringBrowser: response.headers.get(
'x-server-favoring-browser-condition'
),
serverFavoringEdge: response.headers.get(
'x-server-favoring-edge-condition'
),
}
expect(middlewareHeaders).toEqual({
react: 'react-server',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting that Pages router middleware already uses react-server

serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
})
})

it('Pages Router page with nodejs runtime after hydration', async () => {
const browser = await next.browser('/pages/node-page')

const json = await browser.elementByCss('output').text()
expect(JSON.parse(json)).toEqual({
server: {
react: 'default',
serverFavoringBrowser: 'node',
serverFavoringEdge: 'node',
},
client: {
react: 'default',
serverFavoringBrowser: 'browser',
serverFavoringEdge: 'browser',
},
})
})

it('App Router page headers with edge runtime', async () => {
const response = await next.fetch('/app/edge-page')

const middlewareHeaders = {
react: response.headers.get('x-react-condition'),
serverFavoringBrowser: response.headers.get(
'x-server-favoring-browser-condition'
),
serverFavoringEdge: response.headers.get(
'x-server-favoring-edge-condition'
),
}
expect(middlewareHeaders).toEqual({
react: 'react-server',
serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
Comment on lines +99 to +100
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All appearances of worker will be fixed in the next PR stackframe.

})
})

it('App Router page with edge runtime', async () => {
const browser = await next.browser('/app/edge-page')

await browser.waitForElementByCss('input[type="submit"]').click()
await browser.waitForElementByCss('output[aria-busy="false"]')

const json = await browser.elementByCss('output').text()
expect(JSON.parse(json)).toEqual({
server: {
react: 'react-server',
serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
},
client: {
react: 'default',
serverFavoringBrowser: 'browser',
serverFavoringEdge: 'browser',
},
action: {
react: 'react-server',
serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
},
})
})

it('App Router page headers with nodejs runtime', async () => {
const response = await next.fetch('/app/node-page')

const middlewareHeaders = {
react: response.headers.get('x-react-condition'),
serverFavoringBrowser: response.headers.get(
'x-server-favoring-browser-condition'
),
serverFavoringEdge: response.headers.get(
'x-server-favoring-edge-condition'
),
}
expect(middlewareHeaders).toEqual({
react: 'react-server',
serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
})
})

it('App Router page with nodejs runtime', async () => {
const browser = await next.browser('/app/node-page')

await browser.waitForElementByCss('input[type="submit"]').click()
await browser.waitForElementByCss('output[aria-busy="false"]')

const json = await browser.elementByCss('output').text()
expect(JSON.parse(json)).toEqual({
server: {
react: 'react-server',
serverFavoringBrowser: 'node',
serverFavoringEdge: 'node',
},
client: {
react: 'default',
serverFavoringBrowser: 'browser',
serverFavoringEdge: 'browser',
},
action: {
react: 'react-server',
serverFavoringBrowser: 'node',
serverFavoringEdge: 'node',
},
})
})

it('App Router Route Handler with nodejs runtime', async () => {
const response = await next.fetch('/node-route')

const middlewareHeaders = {
react: response.headers.get('x-react-condition'),
serverFavoringBrowser: response.headers.get(
'x-server-favoring-browser-condition'
),
serverFavoringEdge: response.headers.get(
'x-server-favoring-edge-condition'
),
}
const data = await response.json()
expect({ middlewareHeaders, data }).toEqual({
middlewareHeaders: {
react: 'react-server',
serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
},
data: {
react: 'react-server',
serverFavoringBrowser: 'node',
serverFavoringEdge: 'node',
},
})
})

it('App Router Route Handler with edge runtime', async () => {
const response = await next.fetch('/edge-route')

const middlewareHeaders = {
react: response.headers.get('x-react-condition'),
serverFavoringBrowser: response.headers.get(
'x-server-favoring-browser-condition'
),
serverFavoringEdge: response.headers.get(
'x-server-favoring-edge-condition'
),
}
const data = await response.json()
expect({ middlewareHeaders, data }).toEqual({
middlewareHeaders: {
react: 'react-server',
serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
},
data: {
react: 'react-server',
serverFavoringBrowser: 'worker',
serverFavoringEdge: 'worker',
},
})
})
})
1 change: 1 addition & 0 deletions test/e2e/import-conditions/library-with-exports/browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const condition = 'browser'
1 change: 1 addition & 0 deletions test/e2e/import-conditions/library-with-exports/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const condition = 'default'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const condition = 'edge-light'
11 changes: 11 additions & 0 deletions test/e2e/import-conditions/library-with-exports/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
declare module 'library-with-exports/react' {
export const condition: string
}

declare module 'library-with-exports/server-favoring-edge' {
export const condition: string
}

declare module 'library-with-exports/server-favoring-browser' {
export const condition: string
}
1 change: 1 addition & 0 deletions test/e2e/import-conditions/library-with-exports/netlify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const condition = 'netlify'
3 changes: 3 additions & 0 deletions test/e2e/import-conditions/library-with-exports/never.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
throw new Error(
'Imported entrypoint that should never be used. This is a bug in Next.js'
)
1 change: 1 addition & 0 deletions test/e2e/import-conditions/library-with-exports/node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const condition = 'node'
Loading
Loading