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:
parent
44068b58c0
commit
1ae3c2d8f9
@ -5,6 +5,7 @@ export * from './change-build-target';
|
|||||||
export * from './fix-bootstrap';
|
export * from './fix-bootstrap';
|
||||||
export * from './generate-config';
|
export * from './generate-config';
|
||||||
export * from './get-remotes-with-ports';
|
export * from './get-remotes-with-ports';
|
||||||
|
export * from './move-angular-plugin-to-dependencies';
|
||||||
export * from './normalize-options';
|
export * from './normalize-options';
|
||||||
export * from './update-tsconfig';
|
export * from './update-tsconfig';
|
||||||
export * from './setup-host-if-dynamic';
|
export * from './setup-host-if-dynamic';
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
@ -3,13 +3,14 @@ import 'nx/src/internal-testing-utils/mock-project-graph';
|
|||||||
import {
|
import {
|
||||||
readJson,
|
readJson,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
Tree,
|
|
||||||
updateJson,
|
updateJson,
|
||||||
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
|
import { E2eTestRunner } from '../../utils/test-runners';
|
||||||
|
import { nxVersion } from '../../utils/versions';
|
||||||
import { generateTestApplication } from '../utils/testing';
|
import { generateTestApplication } from '../utils/testing';
|
||||||
import { setupMf } from './setup-mf';
|
import { setupMf } from './setup-mf';
|
||||||
import { E2eTestRunner } from '../../utils/test-runners';
|
|
||||||
|
|
||||||
describe('Init MF', () => {
|
describe('Init MF', () => {
|
||||||
let tree: Tree;
|
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', () => {
|
describe('angular compat support', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
updateJson(tree, 'package.json', (json) => ({
|
updateJson(tree, 'package.json', (json) => ({
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import type { Tree } from '@nx/devkit';
|
|
||||||
import {
|
import {
|
||||||
addDependenciesToPackageJson,
|
addDependenciesToPackageJson,
|
||||||
formatFiles,
|
formatFiles,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import type { Schema } from './schema';
|
import {
|
||||||
|
moduleFederationEnhancedVersion,
|
||||||
|
nxVersion,
|
||||||
|
} from '../../utils/versions';
|
||||||
import {
|
import {
|
||||||
addCypressOnErrorWorkaround,
|
addCypressOnErrorWorkaround,
|
||||||
addRemoteEntry,
|
addRemoteEntry,
|
||||||
@ -14,18 +16,16 @@ import {
|
|||||||
fixBootstrap,
|
fixBootstrap,
|
||||||
generateWebpackConfig,
|
generateWebpackConfig,
|
||||||
getRemotesWithPorts,
|
getRemotesWithPorts,
|
||||||
|
moveAngularPluginToDependencies,
|
||||||
normalizeOptions,
|
normalizeOptions,
|
||||||
removeDeadCodeFromRemote,
|
removeDeadCodeFromRemote,
|
||||||
setupHostIfDynamic,
|
setupHostIfDynamic,
|
||||||
setupTspathForRemote,
|
|
||||||
setupServeTarget,
|
setupServeTarget,
|
||||||
|
setupTspathForRemote,
|
||||||
updateHostAppRoutes,
|
updateHostAppRoutes,
|
||||||
updateTsConfig,
|
updateTsConfig,
|
||||||
} from './lib';
|
} from './lib';
|
||||||
import {
|
import type { Schema } from './schema';
|
||||||
moduleFederationEnhancedVersion,
|
|
||||||
nxVersion,
|
|
||||||
} from '../../utils/versions';
|
|
||||||
|
|
||||||
export async function setupMf(tree: Tree, rawOptions: Schema) {
|
export async function setupMf(tree: Tree, rawOptions: Schema) {
|
||||||
const options = normalizeOptions(tree, rawOptions);
|
const options = normalizeOptions(tree, rawOptions);
|
||||||
@ -88,6 +88,15 @@ export async function setupMf(tree: Tree, rawOptions: Schema) {
|
|||||||
|
|
||||||
fixBootstrap(tree, projectConfig.root, options);
|
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) {
|
if (!options.skipE2E) {
|
||||||
addCypressOnErrorWorkaround(tree, options);
|
addCypressOnErrorWorkaround(tree, options);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,9 +103,10 @@ function getPresetDependencies({
|
|||||||
case Preset.AngularMonorepo:
|
case Preset.AngularMonorepo:
|
||||||
case Preset.AngularStandalone:
|
case Preset.AngularStandalone:
|
||||||
return {
|
return {
|
||||||
dependencies: { '@nx/angular': nxVersion },
|
dependencies: {},
|
||||||
dev: {
|
dev: {
|
||||||
'@angular-devkit/core': angularCliVersion,
|
'@angular-devkit/core': angularCliVersion,
|
||||||
|
'@nx/angular': nxVersion,
|
||||||
typescript: typescriptVersion,
|
typescript: typescriptVersion,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -168,9 +168,9 @@ describe('new', () => {
|
|||||||
tree,
|
tree,
|
||||||
'my-workspace/package.json'
|
'my-workspace/package.json'
|
||||||
);
|
);
|
||||||
expect(dependencies).toStrictEqual({ '@nx/angular': nxVersion });
|
|
||||||
expect(devDependencies).toStrictEqual({
|
expect(devDependencies).toStrictEqual({
|
||||||
'@angular-devkit/core': angularCliVersion,
|
'@angular-devkit/core': angularCliVersion,
|
||||||
|
'@nx/angular': nxVersion,
|
||||||
'@nx/workspace': nxVersion,
|
'@nx/workspace': nxVersion,
|
||||||
nx: nxVersion,
|
nx: nxVersion,
|
||||||
typescript: typescriptVersion,
|
typescript: typescriptVersion,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user