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

Disable server action transform in pages router #71028

Merged
merged 5 commits into from
Oct 9, 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
5 changes: 3 additions & 2 deletions packages/next/src/build/swc/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
StyledComponentsConfig,
} from '../../server/config-shared'
import type { ResolvedBaseUrl } from '../load-jsconfig'
import { isWebpackServerOnlyLayer } from '../utils'
import { isWebpackServerOnlyLayer, isWebpackAppPagesLayer } from '../utils'

const nextDistPath =
/(next[\\/]dist[\\/]shared[\\/]lib)|(next[\\/]dist[\\/]client)|(next[\\/]dist[\\/]pages)/
Expand Down Expand Up @@ -82,6 +82,7 @@ function getBaseSWCOptions({
bundleLayer?: WebpackLayerName
}) {
const isReactServerLayer = isWebpackServerOnlyLayer(bundleLayer)
const isAppRouterPagesLayer = isWebpackAppPagesLayer(bundleLayer)
const parserConfig = getParserOptions({ filename, jsConfig })
const paths = jsConfig?.compilerOptions?.paths
const enableDecorators = Boolean(
Expand Down Expand Up @@ -202,7 +203,7 @@ function getBaseSWCOptions({
}
: undefined,
serverActions:
serverComponents && !jest
isAppRouterPagesLayer && !jest
? {
// always enable server actions
// TODO: remove this option
Expand Down
6 changes: 6 additions & 0 deletions packages/next/src/build/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,12 @@ export function isWebpackBundledLayer(
return Boolean(layer && WEBPACK_LAYERS.GROUP.bundled.includes(layer as any))
}

export function isWebpackAppPagesLayer(
layer: WebpackLayerName | null | undefined
): boolean {
return Boolean(layer && WEBPACK_LAYERS.GROUP.appPages.includes(layer as any))
}

export function collectMeta({
status,
headers,
Expand Down
7 changes: 7 additions & 0 deletions packages/next/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ const WEBPACK_LAYERS = {
WEBPACK_LAYERS_NAMES.shared,
WEBPACK_LAYERS_NAMES.instrument,
],
appPages: [
// app router pages and layouts
WEBPACK_LAYERS_NAMES.reactServerComponents,
WEBPACK_LAYERS_NAMES.serverSideRendering,
WEBPACK_LAYERS_NAMES.appPagesBrowser,
WEBPACK_LAYERS_NAMES.actionBrowser,
],
},
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { nextTestSetup } from 'e2e-utils'
import { assertNoRedbox, retry } from 'next-test-utils'

describe('app-dir - action-in-pages-router', () => {
const { next, isNextStart } = nextTestSetup({
files: __dirname,
})

it('should not error on fake server action in pages router', async () => {
const browser = await next.browser('/foo')
const button = await browser.elementByCss('button')
await button.click()

await retry(async () => {
const browserLogText = (await browser.log())
.map((item) => item.message)
.join('')
// This is a fake server action, a simple function so it can still work
expect(browserLogText).toContain('action:foo')
await assertNoRedbox(browser)
})
})

if (isNextStart) {
// Disabling for turbopack because the chunk path are different
if (!process.env.TURBOPACK) {
it('should not contain server action in page bundle', async () => {
const pageBundle = await next.readFile('.next/server/pages/foo.js')
// Should not contain the RSC client import source for the server action
expect(pageBundle).not.toContain('react-server-dom-webpack/client')
})
}

it('should not contain server action in manifest', async () => {
if (process.env.TURBOPACK) {
const manifest = JSON.parse(
await next.readFile('.next/server/server-reference-manifest.json')
)
expect(Object.keys(manifest.node).length).toBe(0)
} else {
expect(
await next.hasFile('.next/server/server-reference-manifest.json')
).toBe(false)
}
})
}
})
5 changes: 5 additions & 0 deletions test/e2e/app-dir/action-in-pages-router/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use server'

export async function actionFoo() {
return 'action:foo'
}
18 changes: 18 additions & 0 deletions test/e2e/app-dir/action-in-pages-router/pages/foo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { actionFoo } from '../actions'

export default function Page() {
return (
<button
onClick={() => {
actionFoo().then((v) => console.log(v))
}}
>
hello
</button>
)
}

// Keep route as dynamic
export async function getServerSideProps() {
return { props: {} }
}
Loading