From c75e7ef683716996783fe28976658570d99c2b92 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Thu, 27 Jun 2024 13:58:16 -0400 Subject: [PATCH] fix(nextjs): fixes for convert-to-inferred (#26735) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …nferred ## Current Behavior ## Expected Behavior ## Related Issue(s) Fixes # --------- Co-authored-by: Nicholas Cunningham --- .../convert-to-inferred.spec.ts | 35 +++++++-- .../lib/build-post-target-transformer.ts | 31 ++++++-- .../lib/update-next-config.spec.ts | 76 +++++++++++++++++++ .../lib/update-next-config.ts | 16 ++++ 4 files changed, 147 insertions(+), 11 deletions(-) diff --git a/packages/next/src/generators/convert-to-inferred/convert-to-inferred.spec.ts b/packages/next/src/generators/convert-to-inferred/convert-to-inferred.spec.ts index 58123956b9..0cd4ccd879 100644 --- a/packages/next/src/generators/convert-to-inferred/convert-to-inferred.spec.ts +++ b/packages/next/src/generators/convert-to-inferred/convert-to-inferred.spec.ts @@ -381,8 +381,10 @@ describe('convert-to-inferred', () => { {}, { build: { + debug: true, + profile: true, experimentalAppOnly: true, - experimentalBuildMode: true, + experimentalBuildMode: 'generate', }, } ); @@ -391,10 +393,33 @@ describe('convert-to-inferred', () => { await convertToInferred(tree, { project: project.name }); const projectConfig = readProjectConfiguration(tree, project.name); - expect(projectConfig.targets.build).toMatchObject({ - options: { - args: ['--experimental-app-only', '--experimental-build-mode'], - }, + expect(projectConfig.targets.build.options).toEqual({ + args: [ + '--debug', + '--profile', + '--experimental-app-only', + '--experimental-build-mode generate', + ], }); }); + + it('should not migrate options to CLI args if they are booleans and are false', async () => { + const project = createProject( + tree, + {}, + { + build: { + debug: false, + profile: false, + experimentalAppOnly: false, + }, + } + ); + writeNextConfig(tree, project.root); + + await convertToInferred(tree, { project: project.name }); + + const projectConfig = readProjectConfiguration(tree, project.name); + expect(projectConfig.targets.build.options).toBeUndefined(); + }); }); diff --git a/packages/next/src/generators/convert-to-inferred/lib/build-post-target-transformer.ts b/packages/next/src/generators/convert-to-inferred/lib/build-post-target-transformer.ts index 02fb153bfa..c209c4c3c1 100644 --- a/packages/next/src/generators/convert-to-inferred/lib/build-post-target-transformer.ts +++ b/packages/next/src/generators/convert-to-inferred/lib/build-post-target-transformer.ts @@ -157,17 +157,36 @@ function handlePropertiesFromTargetOptions( delete options.watch; } - if ('experimentalAppOnly' in options && options.experimentalAppOnly) { - options['args'] ??= []; - options['args'].push('--experimental-app-only'); + if ('debug' in options) { + if (options.debug) { + options['args'] ??= []; + options['args'].push('--debug'); + } + delete options.debug; + } + + if ('profile' in options) { + if (options.profile) { + options['args'] ??= []; + options['args'].push('--profile'); + } + delete options.profile; + } + + if ('experimentalAppOnly' in options) { + if (options.experimentalAppOnly) { + options['args'] ??= []; + options['args'].push('--experimental-app-only'); + } delete options.experimentalAppOnly; } - if ('experimentalBuildMode' in options && options.experimentalBuildMode) { + if ('experimentalBuildMode' in options) { options['args'] ??= []; - options['args'].push(`--experimental-build-mode`); + options['args'].push( + `--experimental-build-mode ${options.experimentalBuildMode}` + ); delete options.experimentalBuildMode; } - configValues[configuration] = configMap; } diff --git a/packages/next/src/generators/convert-to-inferred/lib/update-next-config.spec.ts b/packages/next/src/generators/convert-to-inferred/lib/update-next-config.spec.ts index c22b7ef21b..e44c0adfb1 100644 --- a/packages/next/src/generators/convert-to-inferred/lib/update-next-config.spec.ts +++ b/packages/next/src/generators/convert-to-inferred/lib/update-next-config.spec.ts @@ -145,4 +145,80 @@ describe('UpdateNextConfig', () => { project: 'no-compose-plugins', }); }); + + describe('Reserved variables', () => { + it('should warn the user if the next config file contains reserved variables', () => { + const initConfig = ` + const options = {}; + const configValues = {}; + const configuration = {}; + `; + const projectDetails = { + projectName: 'reserved-variables', + root: 'reserved-variables', + }; + tree.write(`${projectDetails.root}/next.config.js`, initConfig); + + updateNextConfig(tree, '', projectDetails, mockLog); + + expect(mockLog.addLog).toHaveBeenCalledWith({ + executorName: '@nx/next:build', + log: "The project (reserved-variables) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.", + project: 'reserved-variables', + }); + }); + + it('should warn the user if the next config file contains a reserved variable (option)', () => { + const initConfig = `const options = {};`; + const projectDetails = { + projectName: 'reserved-options', + root: 'reserved-options', + }; + tree.write(`${projectDetails.root}/next.config.js`, initConfig); + + updateNextConfig(tree, '', projectDetails, mockLog); + + expect(mockLog.addLog).toHaveBeenCalledWith({ + executorName: '@nx/next:build', + log: "The project (reserved-options) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.", + project: 'reserved-options', + }); + }); + + it('should warn the user if the next config file contains a reserved variable (configValues)', () => { + const initConfig = `const configValues = {};`; + const projectDetails = { + projectName: 'reserved-config-values', + root: 'reserved-config-values', + }; + + tree.write(`${projectDetails.root}/next.config.js`, initConfig); + + updateNextConfig(tree, '', projectDetails, mockLog); + + expect(mockLog.addLog).toHaveBeenCalledWith({ + executorName: '@nx/next:build', + log: "The project (reserved-config-values) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.", + project: 'reserved-config-values', + }); + }); + + it('should warn the user if the next config file contains a reserved variable (configuration)', () => { + const initConfig = `const configuration = {};`; + const projectDetails = { + projectName: 'reserved-configuration-values', + root: 'reserved-configuration-values', + }; + + tree.write(`${projectDetails.root}/next.config.js`, initConfig); + + updateNextConfig(tree, '', projectDetails, mockLog); + + expect(mockLog.addLog).toHaveBeenCalledWith({ + executorName: '@nx/next:build', + log: "The project (reserved-configuration-values) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.", + project: 'reserved-configuration-values', + }); + }); + }); }); diff --git a/packages/next/src/generators/convert-to-inferred/lib/update-next-config.ts b/packages/next/src/generators/convert-to-inferred/lib/update-next-config.ts index a4dda729c4..53c3903e08 100644 --- a/packages/next/src/generators/convert-to-inferred/lib/update-next-config.ts +++ b/packages/next/src/generators/convert-to-inferred/lib/update-next-config.ts @@ -23,6 +23,22 @@ export function updateNextConfig( const nextConfigContents = tree.read(nextConfigPath, 'utf-8'); let ast = tsquery.ast(nextConfigContents); + const reservedVarQuery = ` + VariableStatement > VariableDeclarationList > VariableDeclaration:has(Identifier[name=configValues]), + VariableStatement > VariableDeclarationList > VariableDeclaration:has(Identifier[name=configuration]), + VariableStatement > VariableDeclarationList > VariableDeclaration:has(Identifier[name=options]) + `; + + const matches = tsquery(ast, reservedVarQuery); + if (matches.length > 0) { + migrationLogs.addLog({ + project: project.projectName, + executorName: '@nx/next:build', + log: `The project (${project.projectName}) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.`, + }); + return; + } + // Query to check for composePlugins in module.exports const composePluginsQuery = `ExpressionStatement > BinaryExpression > CallExpression > CallExpression:has(Identifier[name=composePlugins])`; const composePluginNode = tsquery(ast, composePluginsQuery)[0];