108 lines
3.4 KiB
TypeScript
108 lines
3.4 KiB
TypeScript
import 'dotenv/config';
|
|
import {
|
|
ExecutorContext,
|
|
readJsonFile,
|
|
workspaceLayout,
|
|
workspaceRoot,
|
|
writeJsonFile,
|
|
} from '@nrwl/devkit';
|
|
import { createLockFile, createPackageJson } from '@nrwl/js';
|
|
import build from 'next/dist/build';
|
|
import { join, resolve } from 'path';
|
|
import { copySync, existsSync, mkdir, writeFileSync } from 'fs-extra';
|
|
import { gte } from 'semver';
|
|
import { directoryExists } from '@nrwl/workspace/src/utilities/fileutils';
|
|
import {
|
|
calculateProjectDependencies,
|
|
DependentBuildableProjectNode,
|
|
} from '@nrwl/js/src/utils/buildable-libs-utils';
|
|
import { checkAndCleanWithSemver } from '@nrwl/devkit/src/utils/semver';
|
|
|
|
import { prepareConfig } from '../../utils/config';
|
|
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 { PHASE_PRODUCTION_BUILD } from '../../utils/constants';
|
|
import { getLockFileName } from 'nx/src/lock-file/lock-file';
|
|
|
|
export default async function buildExecutor(
|
|
options: NextBuildBuilderOptions,
|
|
context: ExecutorContext
|
|
) {
|
|
// Cast to any to overwrite NODE_ENV
|
|
(process.env as any).NODE_ENV ||= 'production';
|
|
|
|
let dependencies: DependentBuildableProjectNode[] = [];
|
|
const root = resolve(context.root, options.root);
|
|
const libsDir = join(context.root, workspaceLayout().libsDir);
|
|
|
|
checkPublicDirectory(root);
|
|
|
|
if (!options.buildLibsFromSource && context.targetName) {
|
|
const result = calculateProjectDependencies(
|
|
context.projectGraph,
|
|
context.root,
|
|
context.projectName,
|
|
context.targetName,
|
|
context.configurationName
|
|
);
|
|
dependencies = result.dependencies;
|
|
}
|
|
|
|
// Set `__NEXT_REACT_ROOT` based on installed ReactDOM version
|
|
const packageJsonPath = join(root, 'package.json');
|
|
const packageJson = existsSync(packageJsonPath)
|
|
? readJsonFile(packageJsonPath)
|
|
: undefined;
|
|
const rootPackageJson = readJsonFile(join(workspaceRoot, 'package.json'));
|
|
const reactDomVersion =
|
|
packageJson?.dependencies?.['react-dom'] ??
|
|
rootPackageJson.dependencies?.['react-dom'];
|
|
const hasReact18 =
|
|
reactDomVersion &&
|
|
gte(checkAndCleanWithSemver('react-dom', reactDomVersion), '18.0.0');
|
|
if (hasReact18) {
|
|
(process.env as any).__NEXT_REACT_ROOT ||= 'true';
|
|
}
|
|
|
|
const config = await prepareConfig(
|
|
PHASE_PRODUCTION_BUILD,
|
|
options,
|
|
context,
|
|
dependencies,
|
|
libsDir
|
|
);
|
|
|
|
await build(root, config as any);
|
|
|
|
if (!directoryExists(options.outputPath)) {
|
|
mkdir(options.outputPath);
|
|
}
|
|
|
|
const builtPackageJson = createPackageJson(
|
|
context.projectName,
|
|
context.projectGraph,
|
|
{
|
|
target: context.targetName,
|
|
root: context.root,
|
|
isProduction: !options.includeDevDependenciesInPackageJson, // By default we remove devDependencies since this is a production build.
|
|
}
|
|
);
|
|
updatePackageJson(builtPackageJson, context);
|
|
writeJsonFile(`${options.outputPath}/package.json`, builtPackageJson);
|
|
|
|
if (options.generateLockfile) {
|
|
const lockFile = createLockFile(builtPackageJson);
|
|
writeFileSync(`${options.outputPath}/${getLockFileName()}`, lockFile, {
|
|
encoding: 'utf-8',
|
|
});
|
|
}
|
|
|
|
createNextConfigFile(options, context);
|
|
|
|
copySync(join(root, 'public'), join(options.outputPath, 'public'));
|
|
|
|
return { success: true };
|
|
}
|