Skip to content

Commit

Permalink
fix(nextjs): make next build package manager agnostic
Browse files Browse the repository at this point in the history
closes: #18653
  • Loading branch information
ndcunningham committed Aug 17, 2023
1 parent b9ca7ce commit f29afa9
Showing 1 changed file with 47 additions and 23 deletions.
70 changes: 47 additions & 23 deletions packages/next/src/executors/build/build.impl.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import 'dotenv/config';
import {
detectPackageManager,
ExecutorContext,
getPackageManagerVersion,
logger,
readJsonFile,
workspaceRoot,
writeJsonFile,
} from '@nx/devkit';
import { createLockFile, createPackageJson, getLockFileName } from '@nx/js';
import { join } from 'path';
import { join, resolve as pathResolve } from 'path';
import { copySync, existsSync, mkdir, writeFileSync } from 'fs-extra';
import { gte } from 'semver';
import { directoryExists } from '@nx/workspace/src/utilities/fileutils';
Expand All @@ -19,9 +17,11 @@ 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 { execSync, ExecSyncOptions } from 'child_process';
import { ChildProcess, fork } from 'child_process';
import { createCliOptions } from '../../utils/create-cli-options';

let childProcess: ChildProcess;

export default async function buildExecutor(
options: NextBuildBuilderOptions,
context: ExecutorContext
Expand Down Expand Up @@ -49,32 +49,20 @@ export default async function buildExecutor(
process.env['__NEXT_REACT_ROOT'] ||= 'true';
}

const { experimentalAppOnly, profile, debug, outputPath } = options;

// Set output path here since it can also be set via CLI
// We can retrieve it inside plugins/with-nx
process.env.NX_NEXT_OUTPUT_PATH ??= outputPath;
process.env.NX_NEXT_OUTPUT_PATH ??= options.outputPath;

const args = createCliOptions({ experimentalAppOnly, profile, debug });
const isYarnBerry =
detectPackageManager() === 'yarn' &&
gte(getPackageManagerVersion('yarn', workspaceRoot), '2.0.0');
const buildCommand = isYarnBerry
? `yarn next build ${projectRoot}`
: 'npx next build';

const command = `${buildCommand} ${args.join(' ')}`;
const execSyncOptions: ExecSyncOptions = {
stdio: 'inherit',
encoding: 'utf-8',
cwd: projectRoot,
};
try {
execSync(command, execSyncOptions);
await runCliBuild(workspaceRoot, projectRoot, options);
} catch (error) {
logger.error(`Error occurred while trying to run the ${command}`);
logger.error(`Error occurred while trying to run the build command`);
logger.error(error);
return { success: false };
} finally {
if (childProcess) {
childProcess.kill();
}
}

if (!directoryExists(options.outputPath)) {
Expand Down Expand Up @@ -116,3 +104,39 @@ export default async function buildExecutor(
}
return { success: true };
}

function runCliBuild(
workspaceRoot: string,
projectRoot: string,
options: NextBuildBuilderOptions
) {
const { experimentalAppOnly, profile, debug, outputPath } = options;
const args = createCliOptions({ experimentalAppOnly, profile, debug });
return new Promise((resolve, reject) => {
childProcess = fork(
require.resolve('next/dist/bin/next'),
['build', ...args],
{
cwd: pathResolve(workspaceRoot, projectRoot),
stdio: 'inherit',
env: process.env,
}
);

// Ensure the child process is killed when the parent exits
process.on('exit', () => childProcess.kill());
process.on('SIGTERM', () => childProcess.kill());

childProcess.on('error', (err) => {
reject(err);
});

childProcess.on('exit', (code) => {
if (code === 0) {
resolve(code);
} else {
reject(code);
}
});
});
}

0 comments on commit f29afa9

Please sign in to comment.