@nx/angular 20.2.0-canary.20241121-60a9f81 → 20.2.0-canary.20241122-a1efb63

Sign up to get free protection for your applications and to get access to all the features.
package/migrations.json CHANGED
@@ -272,6 +272,12 @@
272
272
  "version": "20.2.0-beta.2",
273
273
  "description": "Update the ModuleFederationConfig import use @nx/module-federation.",
274
274
  "factory": "./src/migrations/update-20-2-0/migrate-mf-imports-to-new-package"
275
+ },
276
+ "update-20-2-0-update-with-module-federation-import": {
277
+ "cli": "nx",
278
+ "version": "20.2.0-beta.2",
279
+ "description": "Update the withModuleFederation import use @nx/module-federation/angular.",
280
+ "factory": "./src/migrations/update-20-2-0/migrate-with-mf-import-to-new-package"
275
281
  }
276
282
  },
277
283
  "packageJsonUpdates": {
@@ -1,2 +1,5 @@
1
- export { withModuleFederation } from '../src/utils/mf/with-module-federation';
2
- export { withModuleFederationForSSR } from '../src/utils/mf/with-module-federation-ssr';
1
+ import { withModuleFederation, withModuleFederationForSSR } from '@nx/module-federation/angular';
2
+ /**
3
+ * @deprecated Update the import path to `@nx/module-federation/angular` instead. This import path will be removed in Nx v22.
4
+ */
5
+ export { withModuleFederation, withModuleFederationForSSR };
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.withModuleFederationForSSR = exports.withModuleFederation = void 0;
4
- var with_module_federation_1 = require("../src/utils/mf/with-module-federation");
5
- Object.defineProperty(exports, "withModuleFederation", { enumerable: true, get: function () { return with_module_federation_1.withModuleFederation; } });
6
- var with_module_federation_ssr_1 = require("../src/utils/mf/with-module-federation-ssr");
7
- Object.defineProperty(exports, "withModuleFederationForSSR", { enumerable: true, get: function () { return with_module_federation_ssr_1.withModuleFederationForSSR; } });
4
+ const angular_1 = require("@nx/module-federation/angular");
5
+ Object.defineProperty(exports, "withModuleFederation", { enumerable: true, get: function () { return angular_1.withModuleFederation; } });
6
+ Object.defineProperty(exports, "withModuleFederationForSSR", { enumerable: true, get: function () { return angular_1.withModuleFederationForSSR; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/angular",
3
- "version": "20.2.0-canary.20241121-60a9f81",
3
+ "version": "20.2.0-canary.20241122-a1efb63",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Angular contains executors, generators, and utilities for managing Angular applications and libraries within an Nx workspace. It provides: \n\n- Integration with libraries such as Storybook, Jest, ESLint, Tailwind CSS, Playwright and Cypress. \n\n- Generators to help scaffold code quickly (like: Micro Frontends, Libraries, both internal to your codebase and publishable to npm) \n\n- Single Component Application Modules (SCAMs) \n\n- NgRx helpers. \n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -78,15 +78,13 @@
78
78
  "semver": "^7.5.3",
79
79
  "tslib": "^2.3.0",
80
80
  "webpack-merge": "^5.8.0",
81
- "webpack": "^5.88.0",
82
- "@module-federation/enhanced": "0.7.6",
83
- "@nx/devkit": "20.2.0-canary.20241121-60a9f81",
84
- "@nx/js": "20.2.0-canary.20241121-60a9f81",
85
- "@nx/eslint": "20.2.0-canary.20241121-60a9f81",
86
- "@nx/webpack": "20.2.0-canary.20241121-60a9f81",
87
- "@nx/module-federation": "20.2.0-canary.20241121-60a9f81",
88
- "@nx/web": "20.2.0-canary.20241121-60a9f81",
89
- "@nx/workspace": "20.2.0-canary.20241121-60a9f81",
81
+ "@nx/devkit": "20.2.0-canary.20241122-a1efb63",
82
+ "@nx/js": "20.2.0-canary.20241122-a1efb63",
83
+ "@nx/eslint": "20.2.0-canary.20241122-a1efb63",
84
+ "@nx/webpack": "20.2.0-canary.20241122-a1efb63",
85
+ "@nx/module-federation": "20.2.0-canary.20241122-a1efb63",
86
+ "@nx/web": "20.2.0-canary.20241122-a1efb63",
87
+ "@nx/workspace": "20.2.0-canary.20241122-a1efb63",
90
88
  "piscina": "^4.4.0"
91
89
  },
92
90
  "peerDependencies": {
@@ -1,4 +1,4 @@
1
- const { withModuleFederationForSSR } = require('@nx/angular/module-federation');
1
+ const { withModuleFederationForSSR } = require('@nx/module-federation/angular');
2
2
  const config = require('./module-federation.config');
3
3
  /**
4
4
  * DTS Plugin is disabled in Nx Workspaces as Nx already provides Typing support for Module Federation
@@ -1,4 +1,4 @@
1
- import { withModuleFederationForSSR } from '@nx/angular/module-federation';
1
+ import { withModuleFederationForSSR } from '@nx/module-federation/angular';
2
2
  import config from './module-federation.config';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- const { withModuleFederationForSSR } = require('@nx/angular/module-federation');
1
+ const { withModuleFederationForSSR } = require('@nx/module-federation/angular');
2
2
  const config = require('./module-federation.config');
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { withModuleFederationForSSR } from '@nx/angular/module-federation';
1
+ import { withModuleFederationForSSR } from '@nx/module-federation/angular';
2
2
  import config from './module-federation.config';
3
3
 
4
4
  /**
@@ -10,7 +10,9 @@ function replaceModuleUsagesWithComponent(tree, moduleName, componentName) {
10
10
  }
11
11
  const fileContents = tree.read(path, 'utf-8');
12
12
  if (fileContents.includes(moduleName)) {
13
- const moduleNameRegex = new RegExp(moduleName, 'g');
13
+ // Word boundary \b ensures that other modules won't be affected.
14
+ // E.g. "MapIconModule" would not be affected when "IconModule" is being migrated.
15
+ const moduleNameRegex = new RegExp(`\\b${moduleName}\\b`, 'g');
14
16
  const newFileContents = fileContents.replace(moduleNameRegex, componentName);
15
17
  tree.write(path, newFileContents);
16
18
  }
@@ -1,4 +1,4 @@
1
- import { withModuleFederation } from '@nx/angular/module-federation';
1
+ import { withModuleFederation } from '@nx/module-federation/angular';
2
2
  import config from './module-federation.config';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { withModuleFederation } from '@nx/angular/module-federation';
1
+ import { withModuleFederation } from '@nx/module-federation/angular';
2
2
  import config from './module-federation.config';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- const { withModuleFederation } = require('@nx/angular/module-federation');
1
+ const { withModuleFederation } = require('@nx/module-federation/angular');
2
2
  const config = require('./module-federation.config');
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- const { withModuleFederation } = require('@nx/angular/module-federation');
1
+ const { withModuleFederation } = require('@nx/module-federation/angular');
2
2
  const config = require('./module-federation.config');
3
3
 
4
4
  /**
@@ -0,0 +1,2 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export default function migrateWithMfImport(tree: Tree): Promise<void>;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = migrateWithMfImport;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
6
+ const tsquery_1 = require("@phenomnomnominal/tsquery");
7
+ const NX_ANGULAR_MODULE_FEDERATION_IMPORT_SELECTOR = 'ImportDeclaration > StringLiteral[value=@nx/angular/module-federation], VariableStatement CallExpression:has(Identifier[name=require]) > StringLiteral[value=@nx/angular/module-federation]';
8
+ const NEW_IMPORT_PATH = `'@nx/module-federation/angular'`;
9
+ async function migrateWithMfImport(tree) {
10
+ const projects = new Set();
11
+ (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nx/angular:webpack-browser', (options, project, target) => {
12
+ const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, project);
13
+ projects.add(projectConfig.root);
14
+ });
15
+ for (const projectRoot of projects) {
16
+ (0, devkit_1.visitNotIgnoredFiles)(tree, projectRoot, (filePath) => {
17
+ if (!filePath.endsWith('.ts') && !filePath.endsWith('.js')) {
18
+ return;
19
+ }
20
+ let contents = tree.read(filePath, 'utf-8');
21
+ if (!contents.includes('@nx/angular/module-federation')) {
22
+ return;
23
+ }
24
+ const ast = tsquery_1.tsquery.ast(contents);
25
+ const importNodes = (0, tsquery_1.tsquery)(ast, NX_ANGULAR_MODULE_FEDERATION_IMPORT_SELECTOR);
26
+ if (importNodes.length === 0) {
27
+ return;
28
+ }
29
+ const importPathNode = importNodes[0];
30
+ contents = `${contents.slice(0, importPathNode.getStart())}${NEW_IMPORT_PATH}${contents.slice(importPathNode.getEnd())}`;
31
+ tree.write(filePath, contents);
32
+ });
33
+ }
34
+ await (0, devkit_1.formatFiles)(tree);
35
+ }
@@ -1,15 +0,0 @@
1
- import { ModuleFederationConfig, SharedLibraryConfig } from '@nx/module-federation';
2
- export declare function applyDefaultEagerPackages(sharedConfig: Record<string, SharedLibraryConfig>): void;
3
- export declare const DEFAULT_NPM_PACKAGES_TO_AVOID: string[];
4
- export declare const DEFAULT_ANGULAR_PACKAGES_TO_SHARE: string[];
5
- export declare function getFunctionDeterminateRemoteUrl(isServer?: boolean): (remote: string) => string;
6
- export declare function getModuleFederationConfig(mfConfig: ModuleFederationConfig, options?: {
7
- isServer: boolean;
8
- determineRemoteUrl?: (remote: string) => string;
9
- }): Promise<{
10
- sharedLibraries: import("@nx/module-federation").SharedWorkspaceLibraryConfig;
11
- sharedDependencies: {
12
- [x: string]: SharedLibraryConfig;
13
- };
14
- mappedRemotes: Record<string, string>;
15
- }>;
@@ -1,101 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_ANGULAR_PACKAGES_TO_SHARE = exports.DEFAULT_NPM_PACKAGES_TO_AVOID = void 0;
4
- exports.applyDefaultEagerPackages = applyDefaultEagerPackages;
5
- exports.getFunctionDeterminateRemoteUrl = getFunctionDeterminateRemoteUrl;
6
- exports.getModuleFederationConfig = getModuleFederationConfig;
7
- const module_federation_1 = require("@nx/module-federation");
8
- const devkit_1 = require("@nx/devkit");
9
- const project_graph_1 = require("nx/src/project-graph/project-graph");
10
- function applyDefaultEagerPackages(sharedConfig) {
11
- const DEFAULT_PACKAGES_TO_LOAD_EAGERLY = [
12
- '@angular/localize',
13
- '@angular/localize/init',
14
- ];
15
- for (const pkg of DEFAULT_PACKAGES_TO_LOAD_EAGERLY) {
16
- if (!sharedConfig[pkg]) {
17
- continue;
18
- }
19
- sharedConfig[pkg] = { ...sharedConfig[pkg], eager: true };
20
- }
21
- }
22
- exports.DEFAULT_NPM_PACKAGES_TO_AVOID = [
23
- 'zone.js',
24
- '@nx/angular/mf',
25
- '@nrwl/angular/mf',
26
- ];
27
- exports.DEFAULT_ANGULAR_PACKAGES_TO_SHARE = [
28
- '@angular/core',
29
- '@angular/animations',
30
- '@angular/common',
31
- ];
32
- function getFunctionDeterminateRemoteUrl(isServer = false) {
33
- const target = 'serve';
34
- const remoteEntry = isServer ? 'server/remoteEntry.js' : 'remoteEntry.mjs';
35
- return function (remote) {
36
- const mappedStaticRemotesFromEnv = process.env
37
- .NX_MF_DEV_SERVER_STATIC_REMOTES
38
- ? JSON.parse(process.env.NX_MF_DEV_SERVER_STATIC_REMOTES)
39
- : undefined;
40
- if (mappedStaticRemotesFromEnv && mappedStaticRemotesFromEnv[remote]) {
41
- return `${mappedStaticRemotesFromEnv[remote]}/${remoteEntry}`;
42
- }
43
- let remoteConfiguration = null;
44
- try {
45
- remoteConfiguration = (0, project_graph_1.readCachedProjectConfiguration)(remote);
46
- }
47
- catch (e) {
48
- throw new Error(`Cannot find remote "${remote}". Check that the remote name is correct in your module federation config file.\n`);
49
- }
50
- const serveTarget = remoteConfiguration?.targets?.[target];
51
- if (!serveTarget) {
52
- throw new Error(`Cannot automatically determine URL of remote (${remote}). Looked for property "host" in the project's "serve" target.\n
53
- You can also use the tuple syntax in your webpack config to configure your remotes. e.g. \`remotes: [['remote1', 'http://localhost:4201']]\``);
54
- }
55
- const host = serveTarget.options?.host ??
56
- `http${serveTarget.options.ssl ? 's' : ''}://localhost`;
57
- const port = serveTarget.options?.port ?? 4201;
58
- return `${host.endsWith('/') ? host.slice(0, -1) : host}:${port}/${remoteEntry}`;
59
- };
60
- }
61
- async function getModuleFederationConfig(mfConfig, options = { isServer: false }) {
62
- let projectGraph;
63
- try {
64
- projectGraph = (0, devkit_1.readCachedProjectGraph)();
65
- }
66
- catch (e) {
67
- projectGraph = await (0, devkit_1.createProjectGraphAsync)();
68
- }
69
- if (!projectGraph.nodes[mfConfig.name]?.data) {
70
- throw Error(`Cannot find project "${mfConfig.name}". Check that the name is correct in module-federation.config.js`);
71
- }
72
- const dependencies = (0, module_federation_1.getDependentPackagesForProject)(projectGraph, mfConfig.name);
73
- if (mfConfig.shared) {
74
- dependencies.workspaceLibraries = dependencies.workspaceLibraries.filter((lib) => mfConfig.shared(lib.importKey, {}) !== false);
75
- dependencies.npmPackages = dependencies.npmPackages.filter((pkg) => mfConfig.shared(pkg, {}) !== false);
76
- }
77
- const sharedLibraries = (0, module_federation_1.shareWorkspaceLibraries)(dependencies.workspaceLibraries);
78
- const npmPackages = (0, module_federation_1.sharePackages)(Array.from(new Set([
79
- ...exports.DEFAULT_ANGULAR_PACKAGES_TO_SHARE,
80
- ...dependencies.npmPackages.filter((pkg) => !exports.DEFAULT_NPM_PACKAGES_TO_AVOID.includes(pkg)),
81
- ])));
82
- exports.DEFAULT_NPM_PACKAGES_TO_AVOID.forEach((pkgName) => {
83
- if (pkgName in npmPackages) {
84
- delete npmPackages[pkgName];
85
- }
86
- });
87
- const sharedDependencies = {
88
- ...sharedLibraries.getLibraries(projectGraph.nodes[mfConfig.name].data.root),
89
- ...npmPackages,
90
- };
91
- applyDefaultEagerPackages(sharedDependencies);
92
- (0, module_federation_1.applySharedFunction)(sharedDependencies, mfConfig.shared);
93
- (0, module_federation_1.applyAdditionalShared)(sharedDependencies, mfConfig.additionalShared, projectGraph);
94
- const determineRemoteUrlFn = options.determineRemoteUrl ||
95
- getFunctionDeterminateRemoteUrl(options.isServer);
96
- const mapRemotesFunction = options.isServer ? module_federation_1.mapRemotesForSSR : module_federation_1.mapRemotes;
97
- const mappedRemotes = !mfConfig.remotes || mfConfig.remotes.length === 0
98
- ? {}
99
- : mapRemotesFunction(mfConfig.remotes, 'mjs', determineRemoteUrlFn);
100
- return { sharedLibraries, sharedDependencies, mappedRemotes };
101
- }
@@ -1,2 +0,0 @@
1
- import type { ModuleFederationConfig, NxModuleFederationConfigOverride } from '@nx/module-federation';
2
- export declare function withModuleFederationForSSR(options: ModuleFederationConfig, configOverride?: NxModuleFederationConfigOverride): Promise<(config: any) => any>;
@@ -1,68 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.withModuleFederationForSSR = withModuleFederationForSSR;
4
- const utils_1 = require("./utils");
5
- async function withModuleFederationForSSR(options, configOverride) {
6
- if (global.NX_GRAPH_CREATION) {
7
- return (config) => config;
8
- }
9
- const { sharedLibraries, sharedDependencies, mappedRemotes } = await (0, utils_1.getModuleFederationConfig)(options, {
10
- isServer: true,
11
- });
12
- return (config) => {
13
- const updatedConfig = {
14
- ...(config ?? {}),
15
- target: 'async-node',
16
- output: {
17
- ...(config.output ?? {}),
18
- uniqueName: options.name,
19
- },
20
- optimization: {
21
- ...(config.optimization ?? {}),
22
- runtimeChunk: false,
23
- },
24
- resolve: {
25
- ...(config.resolve ?? {}),
26
- alias: {
27
- ...(config.resolve?.alias ?? {}),
28
- ...sharedLibraries.getAliases(),
29
- },
30
- },
31
- plugins: [
32
- ...(config.plugins ?? []),
33
- new (require('@module-federation/enhanced').ModuleFederationPlugin)({
34
- name: options.name.replace(/-/g, '_'),
35
- filename: 'remoteEntry.js',
36
- exposes: options.exposes,
37
- remotes: mappedRemotes,
38
- shared: {
39
- ...sharedDependencies,
40
- },
41
- /**
42
- * Apply user-defined config override
43
- */
44
- ...(configOverride ? configOverride : {}),
45
- runtimePlugins: process.env.NX_MF_DEV_REMOTES &&
46
- !options.disableNxRuntimeLibraryControlPlugin
47
- ? [
48
- ...(configOverride?.runtimePlugins ?? []),
49
- require.resolve('@module-federation/node/runtimePlugin'),
50
- require.resolve('@nx/module-federation/src/utils/plugins/runtime-library-control.plugin.js'),
51
- ]
52
- : [
53
- ...(configOverride?.runtimePlugins ?? []),
54
- require.resolve('@module-federation/node/runtimePlugin'),
55
- ],
56
- virtualRuntimeEntry: true,
57
- }, {}),
58
- sharedLibraries.getReplacementPlugin(),
59
- ],
60
- };
61
- // The env var is only set from the module-federation-dev-server
62
- // Attach the runtime plugin
63
- updatedConfig.plugins.push(new (require('webpack').DefinePlugin)({
64
- 'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
65
- }));
66
- return updatedConfig;
67
- };
68
- }
@@ -1,2 +0,0 @@
1
- import type { ModuleFederationConfig, NxModuleFederationConfigOverride } from '@nx/module-federation';
2
- export declare function withModuleFederation(options: ModuleFederationConfig, configOverride?: NxModuleFederationConfigOverride): Promise<(config: any) => any>;
@@ -1,70 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.withModuleFederation = withModuleFederation;
4
- const utils_1 = require("./utils");
5
- const webpack_1 = require("@module-federation/enhanced/webpack");
6
- async function withModuleFederation(options, configOverride) {
7
- if (global.NX_GRAPH_CREATION) {
8
- return (config) => config;
9
- }
10
- const { sharedLibraries, sharedDependencies, mappedRemotes } = await (0, utils_1.getModuleFederationConfig)(options);
11
- return (config) => {
12
- const updatedConfig = {
13
- ...(config ?? {}),
14
- output: {
15
- ...(config.output ?? {}),
16
- uniqueName: options.name,
17
- publicPath: 'auto',
18
- },
19
- optimization: {
20
- ...(config.optimization ?? {}),
21
- runtimeChunk: false,
22
- },
23
- resolve: {
24
- ...(config.resolve ?? {}),
25
- alias: {
26
- ...(config.resolve?.alias ?? {}),
27
- ...sharedLibraries.getAliases(),
28
- },
29
- },
30
- experiments: {
31
- ...(config.experiments ?? {}),
32
- outputModule: true,
33
- },
34
- plugins: [
35
- ...(config.plugins ?? []),
36
- new webpack_1.ModuleFederationPlugin({
37
- name: options.name.replace(/-/g, '_'),
38
- filename: 'remoteEntry.mjs',
39
- exposes: options.exposes,
40
- remotes: mappedRemotes,
41
- shared: {
42
- ...sharedDependencies,
43
- },
44
- library: {
45
- type: 'module',
46
- },
47
- /**
48
- * Apply user-defined config override
49
- */
50
- ...(configOverride ? configOverride : {}),
51
- runtimePlugins: process.env.NX_MF_DEV_REMOTES &&
52
- !options.disableNxRuntimeLibraryControlPlugin
53
- ? [
54
- ...(configOverride?.runtimePlugins ?? []),
55
- require.resolve('@nx/module-federation/src/utils/plugins/runtime-library-control.plugin.js'),
56
- ]
57
- : configOverride?.runtimePlugins,
58
- virtualRuntimeEntry: true,
59
- }),
60
- sharedLibraries.getReplacementPlugin(),
61
- ],
62
- };
63
- // The env var is only set from the module-federation-dev-server
64
- // Attach the runtime plugin
65
- updatedConfig.plugins.push(new (require('webpack').DefinePlugin)({
66
- 'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
67
- }));
68
- return updatedConfig;
69
- };
70
- }