Skip to content

Commit

Permalink
fix(nextjs): set correct distDir when running production server throu…
Browse files Browse the repository at this point in the history
…gh Nx (#15861)
  • Loading branch information
jaysoo committed Mar 23, 2023
1 parent 8af80de commit b3200fb
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 7 deletions.
27 changes: 21 additions & 6 deletions e2e/next/src/next.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,21 +168,36 @@ describe('Next.js Applications', () => {
`dist/apps/${appName}/public/shared/ui/hello.txt`
);

// Check that `nx serve <app> --prod` works with previous production build (e.g. `nx build <app>`).
const prodServePort = 4000;
const prodServeProcess = await runCommandUntil(
`run ${appName}:serve --prod --port=${prodServePort}`,
(output) => {
return output.includes(`localhost:${prodServePort}`);
}
);

// Check that the output is self-contained (i.e. can run with its own package.json + node_modules)
const distPath = joinPathFragments(tmpProjPath(), 'dist/apps', appName);
const port = 3000;
const selfContainedPort = 3000;
const pmc = getPackageManagerCommand();
runCommand(`${pmc.install}`, {
cwd: distPath,
});
runCLI(
`generate @nrwl/workspace:run-commands serve-prod --project ${appName} --cwd=dist/apps/${appName} --command="npx next start --port=${port}"`
`generate @nrwl/workspace:run-commands serve-prod --project ${appName} --cwd=dist/apps/${appName} --command="npx next start --port=${selfContainedPort}"`
);
const selfContainedProcess = await runCommandUntil(
`run ${appName}:serve-prod`,
(output) => {
return output.includes(`localhost:${selfContainedPort}`);
}
);
await runCommandUntil(`run ${appName}:serve-prod`, (output) => {
return output.includes(`localhost:${port}`);
});

await killPort(port);
prodServeProcess.kill();
selfContainedProcess.kill();
await killPort(prodServePort);
await killPort(selfContainedPort);
}, 300_000);

it('should build and install pruned lock file', () => {
Expand Down
31 changes: 30 additions & 1 deletion packages/next/plugins/with-nx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { PHASE_PRODUCTION_SERVER } from 'next/constants';
import * as path from 'path';
import { createWebpackConfig } from '../src/utils/config';
import { NextBuildBuilderOptions } from '../src/utils/types';

export interface WithNxOptions extends NextConfig {
nx?: {
svgr?: boolean;
Expand Down Expand Up @@ -115,6 +116,31 @@ function getNxContext(
}
}

/**
* Try to read output dir from project, and default to '.next' if executing outside of Nx (e.g. dist is added to a docker image).
*/
async function determineDistDirForProdServer(
nextConfig: NextConfig
): Promise<string> {
const project = process.env.NX_TASK_TARGET_PROJECT;
const target = process.env.NX_TASK_TARGET_TARGET;
const configuration = process.env.NX_TASK_TARGET_CONFIGURATION;

if (project && target) {
const originalTarget = { project, target, configuration };
const graph = await createProjectGraphAsync();

const { options, node: projectNode } = getNxContext(graph, originalTarget);
const outputDir = `${offsetFromRoot(projectNode.data.root)}${
options.outputPath
}`;
return nextConfig.distDir && nextConfig.distDir !== '.next'
? joinPathFragments(outputDir, nextConfig.distDir)
: joinPathFragments(outputDir, '.next');
} else {
return '.next';
}
}
export function withNx(
_nextConfig = {} as WithNxOptions,
context: WithNxContext = getWithNxContext()
Expand All @@ -123,7 +149,10 @@ export function withNx(
if (phase === PHASE_PRODUCTION_SERVER) {
// If we are running an already built production server, just return the configuration.
const { nx, ...validNextConfig } = _nextConfig;
return { distDir: '.next', ...validNextConfig };
return {
...validNextConfig,
distDir: await determineDistDirForProdServer(validNextConfig),
};
} else {
// Otherwise, add in webpack and eslint configuration for build or test.
let dependencies: DependentBuildableProjectNode[] = [];
Expand Down

0 comments on commit b3200fb

Please sign in to comment.