diff --git a/packages/next/migrations.json b/packages/next/migrations.json index daad88978238b..3813440a5babc 100644 --- a/packages/next/migrations.json +++ b/packages/next/migrations.json @@ -65,6 +65,12 @@ "version": "16.0.0-beta.1", "description": "Replace @nrwl/next with @nx/next", "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages" + }, + "update-16-3-0-remove-root-build-option": { + "cli": "nx", + "version": "16.3.0-beta.9", + "description": "Remove root build option from project configurations since it is not needed.", + "implementation": "./src/migrations/update-16-3-0/remove-root-build-option" } }, "packageJsonUpdates": { diff --git a/packages/next/plugins/with-nx.ts b/packages/next/plugins/with-nx.ts index 5733357e4b9da..bb015ed559d14 100644 --- a/packages/next/plugins/with-nx.ts +++ b/packages/next/plugins/with-nx.ts @@ -206,7 +206,7 @@ function withNx( nextConfig.webpack = (a, b) => createWebpackConfig( workspaceRoot, - options.root, + projectDirectory, options.fileReplacements, options.assets, dependencies, diff --git a/packages/next/src/executors/build/build.impl.ts b/packages/next/src/executors/build/build.impl.ts index 199a58cff16ce..d94d8440a2107 100644 --- a/packages/next/src/executors/build/build.impl.ts +++ b/packages/next/src/executors/build/build.impl.ts @@ -1,15 +1,14 @@ import 'dotenv/config'; import { ExecutorContext, + logger, readJsonFile, - workspaceRoot, writeJsonFile, - logger, } from '@nx/devkit'; import { createLockFile, createPackageJson, getLockFileName } from '@nx/js'; -import { join, resolve } from 'path'; +import { join } from 'path'; import { copySync, existsSync, mkdir, writeFileSync } from 'fs-extra'; -import { lt, gte } from 'semver'; +import { gte } from 'semver'; import { directoryExists } from '@nx/workspace/src/utilities/fileutils'; import { checkAndCleanWithSemver } from '@nx/devkit/src/utils/semver'; @@ -17,7 +16,7 @@ import { updatePackageJson } from './lib/update-package-json'; import { createNextConfigFile } from './lib/create-next-config-file'; import { checkPublicDirectory } from './lib/check-project'; import { NextBuildBuilderOptions } from '../../utils/types'; -import { ExecSyncOptions, execSync } from 'child_process'; +import { execSync, ExecSyncOptions } from 'child_process'; import { createCliOptions } from '../../utils/create-cli-options'; export default async function buildExecutor( @@ -27,16 +26,16 @@ export default async function buildExecutor( // Cast to any to overwrite NODE_ENV (process.env as any).NODE_ENV ||= 'production'; - const root = resolve(context.root, options.root); + const projectRoot = context.projectGraph.nodes[context.projectName].data.root; - checkPublicDirectory(root); + checkPublicDirectory(projectRoot); // Set `__NEXT_REACT_ROOT` based on installed ReactDOM version - const packageJsonPath = join(root, 'package.json'); + const packageJsonPath = join(projectRoot, 'package.json'); const packageJson = existsSync(packageJsonPath) ? readJsonFile(packageJsonPath) : undefined; - const rootPackageJson = readJsonFile(join(workspaceRoot, 'package.json')); + const rootPackageJson = readJsonFile(join(context.root, 'package.json')); const reactDomVersion = packageJson?.dependencies?.['react-dom'] ?? rootPackageJson.dependencies?.['react-dom']; @@ -54,7 +53,7 @@ export default async function buildExecutor( const execSyncOptions: ExecSyncOptions = { stdio: 'inherit', encoding: 'utf-8', - cwd: root, + cwd: projectRoot, }; try { execSync(command, execSyncOptions); @@ -89,7 +88,7 @@ export default async function buildExecutor( createNextConfigFile(options, context); - copySync(join(root, 'public'), join(options.outputPath, 'public'), { + copySync(join(projectRoot, 'public'), join(options.outputPath, 'public'), { dereference: true, }); diff --git a/packages/next/src/executors/build/lib/create-next-config-file.ts b/packages/next/src/executors/build/lib/create-next-config-file.ts index 09955a95c2254..ca2d3cfc54eec 100644 --- a/packages/next/src/executors/build/lib/create-next-config-file.ts +++ b/packages/next/src/executors/build/lib/create-next-config-file.ts @@ -24,12 +24,13 @@ export function createNextConfigFile( options: NextBuildBuilderOptions, context: ExecutorContext ) { + const projectRoot = context.projectGraph.nodes[context.projectName].data.root; const configRelativeToProjectRoot = findNextConfigPath( - options.root, + projectRoot, // If user passed a config then it is relative to the workspace root, need to normalize it to be relative to the project root. - options.nextConfig ? relative(options.root, options.nextConfig) : undefined + options.nextConfig ? relative(projectRoot, options.nextConfig) : undefined ); - const configAbsolutePath = join(options.root, configRelativeToProjectRoot); + const configAbsolutePath = join(projectRoot, configRelativeToProjectRoot); if (!existsSync(configAbsolutePath)) { throw new Error('next.config.js not found'); @@ -65,12 +66,12 @@ export function createNextConfigFile( // Find all relative imports needed by next.config.js and copy them to the dist folder. const moduleFilesToCopy = getRelativeFilesToCopy( configRelativeToProjectRoot, - options.root + projectRoot ); for (const moduleFile of moduleFilesToCopy) { ensureDirSync(dirname(join(context.root, options.outputPath, moduleFile))); copyFileSync( - join(context.root, options.root, moduleFile), + join(context.root, projectRoot, moduleFile), join(context.root, options.outputPath, moduleFile) ); } diff --git a/packages/next/src/executors/build/schema.json b/packages/next/src/executors/build/schema.json index 6e2b98b98a8ea..e4ca77a9b1e88 100644 --- a/packages/next/src/executors/build/schema.json +++ b/packages/next/src/executors/build/schema.json @@ -7,11 +7,6 @@ "description": "Build a Next.js app.", "type": "object", "properties": { - "root": { - "description": "The source root", - "type": "string", - "x-priority": "important" - }, "outputPath": { "type": "string", "description": "The output path of the generated files.", @@ -76,5 +71,5 @@ "description": "Only build 'app' routes" } }, - "required": ["root", "outputPath"] + "required": ["outputPath"] } diff --git a/packages/next/src/executors/export/export.impl.ts b/packages/next/src/executors/export/export.impl.ts index 75eeb080b9601..27c0ad8b7e9c9 100644 --- a/packages/next/src/executors/export/export.impl.ts +++ b/packages/next/src/executors/export/export.impl.ts @@ -71,14 +71,14 @@ export default async function exportExecutor( buildTarget, context ); - const root = resolve(context.root, buildOptions.root); + const projectRoot = context.projectGraph.nodes[context.projectName].data.root; // Taken from: // https://github.com/vercel/next.js/blob/ead56eaab68409e96c19f7d9139747bac1197aa9/packages/next/cli/next-export.ts#L13 const nextExportCliSpan = nextTrace.trace('next-export-cli'); await exportApp( - root, + projectRoot, { statusMessage: 'Exporting', silent: options.silent, diff --git a/packages/next/src/executors/server/custom-server.impl.ts b/packages/next/src/executors/server/custom-server.impl.ts index cf2e89fcd8009..985751af49770 100644 --- a/packages/next/src/executors/server/custom-server.impl.ts +++ b/packages/next/src/executors/server/custom-server.impl.ts @@ -30,9 +30,9 @@ export default async function* serveExecutor( parseTargetString(options.buildTarget, context.projectGraph), context ); - const root = resolve(context.root, buildOptions.root); + const projectRoot = context.projectGraph.nodes[context.projectName].data.root; - yield* runCustomServer(root, options, context); + yield* runCustomServer(projectRoot, options, context); } async function* runCustomServer( diff --git a/packages/next/src/executors/server/server.impl.ts b/packages/next/src/executors/server/server.impl.ts index fb6fe89c04070..4fd5d7d976179 100644 --- a/packages/next/src/executors/server/server.impl.ts +++ b/packages/next/src/executors/server/server.impl.ts @@ -28,12 +28,12 @@ export default async function* serveExecutor( parseTargetString(options.buildTarget, context.projectGraph), context ); - const root = resolve(context.root, buildOptions.root); + const projectRoot = context.workspace.projects[context.projectName].root; const { port, keepAliveTimeout, hostname } = options; // This is required for the default custom server to work. See the @nx/next:app generator. - process.env.NX_NEXT_DIR = root; + process.env.NX_NEXT_DIR = projectRoot; // Cast to any to overwrite NODE_ENV (process.env as any).NODE_ENV = process.env.NODE_ENV @@ -56,7 +56,7 @@ export default async function* serveExecutor( yield* createAsyncIterable<{ success: boolean; baseUrl: string }>( async ({ done, next, error }) => { const server = fork(nextBin, [mode, ...args, turbo], { - cwd: options.dev ? root : nextDir, + cwd: options.dev ? projectRoot : nextDir, stdio: 'inherit', }); diff --git a/packages/next/src/generators/application/application.spec.ts b/packages/next/src/generators/application/application.spec.ts index 5d1f8c446dc41..ad9d253cb746c 100644 --- a/packages/next/src/generators/application/application.spec.ts +++ b/packages/next/src/generators/application/application.spec.ts @@ -256,7 +256,6 @@ describe('app', () => { '@nx/next:build' ); expect(projectConfiguration.targets.build.options).toEqual({ - root: 'apps/my-app', outputPath: 'dist/apps/my-app', }); }); diff --git a/packages/next/src/generators/application/lib/add-project.ts b/packages/next/src/generators/application/lib/add-project.ts index a141e3bb8d91c..3b401463a1f7d 100644 --- a/packages/next/src/generators/application/lib/add-project.ts +++ b/packages/next/src/generators/application/lib/add-project.ts @@ -13,7 +13,6 @@ export function addProject(host: Tree, options: NormalizedSchema) { outputs: ['{options.outputPath}'], defaultConfiguration: 'production', options: { - root: options.appProjectRoot, outputPath: options.outputPath, }, configurations: { diff --git a/packages/next/src/migrations/update-16-3-0/remove-root-build-option.spec.ts b/packages/next/src/migrations/update-16-3-0/remove-root-build-option.spec.ts new file mode 100644 index 0000000000000..04cd9a5525cdd --- /dev/null +++ b/packages/next/src/migrations/update-16-3-0/remove-root-build-option.spec.ts @@ -0,0 +1,72 @@ +import update from './remove-root-build-option'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing-pre16'; +import { + addProjectConfiguration, + readProjectConfiguration, + Tree, +} from '@nx/devkit'; + +describe('remove-root-build-option', () => { + let tree: Tree; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + }); + + it('should remove the root option from the build target for @nx/next:build executor', async () => { + addProjectConfiguration(tree, 'my-app', { + root: 'my-app', + targets: { + build: { + executor: '@nx/next:build', + options: { + root: 'my-app', + }, + }, + }, + }); + + await update(tree); + + const updatedConfig = readProjectConfiguration(tree, 'my-app'); + expect(updatedConfig.targets.build.options.root).toBeUndefined(); + }); + + it('should remove the root option from the build target for @nrwl/next:build executor', async () => { + addProjectConfiguration(tree, 'my-app', { + root: 'my-app', + targets: { + build: { + executor: '@nrwl/next:build', + options: { + root: 'my-app', + }, + }, + }, + }); + + await update(tree); + + const updatedConfig = readProjectConfiguration(tree, 'my-app'); + expect(updatedConfig.targets.build.options.root).toBeUndefined(); + }); + + it('should leave other executors alone', async () => { + addProjectConfiguration(tree, 'my-app', { + root: 'my-app', + targets: { + build: { + executor: '@acme/foo:bar', + options: { + root: 'my-app', + }, + }, + }, + }); + + await update(tree); + + const updatedConfig = readProjectConfiguration(tree, 'my-app'); + expect(updatedConfig.targets.build.options.root).toEqual('my-app'); + }); +}); diff --git a/packages/next/src/migrations/update-16-3-0/remove-root-build-option.ts b/packages/next/src/migrations/update-16-3-0/remove-root-build-option.ts new file mode 100644 index 0000000000000..0fc1d8a3d61d6 --- /dev/null +++ b/packages/next/src/migrations/update-16-3-0/remove-root-build-option.ts @@ -0,0 +1,27 @@ +import { + readProjectConfiguration, + Tree, + updateProjectConfiguration, +} from '@nx/devkit'; +import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils'; + +export default async function update(tree: Tree) { + forEachExecutorOptions( + tree, + '@nx/next:build', + (options, projectName, targetName) => { + const projectConfig = readProjectConfiguration(tree, projectName); + delete projectConfig.targets[targetName].options.root; + updateProjectConfiguration(tree, projectName, projectConfig); + } + ); + forEachExecutorOptions( + tree, + '@nrwl/next:build', + (options, projectName, targetName) => { + const projectConfig = readProjectConfiguration(tree, projectName); + delete projectConfig.targets[targetName].options.root; + updateProjectConfiguration(tree, projectName, projectConfig); + } + ); +} diff --git a/packages/next/src/utils/types.ts b/packages/next/src/utils/types.ts index b9231089f7fa3..a78c85aca4a1f 100644 --- a/packages/next/src/utils/types.ts +++ b/packages/next/src/utils/types.ts @@ -28,7 +28,6 @@ export interface FileReplacement { } export interface NextBuildBuilderOptions { - root: string; outputPath: string; fileReplacements: FileReplacement[]; assets?: any[];