fix(webpack): Should work when absolute paths are supplied as output (#22736)

This commit is contained in:
Nicholas Cunningham 2024-04-09 09:27:10 -06:00 committed by GitHub
parent f11d7be115
commit c27a668530
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 39 additions and 33 deletions

View File

@ -264,7 +264,7 @@ module.exports = {
} }
}, 120_000); }, 120_000);
xit('should be able to generate a nest application', async () => { it('should be able to generate a nest application', async () => {
const nestapp = uniq('nestapp'); const nestapp = uniq('nestapp');
const port = 3335; const port = 3335;
runCLI(`generate @nx/nest:app ${nestapp} --linter=eslint`); runCLI(`generate @nx/nest:app ${nestapp} --linter=eslint`);
@ -278,49 +278,32 @@ module.exports = {
'Test Suites: 2 passed, 2 total' 'Test Suites: 2 passed, 2 total'
); );
await runCLIAsync(`build ${nestapp}`); const buildResult = runCLI(`build ${nestapp}`);
checkFilesExist( checkFilesExist(
`dist/apps/${nestapp}/main.js`, `dist/apps/${nestapp}/main.js`,
`dist/apps/${nestapp}/assets/file.txt`, `dist/apps/${nestapp}/assets/file.txt`
`dist/apps/${nestapp}/main.js.map`
); );
const server = exec(`node ./dist/apps/${nestapp}/main.js`, { expect(buildResult).toContain(
cwd: tmpProjPath(), `Successfully ran target build for project ${nestapp}`
}); );
expect(server).toBeTruthy();
// checking build
await new Promise((resolve) => {
server.stdout.on('data', async (data) => {
const message = data.toString();
if (message.includes(`Listening at http://localhost:${port}`)) {
const result = await getData(port);
expect(result.message).toEqual(`Welcome to ${nestapp}!`);
server.kill();
resolve(null);
}
});
});
// checking serve // checking serve
const p = await runCommandUntil( const p = await runCommandUntil(
`serve ${nestapp} --port=${port}`, `serve ${nestapp} --port=${port}`,
(output) => { (output) => {
process.stdout.write(output); process.stdout.write(output);
return output.includes(`Listening at http://localhost:${port}`); return output.includes(`listening on ws://localhost:${port}`);
} }
); );
const result = await getData(port);
expect(result.message).toEqual(`Welcome to ${nestapp}!`); const e2eRsult = await runCLIAsync(`e2e ${nestapp}-e2e`);
try {
await promisifiedTreeKill(p.pid, 'SIGKILL'); expect(e2eRsult.combinedOutput).toContain('Test Suites: 1 passed, 1 total');
expect(await killPorts(port)).toBeTruthy();
} catch (err) { await killPorts(port);
expect(err).toBeFalsy(); p.kill();
}
}, 120000); }, 120000);
// TODO(crystal, @ndcunningham): how do we handle this now? // TODO(crystal, @ndcunningham): how do we handle this now?

View File

@ -21,6 +21,7 @@ import { calculateProjectBuildableDependencies } from '../../utils/buildable-lib
import { killTree } from './lib/kill-tree'; import { killTree } from './lib/kill-tree';
import { fileExists } from 'nx/src/utils/fileutils'; import { fileExists } from 'nx/src/utils/fileutils';
import { getRelativeDirectoryToProjectRoot } from '../../utils/get-main-file-dir'; import { getRelativeDirectoryToProjectRoot } from '../../utils/get-main-file-dir';
import { interpolate } from 'nx/src/tasks-runner/utils';
interface ActiveTask { interface ActiveTask {
id: string; id: string;
@ -69,6 +70,7 @@ export async function* nodeExecutor(
const buildOptions: Record<string, any> = { const buildOptions: Record<string, any> = {
...readTargetOptions(buildTarget, context), ...readTargetOptions(buildTarget, context),
...options.buildTargetOptions, ...options.buildTargetOptions,
target: buildTarget.target,
}; };
if (options.waitUntilTargets && options.waitUntilTargets.length > 0) { if (options.waitUntilTargets && options.waitUntilTargets.length > 0) {
@ -364,7 +366,21 @@ function getFileToRun(
// If using run-commands or another custom executor, then user should set // If using run-commands or another custom executor, then user should set
// outputFileName, but we can try the default value that we use. // outputFileName, but we can try the default value that we use.
if (!buildOptions?.outputPath && !buildOptions?.outputFileName) { if (!buildOptions?.outputPath && !buildOptions?.outputFileName) {
// If we are using crystal for infering the target, we can use the output path from the target.
// Since the output path has a token for the project name, we need to interpolate it.
// {workspaceRoot}/dist/{projectRoot} -> dist/my-app
const outputPath = project.data.targets[buildOptions.target]?.outputs?.[0];
if (outputPath) {
const outputFilePath = interpolate(outputPath, {
projectName: project.name,
projectRoot: project.data.root,
workspaceRoot: '',
});
return path.join(outputFilePath, 'main.js');
}
const fallbackFile = path.join('dist', project.data.root, 'main.js'); const fallbackFile = path.join('dist', project.data.root, 'main.js');
logger.warn( logger.warn(
`Build option ${chalk.bold('outputFileName')} not set for ${chalk.bold( `Build option ${chalk.bold('outputFileName')} not set for ${chalk.bold(
project.name project.name

View File

@ -8,7 +8,7 @@ import {
workspaceRoot, workspaceRoot,
writeJsonFile, writeJsonFile,
} from '@nx/devkit'; } from '@nx/devkit';
import { dirname, isAbsolute, join, relative } from 'path'; import { dirname, isAbsolute, join, relative, resolve } from 'path';
import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs'; import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
import { WebpackExecutorOptions } from '../executors/webpack/schema'; import { WebpackExecutorOptions } from '../executors/webpack/schema';
import { WebDevServerOptions } from '../executors/dev-server/schema'; import { WebDevServerOptions } from '../executors/dev-server/schema';
@ -187,7 +187,14 @@ function normalizeOutputPath(
} }
} else { } else {
if (isAbsolute(outputPath)) { if (isAbsolute(outputPath)) {
return `{workspaceRoot}/${relative(workspaceRoot, outputPath)}`; /**
* If outputPath is absolute, we need to resolve it relative to the workspaceRoot first.
* After that, we can use the relative path to the workspaceRoot token {workspaceRoot} to generate the output path.
*/
return `{workspaceRoot}/${relative(
workspaceRoot,
resolve(workspaceRoot, outputPath)
)}`;
} else { } else {
if (outputPath.startsWith('..')) { if (outputPath.startsWith('..')) {
return join('{workspaceRoot}', join(projectRoot, outputPath)); return join('{workspaceRoot}', join(projectRoot, outputPath));