fix(angular): generate @nx/angular in devDependencies and move to dependencies when using runtime helpers (#27405)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

New workspaces are generated with `@nx/angular` as a production
dependency even though the generated code does not use any runtime
helper from it.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

New workspaces should be generated with `@nx/angular` as a development
dependency. When generating a new MF host or dynamic MF application
(host or remote), the `@nx/angular` package should be moved to the
production dependencies because the generated code uses some runtime
helpers from it.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #27333
This commit is contained in:
Leosvel Pérez Espinosa 2024-08-16 15:23:19 +02:00 committed by GitHub
parent 44068b58c0
commit 1ae3c2d8f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 75 additions and 12 deletions

View File

@ -5,6 +5,7 @@ export * from './change-build-target';
export * from './fix-bootstrap';
export * from './generate-config';
export * from './get-remotes-with-ports';
export * from './move-angular-plugin-to-dependencies';
export * from './normalize-options';
export * from './update-tsconfig';
export * from './setup-host-if-dynamic';

View File

@ -0,0 +1,15 @@
import { readJson, writeJson, type Tree } from '@nx/devkit';
export function moveAngularPluginToDependencies(tree: Tree): void {
const packageJson = readJson(tree, 'package.json');
if (packageJson.dependencies?.['@nx/angular']) {
return;
}
packageJson.dependencies ??= {};
packageJson.dependencies['@nx/angular'] =
packageJson.devDependencies['@nx/angular'];
delete packageJson.devDependencies['@nx/angular'];
writeJson(tree, 'package.json', packageJson);
}

View File

@ -3,13 +3,14 @@ import 'nx/src/internal-testing-utils/mock-project-graph';
import {
readJson,
readProjectConfiguration,
Tree,
updateJson,
type Tree,
} from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { E2eTestRunner } from '../../utils/test-runners';
import { nxVersion } from '../../utils/versions';
import { generateTestApplication } from '../utils/testing';
import { setupMf } from './setup-mf';
import { E2eTestRunner } from '../../utils/test-runners';
describe('Init MF', () => {
let tree: Tree;
@ -760,6 +761,42 @@ describe('Init MF', () => {
`);
});
it('should move the @nx/angular plugin to dependencies when --mfType=host', async () => {
updateJson(tree, 'package.json', (json) => ({
...json,
devDependencies: {
...json.devDependencies,
'@nx/angular': nxVersion,
},
}));
await setupMf(tree, { appName: 'app1', mfType: 'host' });
const { devDependencies, dependencies } = readJson(tree, 'package.json');
expect(devDependencies['@nx/angular']).toBeUndefined();
expect(dependencies['@nx/angular']).toBe(nxVersion);
});
it('should move the @nx/angular plugin to dependencies when --federationType=dynamic', async () => {
updateJson(tree, 'package.json', (json) => ({
...json,
devDependencies: {
...json.devDependencies,
'@nx/angular': nxVersion,
},
}));
await setupMf(tree, {
appName: 'app1',
mfType: 'remote',
federationType: 'dynamic',
});
const { devDependencies, dependencies } = readJson(tree, 'package.json');
expect(devDependencies['@nx/angular']).toBeUndefined();
expect(dependencies['@nx/angular']).toBe(nxVersion);
});
describe('angular compat support', () => {
beforeEach(() => {
updateJson(tree, 'package.json', (json) => ({

View File

@ -1,11 +1,13 @@
import type { Tree } from '@nx/devkit';
import {
addDependenciesToPackageJson,
formatFiles,
readProjectConfiguration,
type Tree,
} from '@nx/devkit';
import type { Schema } from './schema';
import {
moduleFederationEnhancedVersion,
nxVersion,
} from '../../utils/versions';
import {
addCypressOnErrorWorkaround,
addRemoteEntry,
@ -14,18 +16,16 @@ import {
fixBootstrap,
generateWebpackConfig,
getRemotesWithPorts,
moveAngularPluginToDependencies,
normalizeOptions,
removeDeadCodeFromRemote,
setupHostIfDynamic,
setupTspathForRemote,
setupServeTarget,
setupTspathForRemote,
updateHostAppRoutes,
updateTsConfig,
} from './lib';
import {
moduleFederationEnhancedVersion,
nxVersion,
} from '../../utils/versions';
import type { Schema } from './schema';
export async function setupMf(tree: Tree, rawOptions: Schema) {
const options = normalizeOptions(tree, rawOptions);
@ -88,6 +88,15 @@ export async function setupMf(tree: Tree, rawOptions: Schema) {
fixBootstrap(tree, projectConfig.root, options);
if (options.mfType === 'host' || options.federationType === 'dynamic') {
/**
* Host applications and dynamic federation applications generate runtime
* code that depends on the @nx/angular plugin. Ensure that the plugin is
* in the production dependencies.
*/
moveAngularPluginToDependencies(tree);
}
if (!options.skipE2E) {
addCypressOnErrorWorkaround(tree, options);
}

View File

@ -103,9 +103,10 @@ function getPresetDependencies({
case Preset.AngularMonorepo:
case Preset.AngularStandalone:
return {
dependencies: { '@nx/angular': nxVersion },
dependencies: {},
dev: {
'@angular-devkit/core': angularCliVersion,
'@nx/angular': nxVersion,
typescript: typescriptVersion,
},
};

View File

@ -168,9 +168,9 @@ describe('new', () => {
tree,
'my-workspace/package.json'
);
expect(dependencies).toStrictEqual({ '@nx/angular': nxVersion });
expect(devDependencies).toStrictEqual({
'@angular-devkit/core': angularCliVersion,
'@nx/angular': nxVersion,
'@nx/workspace': nxVersion,
nx: nxVersion,
typescript: typescriptVersion,