diff --git a/docs/02-app/02-api-reference/04-functions/server-actions.mdx b/docs/02-app/02-api-reference/04-functions/server-actions.mdx index db07eb602ac9c..a7a9aed1fdf04 100644 --- a/docs/02-app/02-api-reference/04-functions/server-actions.mdx +++ b/docs/02-app/02-api-reference/04-functions/server-actions.mdx @@ -142,12 +142,14 @@ In both cases, the form is interactive before hydration occurs. Although Server By default, the maximum size of the request body sent to a Server Action is 1MB, to prevent the consumption of excessive server resources in parsing large amounts of data. -However, you can configure this limit using the `serverActionsBodySizeLimit` option. It can take the number of bytes or any string format supported by bytes, for example `1000`, `'500kb'` or `'3mb'`. +However, you can configure this limit using the `serverActions.bodySizeLimit` option. It can take the number of bytes or any string format supported by bytes, for example `1000`, `'500kb'` or `'3mb'`. ```js filename="next.config.js" module.exports = { experimental: { - serverActionsBodySizeLimit: '2mb', + serverActions: { + bodySizeLimit: '2mb', + }, }, } ``` diff --git a/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs b/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs index f35468d1ed151..1fd09ccbc7f33 100644 --- a/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs +++ b/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs @@ -155,7 +155,14 @@ async fn wrap_edge_page( // TODO(timneutkens): remove this let is_server_component = true; - let server_actions_body_size_limit = &next_config.experimental.server_actions_body_size_limit; + // let server_actions_body_size_limit = + // &next_config.experimental.server_actions.body_size_limit; + let server_actions_body_size_limit = next_config + .experimental + .server_actions + .as_ref() + .and_then(|sa| sa.body_size_limit.as_ref()); + let sri_enabled = !dev && next_config .experimental @@ -177,7 +184,7 @@ async fn wrap_edge_page( "nextConfig" => serde_json::to_string(next_config)?, "isServerComponent" => serde_json::Value::Bool(is_server_component).to_string(), "dev" => serde_json::Value::Bool(dev).to_string(), - "serverActionsBodySizeLimit" => serde_json::to_string(server_actions_body_size_limit)?, + "serverActionsBodySizeLimit" => serde_json::to_string(&server_actions_body_size_limit)? }, indexmap! { "incrementalCacheHandler" => None, diff --git a/packages/next-swc/crates/next-core/src/next_config.rs b/packages/next-swc/crates/next-core/src/next_config.rs index 887baca13e79b..eecbba2a34b9b 100644 --- a/packages/next-swc/crates/next-core/src/next_config.rs +++ b/packages/next-swc/crates/next-core/src/next_config.rs @@ -442,11 +442,7 @@ pub struct ExperimentalConfig { pub optimize_css: Option, pub next_script_workers: Option, pub web_vitals_attribution: Option>, - /// Enables server actions. Using this feature will enable the - /// `react@experimental` for the `app` directory. @see https://nextjs.org/docs/app/api-reference/functions/server-actions - server_actions: Option, - /// Allows adjusting body parser size limit for server actions. - pub server_actions_body_size_limit: Option, + pub server_actions: Option, pub sri: Option, // --- @@ -515,6 +511,13 @@ pub struct SubResourceIntegrity { pub algorithm: Option, } +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[serde(rename_all = "camelCase")] +pub struct ServerActions { + /// Allows adjusting body parser size limit for server actions. + pub body_size_limit: Option, +} + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] #[serde(untagged)] pub enum SizeLimit { diff --git a/packages/next/src/build/entries.ts b/packages/next/src/build/entries.ts index 2c73c7c9c6ab5..e0bb905fc7b31 100644 --- a/packages/next/src/build/entries.ts +++ b/packages/next/src/build/entries.ts @@ -418,7 +418,7 @@ export function getEdgeServerEntry(opts: { JSON.stringify(opts.middlewareConfig || {}) ).toString('base64'), serverActionsBodySizeLimit: - opts.config.experimental.serverActionsBodySizeLimit, + opts.config.experimental.serverActions?.bodySizeLimit, } return { diff --git a/packages/next/src/export/index.ts b/packages/next/src/export/index.ts index c7a6a56a99861..70935631f6b55 100644 --- a/packages/next/src/export/index.ts +++ b/packages/next/src/export/index.ts @@ -489,7 +489,7 @@ export async function exportAppImpl( largePageDataBytes: nextConfig.experimental.largePageDataBytes, serverComponents: options.hasAppDir, serverActionsBodySizeLimit: - nextConfig.experimental.serverActionsBodySizeLimit, + nextConfig.experimental.serverActions?.bodySizeLimit, nextFontManifest: require(join( distDir, 'server', diff --git a/packages/next/src/lib/turbopack-warning.ts b/packages/next/src/lib/turbopack-warning.ts index 6f5e707768260..f11b8e7537a98 100644 --- a/packages/next/src/lib/turbopack-warning.ts +++ b/packages/next/src/lib/turbopack-warning.ts @@ -78,7 +78,7 @@ const supportedTurbopackNextConfigOptions = [ 'experimental.logging.fullUrl', 'experimental.scrollRestoration', 'experimental.forceSwcTransforms', - 'experimental.serverActionsBodySizeLimit', + 'experimental.serverActions.bodySizeLimit', 'experimental.memoryBasedWorkersCount', 'experimental.clientRouterFilterRedirects', 'experimental.webpackBuildWorker', diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 27f507d08f01e..fc997ca4e78c9 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -2091,7 +2091,7 @@ export default abstract class Server { isRevalidate: isSSG, originalPathname: components.ComponentMod.originalPathname, serverActionsBodySizeLimit: - this.nextConfig.experimental.serverActionsBodySizeLimit, + this.nextConfig.experimental.serverActions?.bodySizeLimit, } : {}), isDataReq, diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index f7bcbb128ff37..32ada2cb88a8e 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -306,10 +306,12 @@ export interface ExperimentalConfig { */ taint?: boolean - /** - * Allows adjusting body parser size limit for server actions. - */ - serverActionsBodySizeLimit?: SizeLimit + serverActions?: { + /** + * Allows adjusting body parser size limit for server actions. + */ + bodySizeLimit?: SizeLimit + } /** * enables the minification of server code. diff --git a/packages/next/src/server/config.ts b/packages/next/src/server/config.ts index 0c5eea71eb4f2..7d5b1d344a8c4 100644 --- a/packages/next/src/server/config.ts +++ b/packages/next/src/server/config.ts @@ -483,9 +483,11 @@ function assignDefaults( result.output = 'standalone' } - if (typeof result.experimental?.serverActionsBodySizeLimit !== 'undefined') { + if ( + typeof result.experimental?.serverActions?.bodySizeLimit !== 'undefined' + ) { const value = parseInt( - result.experimental.serverActionsBodySizeLimit.toString() + result.experimental.serverActions?.bodySizeLimit.toString() ) if (isNaN(value) || value < 1) { throw new Error( diff --git a/test/e2e/app-dir/actions/app-action-size-limit-invalid.test.ts b/test/e2e/app-dir/actions/app-action-size-limit-invalid.test.ts index f1121af392ce6..ddf1668d127d2 100644 --- a/test/e2e/app-dir/actions/app-action-size-limit-invalid.test.ts +++ b/test/e2e/app-dir/actions/app-action-size-limit-invalid.test.ts @@ -21,13 +21,13 @@ createNextDescribe( return } - it('should error if serverActionsBodySizeLimit config is a negative number', async function () { + it('should error if serverActions.bodySizeLimit config is a negative number', async function () { await next.patchFile( 'next.config.js', ` module.exports = { experimental: { - serverActionsBodySizeLimit: -3000, + serverActions: { bodySizeLimit: -3000 } }, } ` @@ -39,13 +39,13 @@ createNextDescribe( expect(next.cliOutput).toContain(CONFIG_ERROR) }) - it('should error if serverActionsBodySizeLimit config is invalid', async function () { + it('should error if serverActions.bodySizeLimit config is invalid', async function () { await next.patchFile( 'next.config.js', ` module.exports = { experimental: { - serverActionsBodySizeLimit: 'testmb', + serverActions: { bodySizeLimit: 'testmb' } }, } ` @@ -57,13 +57,13 @@ createNextDescribe( expect(next.cliOutput).toContain(CONFIG_ERROR) }) - it('should error if serverActionsBodySizeLimit config is a negative size', async function () { + it('should error if serverActions.bodySizeLimit config is a negative size', async function () { await next.patchFile( 'next.config.js', ` module.exports = { experimental: { - serverActionsBodySizeLimit: '-3000mb', + serverActions: { bodySizeLimit: '-3000mb' } }, } ` @@ -76,13 +76,13 @@ createNextDescribe( }) if (!isNextDeploy) { - it('should respect the size set in serverActionsBodySizeLimit', async function () { + it('should respect the size set in serverActions.bodySizeLimit', async function () { await next.patchFile( 'next.config.js', ` module.exports = { experimental: { - serverActionsBodySizeLimit: '1.5mb', + serverActions: { bodySizeLimit: '1.5mb' } }, } `