Skip to content

Commit

Permalink
fix(nextjs): move webpack config to withNx from build.impl
Browse files Browse the repository at this point in the history
  • Loading branch information
ndcunningham committed Mar 15, 2023
1 parent 8e838b5 commit 2feae02
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 170 deletions.
2 changes: 1 addition & 1 deletion nx-dev/nx-dev/next.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// nx-ignore-next-line
const withNx = require('@nrwl/next/plugins/with-nx');
const { withNx } = require('@nrwl/next/plugins/with-nx');
const { copySync } = require('fs-extra');
const path = require('path');
const redirectRules = require('./redirect-rules.config');
Expand Down
94 changes: 94 additions & 0 deletions packages/next/plugins/with-nx.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
import {
createProjectGraphAsync,
joinPathFragments,
offsetFromRoot,
parseTargetString,
workspaceRoot,
} from '@nrwl/devkit';
import {
calculateProjectDependencies,
DependentBuildableProjectNode,
} from '@nrwl/js/src/utils/buildable-libs-utils';
import type { NextConfig } from 'next';

import path = require('path');
import { createWebpackConfig } from '../src/utils/config';
export interface WithNxOptions extends NextConfig {
nx?: {
svgr?: boolean;
Expand Down Expand Up @@ -35,6 +48,87 @@ function getWithNxContext(): WithNxContext {
}

export function withNx(
_nextConfig = {} as WithNxOptions,
context: WithNxContext = getWithNxContext()
): () => Promise<NextConfig> {
return async () => {
let dependencies: DependentBuildableProjectNode[] = [];

const graph = await createProjectGraphAsync();
const project = process.env.NX_TASK_TARGET_PROJECT;
let projectNode = graph.nodes[project];

const targetName = process.env.NX_TASK_TARGET_TARGET;
const configurationName = process.env.NX_TASK_TARGET_CONFIGURATION;

let options = projectNode.data.targets[targetName].options;
if (configurationName) {
Object.assign(
options,
projectNode.data.targets[targetName].configurations[configurationName]
);
}

// If we are running serve or export pull the options from the dependent target first (ex. build)
if (
['@nrwl/next:server', '@nrwl/next:export'].includes(
projectNode.data.targets[targetName].executor
)
) {
const target = parseTargetString(options.buildTarget, graph);
projectNode = graph.nodes[target.project];
options = projectNode.data.targets[target.target].options;

if (target.configuration) {
Object.assign(
options,
projectNode.data.targets[target.target].configurations[
target.configuration
]
);
}
}
const projectDirectory = projectNode.data.root;

if (!options.buildLibsFromSource && targetName) {
const result = calculateProjectDependencies(
graph,
workspaceRoot,
project,
targetName,
configurationName
);
dependencies = result.dependencies;
}

// Get next config
const nextConfig = getNextConfig(_nextConfig, context);

const outputDir = `${offsetFromRoot(projectDirectory)}${
options.outputPath
}`;
nextConfig.distDir =
nextConfig.distDir && nextConfig.distDir !== '.next'
? joinPathFragments(outputDir, nextConfig.distDir)
: joinPathFragments(outputDir, '.next');

const userWebpackConfig = nextConfig.webpack;

nextConfig.webpack = (a, b) =>
createWebpackConfig(
workspaceRoot,
options.root,
options.fileReplacements,
options.assets,
dependencies,
path.join(workspaceRoot, context.libsDir)
)(userWebpackConfig ? userWebpackConfig(a, b) : a, b);

return nextConfig;
};
}

export function getNextConfig(
nextConfig = {} as WithNxOptions,
context: WithNxContext = getWithNxContext()
): NextConfig {
Expand Down
31 changes: 2 additions & 29 deletions packages/next/src/executors/build/build.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'dotenv/config';
import {
ExecutorContext,
readJsonFile,
workspaceLayout,
workspaceRoot,
writeJsonFile,
} from '@nrwl/devkit';
Expand All @@ -12,18 +11,13 @@ 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(
Expand All @@ -33,23 +27,10 @@ export default async function buildExecutor(
// 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)
Expand All @@ -66,15 +47,7 @@ export default async function buildExecutor(
(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);
await build(root);

if (!directoryExists(options.outputPath)) {
mkdir(options.outputPath);
Expand Down
40 changes: 23 additions & 17 deletions packages/next/src/executors/export/export.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
ExecutorContext,
parseTargetString,
readTargetOptions,
runExecutor,
workspaceLayout,
} from '@nrwl/devkit';
import exportApp from 'next/dist/export';
Expand All @@ -13,13 +12,18 @@ import {
DependentBuildableProjectNode,
} from '@nrwl/js/src/utils/buildable-libs-utils';

import { prepareConfig } from '../../utils/config';
import {
NextBuildBuilderOptions,
NextExportBuilderOptions,
} from '../../utils/types';
import { PHASE_EXPORT } from '../../utils/constants';
import nextTrace = require('next/dist/trace');
import { platform } from 'os';
import { execFileSync } from 'child_process';
import * as chalk from 'chalk';

// platform specific command name
const pmCmd = platform() === 'win32' ? `npx.cmd` : 'npx';

export default async function exportExecutor(
options: NextExportBuilderOptions,
Expand All @@ -38,27 +42,25 @@ export default async function exportExecutor(
}

const libsDir = join(context.root, workspaceLayout().libsDir);
const buildTarget = parseTargetString(options.buildTarget);
const build = await runExecutor(buildTarget, {}, context);
const buildTarget = parseTargetString(
options.buildTarget,
context.projectGraph
);

for await (const result of build) {
if (!result.success) {
return result;
}
try {
const args = getBuildTargetCommand(options);
execFileSync(pmCmd, args, {
stdio: [0, 1, 2],
});
} catch {
throw new Error(`Build target failed: ${chalk.bold(options.buildTarget)}`);
}

const buildOptions = readTargetOptions<NextBuildBuilderOptions>(
buildTarget,
context
);
const root = resolve(context.root, buildOptions.root);
const config = await prepareConfig(
PHASE_EXPORT,
buildOptions,
context,
dependencies,
libsDir
);

// Taken from:
// https://github.com/vercel/next.js/blob/ead56eaab68409e96c19f7d9139747bac1197aa9/packages/next/cli/next-export.ts#L13
Expand All @@ -72,9 +74,13 @@ export default async function exportExecutor(
threads: options.threads,
outdir: `${buildOptions.outputPath}/exported`,
} as any,
nextExportCliSpan,
config
nextExportCliSpan
);

return { success: true };
}

function getBuildTargetCommand(options: NextExportBuilderOptions) {
const cmd = ['nx', 'run', options.buildTarget];
return cmd;
}
39 changes: 2 additions & 37 deletions packages/next/src/executors/server/server.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ import {
parseTargetString,
readTargetOptions,
runExecutor,
workspaceLayout,
} from '@nrwl/devkit';
import * as chalk from 'chalk';
import { existsSync } from 'fs';
import { join, resolve } from 'path';
import { calculateProjectDependencies } from '@nrwl/js/src/utils/buildable-libs-utils';

import { prepareConfig } from '../../utils/config';
import {
NextBuildBuilderOptions,
NextServeBuilderOptions,
Expand All @@ -22,10 +19,6 @@ import {
} from '../../utils/types';
import { customServer } from './lib/custom-server';
import { defaultServer } from './lib/default-server';
import {
PHASE_DEVELOPMENT_SERVER,
PHASE_PRODUCTION_SERVER,
} from '../../utils/constants';

const infoPrefix = `[ ${chalk.dim(chalk.cyan('info'))} ] `;

Expand All @@ -48,42 +41,16 @@ export default async function* serveExecutor(
context
);
const root = resolve(context.root, buildOptions.root);
const config = await prepareConfig(
options.dev ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_SERVER,
buildOptions,
context,
getDependencies(options, context),
join(context.root, workspaceLayout().libsDir)
);

if (options.customServerTarget) {
yield* runCustomServer(root, config, options, buildOptions, context);
} else {
yield* runNextDevServer(root, config, options, buildOptions, context);
}
}

function getDependencies(
options: NextServeBuilderOptions,
context: ExecutorContext
) {
if (options.buildLibsFromSource) {
return [];
yield* runCustomServer(root, options, buildOptions, context);
} else {
const result = calculateProjectDependencies(
context.projectGraph,
context.root,
context.projectName,
'build', // should be generalized
context.configurationName
);
return result.dependencies;
yield* runNextDevServer(root, options, buildOptions, context);
}
}

async function* runNextDevServer(
root: string,
config: ReturnType<typeof prepareConfig>,
options: NextServeBuilderOptions,
buildOptions: NextBuildBuilderOptions,
context: ExecutorContext
Expand All @@ -94,7 +61,6 @@ async function* runNextDevServer(
dir: root,
staticMarkup: options.staticMarkup,
quiet: options.quiet,
conf: config,
port: options.port,
customServer: !!options.customServerTarget,
hostname: options.hostname || 'localhost',
Expand Down Expand Up @@ -144,7 +110,6 @@ async function* runNextDevServer(

async function* runCustomServer(
root: string,
config: ReturnType<typeof prepareConfig>,
options: NextServeBuilderOptions,
buildOptions: NextBuildBuilderOptions,
context: ExecutorContext
Expand Down
Loading

0 comments on commit 2feae02

Please sign in to comment.