From 5027fc82d7ce1210ae14812fbf9757fa6be25239 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 19 Oct 2023 16:09:52 -0700 Subject: [PATCH 1/2] remove serverActions experimental flag --- .../03-forms-and-mutations.mdx | 10 - .../04-functions/server-actions.mdx | 11 - packages/next/src/build/swc/options.ts | 8 +- packages/next/src/build/webpack-config.ts | 3 - .../build/webpack/loaders/next-swc-loader.ts | 1 - .../plugins/flight-client-entry-plugin.ts | 208 +++++++++--------- .../next/src/lib/needs-experimental-react.ts | 2 +- packages/next/src/lib/turbopack-warning.ts | 1 - packages/next/src/server/config-schema.ts | 1 - packages/next/src/server/config-shared.ts | 6 - packages/next/src/server/config.ts | 8 + .../app-dir/actions-navigation/next.config.js | 4 +- .../app-dir/actions/app-action-export.test.ts | 5 +- .../actions/app-action-invalid.test.ts | 41 ---- .../app-action-size-limit-invalid.test.ts | 4 - test/e2e/app-dir/actions/next.config.js | 1 - test/e2e/app-dir/app-static/next.config.js | 1 - test/e2e/app-dir/rsc-basic/rsc-basic.test.ts | 2 +- .../next.config.js | 4 +- test/turbopack-tests-manifest.json | 1 - 20 files changed, 113 insertions(+), 209 deletions(-) delete mode 100644 test/e2e/app-dir/actions/app-action-invalid.test.ts diff --git a/docs/02-app/01-building-your-application/02-data-fetching/03-forms-and-mutations.mdx b/docs/02-app/01-building-your-application/02-data-fetching/03-forms-and-mutations.mdx index 236b7e88200ee..70342516b8e46 100644 --- a/docs/02-app/01-building-your-application/02-data-fetching/03-forms-and-mutations.mdx +++ b/docs/02-app/01-building-your-application/02-data-fetching/03-forms-and-mutations.mdx @@ -37,16 +37,6 @@ With Server Actions, you don't need to manually create API endpoints. Instead, y Server Actions can be defined in Server Components or called from Client Components. Defining the action in a Server Component allows the form to function without JavaScript, providing progressive enhancement. -Enable Server Actions in your `next.config.js` file: - -```js filename="next.config.js" -module.exports = { - experimental: { - serverActions: true, - }, -} -``` - > **Good to know:** > > - Forms calling Server Actions from Server Components can function without JavaScript. 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 a28fd06c76400..db07eb602ac9c 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 @@ -15,16 +15,6 @@ Next.js integrates with React Actions to provide a built-in solution for [server ## Convention -You can enable Server Actions in your Next.js project by enabling the **experimental** `serverActions` flag. - -```js filename="next.config.js" -module.exports = { - experimental: { - serverActions: true, - }, -} -``` - Server Actions can be defined in two places: - Inside the component that uses it (Server Components only). @@ -157,7 +147,6 @@ However, you can configure this limit using the `serverActionsBodySizeLimit` opt ```js filename="next.config.js" module.exports = { experimental: { - serverActions: true, serverActionsBodySizeLimit: '2mb', }, } diff --git a/packages/next/src/build/swc/options.ts b/packages/next/src/build/swc/options.ts index f92bd3c99fd6f..7a538f42d863e 100644 --- a/packages/next/src/build/swc/options.ts +++ b/packages/next/src/build/swc/options.ts @@ -46,7 +46,6 @@ function getBaseSWCOptions({ isServerLayer, bundleTarget, hasServerComponents, - isServerActionsEnabled, }: { filename: string jest?: boolean @@ -56,7 +55,6 @@ function getBaseSWCOptions({ modularizeImports?: NextConfig['modularizeImports'] compilerOptions: NextConfig['compiler'] swcPlugins: ExperimentalConfig['swcPlugins'] - isServerActionsEnabled?: ExperimentalConfig['serverActions'] resolvedBaseUrl?: string jsConfig: any bundleTarget: BundleType @@ -183,8 +181,7 @@ function getBaseSWCOptions({ serverActions: hasServerComponents && !jest ? { - // TODO-APP: When Server Actions is stable, we need to remove this flag. - enabled: !!isServerActionsEnabled, + enabled: true, isServer: !!isServerLayer, } : undefined, @@ -320,7 +317,6 @@ export function getLoaderSWCOptions({ relativeFilePathFromRoot, hasServerComponents, isServerLayer, - isServerActionsEnabled, bundleTarget, }: // This is not passed yet as "paths" resolving is handled by webpack currently. // resolvedBaseUrl, @@ -346,7 +342,6 @@ export function getLoaderSWCOptions({ bundleTarget: BundleType hasServerComponents?: boolean isServerLayer: boolean - isServerActionsEnabled?: boolean }) { let baseOptions: any = getBaseSWCOptions({ filename, @@ -361,7 +356,6 @@ export function getLoaderSWCOptions({ swcCacheDir, hasServerComponents, isServerLayer, - isServerActionsEnabled, bundleTarget, }) baseOptions.fontLoaders = { diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index 3305e4764d679..51c1563154b8b 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -483,7 +483,6 @@ export default async function getBaseWebpackConfig( const hasServerComponents = hasAppDir const disableOptimizedLoading = true const enableTypedRoutes = !!config.experimental.typedRoutes && hasAppDir - const useServerActions = !!config.experimental.serverActions && hasAppDir const bundledReactChannel = needsExperimentalReact(config) ? '-experimental' : '' @@ -2077,7 +2076,6 @@ export default async function getBaseWebpackConfig( appDir, dev, isEdgeServer, - useServerActions, })), hasAppDir && !isClient && @@ -2252,7 +2250,6 @@ export default async function getBaseWebpackConfig( optimizeCss: config.experimental.optimizeCss, nextScriptWorkers: config.experimental.nextScriptWorkers, scrollRestoration: config.experimental.scrollRestoration, - serverActions: config.experimental.serverActions, typedRoutes: config.experimental.typedRoutes, basePath: config.basePath, excludeDefaultMomentLocales: config.excludeDefaultMomentLocales, diff --git a/packages/next/src/build/webpack/loaders/next-swc-loader.ts b/packages/next/src/build/webpack/loaders/next-swc-loader.ts index 6a18b06d9bd2b..a708e0e37380a 100644 --- a/packages/next/src/build/webpack/loaders/next-swc-loader.ts +++ b/packages/next/src/build/webpack/loaders/next-swc-loader.ts @@ -93,7 +93,6 @@ async function loaderTransform( swcCacheDir, relativeFilePathFromRoot, hasServerComponents, - isServerActionsEnabled: nextConfig?.experimental?.serverActions, isServerLayer, bundleTarget, }) diff --git a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts index c62935a243a84..814db070c7465 100644 --- a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts +++ b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts @@ -38,7 +38,6 @@ interface Options { dev: boolean appDir: string isEdgeServer: boolean - useServerActions: boolean serverActionsBodySizeLimit?: SizeLimit } @@ -154,7 +153,6 @@ export class FlightClientEntryPlugin { dev: boolean appDir: string isEdgeServer: boolean - useServerActions: boolean serverActionsBodySizeLimit?: SizeLimit assetPrefix: string @@ -162,7 +160,6 @@ export class FlightClientEntryPlugin { this.dev = options.dev this.appDir = options.appDir this.isEdgeServer = options.isEdgeServer - this.useServerActions = options.useServerActions this.serverActionsBodySizeLimit = options.serverActionsBodySizeLimit this.assetPrefix = !this.dev && !this.isEdgeServer ? '../' : '' } @@ -387,78 +384,73 @@ export class FlightClientEntryPlugin { ) } - if (this.useServerActions) { - compilation.hooks.finishModules.tapPromise(PLUGIN_NAME, () => { - const addedClientActionEntryList: Promise[] = [] - const actionMapsPerClientEntry: Record< - string, - Map - > = {} - - // We need to create extra action entries that are created from the - // client layer. - // Start from each entry's created SSR dependency from our previous step. - for (const [name, ssrEntryDepdendencies] of Object.entries( - createdSSRDependenciesForEntry - )) { - // Collect from all entries, e.g. layout.js, page.js, loading.js, ... - // add agregate them. - const actionEntryImports = this.collectClientActionsFromDependencies({ - compilation, - dependencies: ssrEntryDepdendencies, - }) + compilation.hooks.finishModules.tapPromise(PLUGIN_NAME, () => { + const addedClientActionEntryList: Promise[] = [] + const actionMapsPerClientEntry: Record> = {} - if (actionEntryImports.size > 0) { - if (!actionMapsPerClientEntry[name]) { - actionMapsPerClientEntry[name] = new Map() - } - actionMapsPerClientEntry[name] = new Map([ - ...actionMapsPerClientEntry[name], - ...actionEntryImports, - ]) + // We need to create extra action entries that are created from the + // client layer. + // Start from each entry's created SSR dependency from our previous step. + for (const [name, ssrEntryDepdendencies] of Object.entries( + createdSSRDependenciesForEntry + )) { + // Collect from all entries, e.g. layout.js, page.js, loading.js, ... + // add agregate them. + const actionEntryImports = this.collectClientActionsFromDependencies({ + compilation, + dependencies: ssrEntryDepdendencies, + }) + + if (actionEntryImports.size > 0) { + if (!actionMapsPerClientEntry[name]) { + actionMapsPerClientEntry[name] = new Map() } + actionMapsPerClientEntry[name] = new Map([ + ...actionMapsPerClientEntry[name], + ...actionEntryImports, + ]) } + } - for (const [name, actionEntryImports] of Object.entries( - actionMapsPerClientEntry - )) { - // If an action method is already created in the server layer, we don't - // need to create it again in the action layer. - // This is to avoid duplicate action instances and make sure the module - // state is shared. - let remainingClientImportedActions = false - const remainingActionEntryImports = new Map() - for (const [dep, actionNames] of actionEntryImports) { - const remainingActionNames = [] - for (const actionName of actionNames) { - const id = name + '@' + dep + '@' + actionName - if (!createdActions.has(id)) { - remainingActionNames.push(actionName) - } - } - if (remainingActionNames.length > 0) { - remainingActionEntryImports.set(dep, remainingActionNames) - remainingClientImportedActions = true + for (const [name, actionEntryImports] of Object.entries( + actionMapsPerClientEntry + )) { + // If an action method is already created in the server layer, we don't + // need to create it again in the action layer. + // This is to avoid duplicate action instances and make sure the module + // state is shared. + let remainingClientImportedActions = false + const remainingActionEntryImports = new Map() + for (const [dep, actionNames] of actionEntryImports) { + const remainingActionNames = [] + for (const actionName of actionNames) { + const id = name + '@' + dep + '@' + actionName + if (!createdActions.has(id)) { + remainingActionNames.push(actionName) } } - - if (remainingClientImportedActions) { - addedClientActionEntryList.push( - this.injectActionEntry({ - compiler, - compilation, - actions: remainingActionEntryImports, - entryName: name, - bundlePath: name, - fromClient: true, - }) - ) + if (remainingActionNames.length > 0) { + remainingActionEntryImports.set(dep, remainingActionNames) + remainingClientImportedActions = true } } - return Promise.all(addedClientActionEntryList) - }) - } + if (remainingClientImportedActions) { + addedClientActionEntryList.push( + this.injectActionEntry({ + compiler, + compilation, + actions: remainingActionEntryImports, + entryName: name, + bundlePath: name, + fromClient: true, + }) + ) + } + } + + return Promise.all(addedClientActionEntryList) + }) // Invalidate in development to trigger recompilation const invalidator = getInvalidator(compiler.outputPath) @@ -871,54 +863,52 @@ export class FlightClientEntryPlugin { const serverActions: ActionManifest['node'] = {} const edgeServerActions: ActionManifest['edge'] = {} - if (this.useServerActions) { - traverseModules(compilation, (mod, _chunk, chunkGroup, modId) => { - // Go through all action entries and record the module ID for each entry. - if ( - chunkGroup.name && - mod.request && - /next-flight-action-entry-loader/.test(mod.request) - ) { - const fromClient = /&__client_imported__=true/.test(mod.request) - - const mapping = this.isEdgeServer - ? pluginState.actionModEdgeServerId - : pluginState.actionModServerId - - if (!mapping[chunkGroup.name]) { - mapping[chunkGroup.name] = {} - } - mapping[chunkGroup.name][fromClient ? 'client' : 'server'] = modId + traverseModules(compilation, (mod, _chunk, chunkGroup, modId) => { + // Go through all action entries and record the module ID for each entry. + if ( + chunkGroup.name && + mod.request && + /next-flight-action-entry-loader/.test(mod.request) + ) { + const fromClient = /&__client_imported__=true/.test(mod.request) + + const mapping = this.isEdgeServer + ? pluginState.actionModEdgeServerId + : pluginState.actionModServerId + + if (!mapping[chunkGroup.name]) { + mapping[chunkGroup.name] = {} } - }) + mapping[chunkGroup.name][fromClient ? 'client' : 'server'] = modId + } + }) - for (let id in pluginState.serverActions) { - const action = pluginState.serverActions[id] - for (let name in action.workers) { - const modId = - pluginState.actionModServerId[name][ - action.layer[name] === WEBPACK_LAYERS.actionBrowser - ? 'client' - : 'server' - ] - action.workers[name] = modId! - } - serverActions[id] = action + for (let id in pluginState.serverActions) { + const action = pluginState.serverActions[id] + for (let name in action.workers) { + const modId = + pluginState.actionModServerId[name][ + action.layer[name] === WEBPACK_LAYERS.actionBrowser + ? 'client' + : 'server' + ] + action.workers[name] = modId! } + serverActions[id] = action + } - for (let id in pluginState.edgeServerActions) { - const action = pluginState.edgeServerActions[id] - for (let name in action.workers) { - const modId = - pluginState.actionModEdgeServerId[name][ - action.layer[name] === WEBPACK_LAYERS.actionBrowser - ? 'client' - : 'server' - ] - action.workers[name] = modId! - } - edgeServerActions[id] = action + for (let id in pluginState.edgeServerActions) { + const action = pluginState.edgeServerActions[id] + for (let name in action.workers) { + const modId = + pluginState.actionModEdgeServerId[name][ + action.layer[name] === WEBPACK_LAYERS.actionBrowser + ? 'client' + : 'server' + ] + action.workers[name] = modId! } + edgeServerActions[id] = action } const json = JSON.stringify( diff --git a/packages/next/src/lib/needs-experimental-react.ts b/packages/next/src/lib/needs-experimental-react.ts index 36ffa9a89c5ae..5cb8af76692f5 100644 --- a/packages/next/src/lib/needs-experimental-react.ts +++ b/packages/next/src/lib/needs-experimental-react.ts @@ -1,5 +1,5 @@ import type { NextConfig } from '../server/config-shared' export function needsExperimentalReact(config: NextConfig) { - return Boolean(config.experimental?.serverActions || config.experimental?.ppr) + return Boolean(config.experimental?.ppr) } diff --git a/packages/next/src/lib/turbopack-warning.ts b/packages/next/src/lib/turbopack-warning.ts index e55b259dee029..5b0e52625b6bc 100644 --- a/packages/next/src/lib/turbopack-warning.ts +++ b/packages/next/src/lib/turbopack-warning.ts @@ -62,7 +62,6 @@ const supportedTurbopackNextConfigOptions = [ 'experimental.useDeploymentId', 'experimental.useDeploymentIdServerActions', 'experimental.deploymentId', - 'experimental.serverActions', // Experimental options that don't affect compilation 'serverRuntimeConfig', diff --git a/packages/next/src/server/config-schema.ts b/packages/next/src/server/config-schema.ts index 6d8cbf38249b7..d8a8d380896c6 100644 --- a/packages/next/src/server/config-schema.ts +++ b/packages/next/src/server/config-schema.ts @@ -251,7 +251,6 @@ export const configSchema: zod.ZodType = z.lazy(() => disableOptimizedLoading: z.boolean().optional(), disablePostcssPresetEnv: z.boolean().optional(), esmExternals: z.union([z.boolean(), z.literal('loose')]).optional(), - serverActions: z.boolean().optional(), serverActionsBodySizeLimit: zSizeLimit.optional(), // The original type was Record extensionAlias: z.record(z.string(), z.any()).optional(), diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index 8064d3b8d5570..e6454ad58bcc1 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -296,12 +296,6 @@ export interface ExperimentalConfig { */ instrumentationHook?: boolean - /** - * 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 - */ - serverActions?: boolean - /** * Using this feature will enable the `react@experimental` for the `app` directory. */ diff --git a/packages/next/src/server/config.ts b/packages/next/src/server/config.ts index a357a685486ec..92867f35f1290 100644 --- a/packages/next/src/server/config.ts +++ b/packages/next/src/server/config.ts @@ -420,6 +420,14 @@ function assignDefaults( 'You are using `experimental.runtime` which was removed. Check https://nextjs.org/docs/api-routes/edge-api-routes on how to use edge runtime.', silent ) + // TODO: Remove this warning in Next.js 15 + warnOptionHasBeenDeprecated( + result, + 'experimental.serverActions', + 'Server Actions are available by default now, `experimental.serverActions` option can be safely removed.', + silent + ) + warnOptionHasBeenMovedOutOfExperimental( result, 'relay', diff --git a/test/e2e/app-dir/actions-navigation/next.config.js b/test/e2e/app-dir/actions-navigation/next.config.js index 6b81f43169761..e289c86facd62 100644 --- a/test/e2e/app-dir/actions-navigation/next.config.js +++ b/test/e2e/app-dir/actions-navigation/next.config.js @@ -1,5 +1,3 @@ module.exports = { - experimental: { - serverActions: true, - }, + experimental: {}, } diff --git a/test/e2e/app-dir/actions/app-action-export.test.ts b/test/e2e/app-dir/actions/app-action-export.test.ts index 734a3dcf9bd81..446982c7b8a0d 100644 --- a/test/e2e/app-dir/actions/app-action-export.test.ts +++ b/test/e2e/app-dir/actions/app-action-export.test.ts @@ -24,10 +24,7 @@ createNextDescribe( 'next.config.js', ` module.exports = { - output: 'export', - experimental: { - serverActions: true, - }, + output: 'export' } ` ) diff --git a/test/e2e/app-dir/actions/app-action-invalid.test.ts b/test/e2e/app-dir/actions/app-action-invalid.test.ts deleted file mode 100644 index a9fa84d85f646..0000000000000 --- a/test/e2e/app-dir/actions/app-action-invalid.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { createNextDescribe } from 'e2e-utils' - -createNextDescribe( - 'app-dir action invalid config', - { - files: __dirname, - skipDeployment: true, - dependencies: { - react: 'latest', - 'react-dom': 'latest', - 'server-only': 'latest', - }, - }, - ({ next, isNextStart }) => { - if (!isNextStart) { - it('skip test for dev mode', () => {}) - return - } - - beforeAll(async () => { - await next.stop() - await next.patchFile( - 'next.config.js', - ` - module.exports = { - experimental: {}, - } - ` - ) - try { - await next.build() - } catch {} - }) - - it('should error if serverActions is not enabled', async () => { - expect(next.cliOutput).toContain( - 'To use Server Actions, please enable the feature flag in your Next.js config.' - ) - }) - } -) 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 3e5e6b82ea050..f1121af392ce6 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 @@ -27,7 +27,6 @@ createNextDescribe( ` module.exports = { experimental: { - serverActions: true, serverActionsBodySizeLimit: -3000, }, } @@ -46,7 +45,6 @@ createNextDescribe( ` module.exports = { experimental: { - serverActions: true, serverActionsBodySizeLimit: 'testmb', }, } @@ -65,7 +63,6 @@ createNextDescribe( ` module.exports = { experimental: { - serverActions: true, serverActionsBodySizeLimit: '-3000mb', }, } @@ -85,7 +82,6 @@ createNextDescribe( ` module.exports = { experimental: { - serverActions: true, serverActionsBodySizeLimit: '1.5mb', }, } diff --git a/test/e2e/app-dir/actions/next.config.js b/test/e2e/app-dir/actions/next.config.js index bec00d8d3b471..74b7f23803592 100644 --- a/test/e2e/app-dir/actions/next.config.js +++ b/test/e2e/app-dir/actions/next.config.js @@ -5,6 +5,5 @@ module.exports = { logging: { level: 'verbose', }, - serverActions: true, }, } diff --git a/test/e2e/app-dir/app-static/next.config.js b/test/e2e/app-dir/app-static/next.config.js index e473392c23ce5..1091d8c819406 100644 --- a/test/e2e/app-dir/app-static/next.config.js +++ b/test/e2e/app-dir/app-static/next.config.js @@ -4,7 +4,6 @@ module.exports = { logging: { level: 'verbose', }, - serverActions: true, incrementalCacheHandlerPath: process.env.CUSTOM_CACHE_HANDLER, }, diff --git a/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts b/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts index d4c75be2f425e..6367c38156e90 100644 --- a/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts +++ b/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts @@ -591,7 +591,7 @@ createNextDescribe( } describe('react@experimental', () => { - it.each([{ flag: 'ppr' }, { flag: 'serverActions' }])( + it.each([{ flag: 'ppr' }])( 'should opt into the react@experimental when enabling $flag', async ({ flag }) => { await next.stop() diff --git a/test/e2e/app-dir/server-actions-relative-redirect/next.config.js b/test/e2e/app-dir/server-actions-relative-redirect/next.config.js index d20ba617cfdfc..a20fa28cb6c32 100644 --- a/test/e2e/app-dir/server-actions-relative-redirect/next.config.js +++ b/test/e2e/app-dir/server-actions-relative-redirect/next.config.js @@ -2,9 +2,7 @@ * @type {import('next').NextConfig} */ const nextConfig = { - experimental: { - serverActions: true, - }, + experimental: {}, } module.exports = nextConfig diff --git a/test/turbopack-tests-manifest.json b/test/turbopack-tests-manifest.json index 9acc60dc3e211..75c0392a98247 100644 --- a/test/turbopack-tests-manifest.json +++ b/test/turbopack-tests-manifest.json @@ -3742,7 +3742,6 @@ ], "failed": [ "app dir - rsc basics react@experimental should opt into the react@experimental when enabling ppr", - "app dir - rsc basics react@experimental should opt into the react@experimental when enabling serverActions", "app dir - rsc basics should create client reference successfully for all file conventions", "app dir - rsc basics should support next/link in server components", "app dir - rsc basics should support webpack loader rules" From 436376729b7b72ac416a52772f6c8c1d2852c346 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 19 Oct 2023 16:18:51 -0700 Subject: [PATCH 2/2] fix build error --- packages/next/src/export/index.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/next/src/export/index.ts b/packages/next/src/export/index.ts index 32a71d7a6c2cc..0ae80718225ac 100644 --- a/packages/next/src/export/index.ts +++ b/packages/next/src/export/index.ts @@ -247,15 +247,6 @@ export async function exportAppImpl( ) } - // Running 'next export' or output is set to 'export' - if (options.isInvokedFromCli || isExportOutput) { - if (nextConfig.experimental.serverActions) { - throw new ExportError( - `Server Actions are not supported with static export.` - ) - } - } - const telemetry = options.buildExport ? null : new Telemetry({ distDir }) if (telemetry) {