diff --git a/packages/next/server/config.ts b/packages/next/server/config.ts index 427f03f3524da..58800ffb28621 100644 --- a/packages/next/server/config.ts +++ b/packages/next/server/config.ts @@ -25,14 +25,23 @@ export { DomainLocale, NextConfig, normalizeConfig } from './config-shared' const targets = ['server', 'serverless', 'experimental-serverless-trace'] -const experimentalWarning = execOnce(() => { - Log.warn(chalk.bold('You have enabled experimental feature(s).')) - Log.warn( - `Experimental features are not covered by semver, and may cause unexpected or broken application behavior. ` + - `Use them at your own risk.` - ) - console.warn() -}) +const experimentalWarning = execOnce( + (configFileName: string, features: string[]) => { + const s = features.length > 1 ? 's' : '' + Log.warn( + chalk.bold( + `You have enabled experimental feature${s} (${features.join( + ', ' + )}) in ${configFileName}.` + ) + ) + Log.warn( + `Experimental features are not covered by semver, and may cause unexpected or broken application behavior. ` + + `Use at your own risk.` + ) + console.warn() + } +) function assignDefaults(userConfig: { [key: string]: any }) { const configFileName = userConfig.configFileName @@ -74,7 +83,7 @@ function assignDefaults(userConfig: { [key: string]: any }) { typeof value === 'object' && Object.keys(value).length > 0 ) { - experimentalWarning() + experimentalWarning(configFileName, Object.keys(value)) } if (key === 'distDir') { diff --git a/test/integration/config-experimental-warning/test/index.test.js b/test/integration/config-experimental-warning/test/index.test.js index 70c5b0b1bd038..dc20cd6820471 100644 --- a/test/integration/config-experimental-warning/test/index.test.js +++ b/test/integration/config-experimental-warning/test/index.test.js @@ -5,9 +5,15 @@ import { nextBuild, File } from 'next-test-utils' const appDir = join(__dirname, '..') const configFile = new File(join(appDir, '/next.config.js')) +const configFileMjs = new File(join(appDir, '/next.config.mjs')) -describe('Promise in next config', () => { - afterAll(() => configFile.delete()) +describe('Config Experimental Warning', () => { + afterEach(() => { + configFile.write('') + configFile.delete() + configFileMjs.write('') + configFileMjs.delete() + }) it('should not show warning with default config from function', async () => { configFile.write(` @@ -20,7 +26,7 @@ describe('Promise in next config', () => { `) const { stderr } = await nextBuild(appDir, [], { stderr: true }) - expect(stderr).not.toMatch(/experimental feature/) + expect(stderr).not.toMatch('You have enabled experimental feature') }) it('should not show warning with config from object', async () => { @@ -30,7 +36,7 @@ describe('Promise in next config', () => { } `) const { stderr } = await nextBuild(appDir, [], { stderr: true }) - expect(stderr).not.toMatch(/experimental feature/) + expect(stderr).not.toMatch('You have enabled experimental feature') }) it('should show warning with config from object with experimental', async () => { @@ -43,7 +49,9 @@ describe('Promise in next config', () => { } `) const { stderr } = await nextBuild(appDir, [], { stderr: true }) - expect(stderr).toMatch(/experimental feature/) + expect(stderr).toMatch( + 'You have enabled experimental feature (something) in next.config.js.' + ) }) it('should show warning with config from function with experimental', async () => { @@ -56,6 +64,38 @@ describe('Promise in next config', () => { }) `) const { stderr } = await nextBuild(appDir, [], { stderr: true }) - expect(stderr).toMatch(/experimental feature/) + expect(stderr).toMatch( + 'You have enabled experimental feature (something) in next.config.js.' + ) + }) + + it('should show warning with config from object with experimental and multiple keys', async () => { + configFile.write(` + module.exports = { + experimental: { + something: true, + another: 1, + } + } + `) + const { stderr } = await nextBuild(appDir, [], { stderr: true }) + expect(stderr).toMatch( + 'You have enabled experimental features (something, another) in next.config.js.' + ) + }) + + it('should show warning with next.config.mjs from object with experimental', async () => { + configFileMjs.write(` + const config = { + experimental: { + something: true, + } + } + export default config + `) + const { stderr } = await nextBuild(appDir, [], { stderr: true }) + expect(stderr).toMatch( + 'You have enabled experimental feature (something) in next.config.mjs.' + ) }) })