fix(nextjs): set correct distDir when running production server through Nx (#15861)

This commit is contained in:
Jack Hsu 2023-03-23 12:57:10 -04:00 committed by GitHub
parent 8af80de3e7
commit b3200fb7c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 7 deletions

View File

@ -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', () => {

View File

@ -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;
@ -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()
@ -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[] = [];