@nx/angular 19.5.0 → 19.5.2

Sign up to get free protection for your applications and to get access to all the features.
package/ng-package.json CHANGED
@@ -21,11 +21,15 @@
21
21
  "ts-node",
22
22
  "tsconfig-paths",
23
23
  "semver",
24
+ "webpack",
25
+ "express",
26
+ "http-proxy-middleware",
24
27
  "http-server",
25
28
  "magic-string",
26
29
  "enquirer",
27
30
  "find-cache-dir",
28
- "piscina"
31
+ "piscina",
32
+ "webpack"
29
33
  ],
30
34
  "keepLifecycleScripts": true
31
35
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/angular",
3
- "version": "19.5.0",
3
+ "version": "19.5.2",
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,16 @@
78
78
  "semver": "^7.5.3",
79
79
  "tslib": "^2.3.0",
80
80
  "webpack-merge": "^5.8.0",
81
+ "webpack": "^5.88.0",
81
82
  "@module-federation/enhanced": "~0.2.3",
82
- "@nx/devkit": "19.5.0",
83
- "@nx/js": "19.5.0",
84
- "@nx/eslint": "19.5.0",
85
- "@nx/webpack": "19.5.0",
86
- "@nx/web": "19.5.0",
87
- "@nx/workspace": "19.5.0",
83
+ "@nx/devkit": "19.5.2",
84
+ "@nx/js": "19.5.2",
85
+ "@nx/eslint": "19.5.2",
86
+ "@nx/webpack": "19.5.2",
87
+ "@nx/web": "19.5.2",
88
+ "@nx/workspace": "19.5.2",
88
89
  "piscina": "^4.4.0",
89
- "@nrwl/angular": "19.5.0"
90
+ "@nrwl/angular": "19.5.2"
90
91
  },
91
92
  "peerDependencies": {
92
93
  "@angular-devkit/build-angular": ">= 16.0.0 < 19.0.0",
@@ -36,6 +36,8 @@ function executeModuleFederationDevSSRBuilder(schema, context) {
36
36
  : Array.isArray(options.devRemotes)
37
37
  ? options.devRemotes
38
38
  : [options.devRemotes];
39
+ // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin
40
+ process.env.NX_MF_DEV_REMOTES = JSON.stringify(devServeRemotes);
39
41
  (0, module_federation_1.validateDevRemotes)({ devRemotes: devServeRemotes }, workspaceProjects);
40
42
  const remotesToSkip = new Set(options.skipRemotes ?? []);
41
43
  const staticRemotes = (0, module_federation_1.getStaticRemotes)(project, context, workspaceProjects, remotesToSkip);
@@ -1,4 +1,4 @@
1
1
  import { type Schema } from '../schema';
2
2
  import { type ExecutorContext } from '@nx/devkit';
3
- import type { StaticRemotesConfig } from './parse-static-remotes-config';
4
- export declare function buildStaticRemotes(staticRemotesConfig: StaticRemotesConfig, nxBin: any, context: ExecutorContext, options: Schema): Promise<void>;
3
+ import type { StaticRemotesConfig } from '@nx/webpack/src/utils/module-federation/parse-static-remotes-config';
4
+ export declare function buildStaticRemotes(staticRemotesConfig: StaticRemotesConfig, nxBin: any, context: ExecutorContext, options: Schema): Promise<Record<string, string>>;
@@ -14,7 +14,6 @@ async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options)
14
14
  for (const app of staticRemotesConfig.remotes) {
15
15
  mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host}:${options.staticRemotesPort}/${staticRemotesConfig.config[app].urlSegment}`;
16
16
  }
17
- process.env.NX_MF_DEV_SERVER_STATIC_REMOTES = JSON.stringify(mappedLocationOfRemotes);
18
17
  await new Promise((res) => {
19
18
  devkit_1.logger.info(`NX Building ${staticRemotesConfig.remotes.length} static remotes...`);
20
19
  const staticProcess = (0, node_child_process_1.fork)(nxBin, [
@@ -55,4 +54,5 @@ async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options)
55
54
  process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
56
55
  process.on('exit', () => staticProcess.kill('SIGTERM'));
57
56
  });
57
+ return mappedLocationOfRemotes;
58
58
  }
@@ -1,5 +1,4 @@
1
1
  export * from './build-static-remotes';
2
2
  export * from './normalize-options';
3
- export * from './parse-static-remotes-config';
4
3
  export * from './start-dev-remotes';
5
4
  export * from './start-static-remotes-file-server';
@@ -3,6 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./build-static-remotes"), exports);
5
5
  tslib_1.__exportStar(require("./normalize-options"), exports);
6
- tslib_1.__exportStar(require("./parse-static-remotes-config"), exports);
7
6
  tslib_1.__exportStar(require("./start-dev-remotes"), exports);
8
7
  tslib_1.__exportStar(require("./start-static-remotes-file-server"), exports);
@@ -1,6 +1,6 @@
1
1
  import { type ExecutorContext } from '@nx/devkit';
2
2
  import { type Schema } from '../schema';
3
- import type { StaticRemotesConfig } from './parse-static-remotes-config';
3
+ import type { StaticRemotesConfig } from '@nx/webpack/src/utils/module-federation/parse-static-remotes-config';
4
4
  export declare function startStaticRemotesFileServer(staticRemotesConfig: StaticRemotesConfig, context: ExecutorContext, options: Schema): AsyncGenerator<{
5
5
  success: boolean;
6
6
  baseUrl: string;
@@ -7,6 +7,10 @@ const file_server_impl_1 = tslib_1.__importDefault(require("@nx/web/src/executor
7
7
  const path_1 = require("path");
8
8
  const fs_1 = require("fs");
9
9
  function startStaticRemotesFileServer(staticRemotesConfig, context, options) {
10
+ if (!staticRemotesConfig.remotes ||
11
+ staticRemotesConfig.remotes.length === 0) {
12
+ return;
13
+ }
10
14
  let shouldMoveToCommonLocation = false;
11
15
  let commonOutputDirectory;
12
16
  for (const app of staticRemotesConfig.remotes) {
@@ -41,6 +45,7 @@ function startStaticRemotesFileServer(staticRemotesConfig, context, options) {
41
45
  ssl: options.ssl,
42
46
  sslCert: options.sslCert,
43
47
  sslKey: options.sslKey,
48
+ cacheSeconds: -1,
44
49
  }, context);
45
50
  return staticRemotesIter;
46
51
  }
@@ -14,11 +14,12 @@ const dev_server_impl_1 = require("../../builders/dev-server/dev-server.impl");
14
14
  const module_federation_2 = require("../../builders/utilities/module-federation");
15
15
  const path_1 = require("path");
16
16
  const fs_1 = require("fs");
17
+ const start_remote_proxies_1 = require("@nx/webpack/src/utils/module-federation/start-remote-proxies");
18
+ const parse_static_remotes_config_1 = require("@nx/webpack/src/utils/module-federation/parse-static-remotes-config");
17
19
  async function* moduleFederationDevServerExecutor(schema, context) {
18
20
  // Force Node to resolve to look for the nx binary that is inside node_modules
19
21
  const nxBin = require.resolve('nx/bin/nx');
20
22
  const options = (0, lib_1.normalizeOptions)(schema);
21
- options.staticRemotesPort ??= options.port + 1;
22
23
  const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(context.projectGraph);
23
24
  const project = workspaceProjects[context.projectName];
24
25
  const currIter = options.static
@@ -31,6 +32,7 @@ async function* moduleFederationDevServerExecutor(schema, context) {
31
32
  spa: false,
32
33
  withDeps: false,
33
34
  cors: true,
35
+ cacheSeconds: -1,
34
36
  }, context)
35
37
  : (0, rxjs_for_await_1.eachValueFrom)((0, dev_server_impl_1.executeDevServerBuilder)(options, await (0, ngcli_adapter_1.createBuilderContext)({
36
38
  builderName: '@nx/angular:webpack-browser',
@@ -62,31 +64,19 @@ async function* moduleFederationDevServerExecutor(schema, context) {
62
64
  projectGraph: context.projectGraph,
63
65
  root: context.root,
64
66
  }, pathToManifestFile);
65
- if (remotes.devRemotes.length > 0 && !schema.staticRemotesPort) {
66
- options.staticRemotesPort = options.devRemotes.reduce((portToUse, r) => {
67
- const remoteName = typeof r === 'string' ? r : r.remoteName;
68
- const remotePort = context.projectGraph.nodes[remoteName].data.targets['serve'].options
69
- .port;
70
- if (remotePort >= portToUse) {
71
- return remotePort + 1;
72
- }
73
- else {
74
- return portToUse;
75
- }
76
- }, options.staticRemotesPort);
77
- }
78
- const staticRemotesConfig = (0, lib_1.parseStaticRemotesConfig)(remotes.staticRemotes, context);
79
- await (0, lib_1.buildStaticRemotes)(staticRemotesConfig, nxBin, context, options);
67
+ options.staticRemotesPort ??= remotes.staticRemotePort;
68
+ // Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin
69
+ process.env.NX_MF_DEV_REMOTES = JSON.stringify(remotes.devRemotes.map((r) => (typeof r === 'string' ? r : r.remoteName)));
70
+ const staticRemotesConfig = (0, parse_static_remotes_config_1.parseStaticRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context);
71
+ const mappedLocationsOfStaticRemotes = await (0, lib_1.buildStaticRemotes)(staticRemotesConfig, nxBin, context, options);
80
72
  const devRemoteIters = await (0, lib_1.startRemotes)(remotes.devRemotes, workspaceProjects, options, context, 'serve');
81
- const dynamicRemoteIters = await (0, lib_1.startRemotes)(remotes.dynamicRemotes, workspaceProjects, options, context, 'serve-static');
82
- const staticRemotesIter = remotes.staticRemotes.length > 0
83
- ? (0, lib_1.startStaticRemotesFileServer)(staticRemotesConfig, context, options)
84
- : undefined;
73
+ const staticRemotesIter = (0, lib_1.startStaticRemotesFileServer)(staticRemotesConfig, context, options);
74
+ (0, start_remote_proxies_1.startRemoteProxies)(staticRemotesConfig, mappedLocationsOfStaticRemotes);
85
75
  const removeBaseUrlEmission = (iter) => (0, async_iterable_1.mapAsyncIterable)(iter, (v) => ({
86
76
  ...v,
87
77
  baseUrl: undefined,
88
78
  }));
89
- return yield* (0, async_iterable_1.combineAsyncIterables)(removeBaseUrlEmission(currIter), ...devRemoteIters.map(removeBaseUrlEmission), ...dynamicRemoteIters.map(removeBaseUrlEmission), ...(staticRemotesIter ? [removeBaseUrlEmission(staticRemotesIter)] : []), (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
79
+ return yield* (0, async_iterable_1.combineAsyncIterables)(removeBaseUrlEmission(currIter), ...devRemoteIters.map(removeBaseUrlEmission), ...(staticRemotesIter ? [removeBaseUrlEmission(staticRemotesIter)] : []), (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
90
80
  if (!options.isInitialHost) {
91
81
  done();
92
82
  return;
@@ -23,13 +23,15 @@ export function app(): express.Express {
23
23
  // Example Express Rest API endpoints
24
24
  // server.get('/api/**', (req, res) => { });
25
25
  // Serve static files from /browser
26
- server.get('**', express.static(distFolder, {
27
- maxAge: '1y',
28
- index: 'index.html'
29
- }));
26
+ server.get(
27
+ '*.*',
28
+ express.static(distFolder, {
29
+ maxAge: '1y',
30
+ })
31
+ );
30
32
 
31
33
  // All regular routes use the Angular engine
32
- server.get('**', (req, res, next) => {
34
+ server.get('*', (req, res, next) => {
33
35
  const { protocol, originalUrl, baseUrl, headers } = req;
34
36
 
35
37
  commonEngine
@@ -5,7 +5,7 @@ const devkit_1 = require("@nx/devkit");
5
5
  function addMfEnvToTargetDefaultInputs(tree) {
6
6
  const nxJson = (0, devkit_1.readNxJson)(tree);
7
7
  const webpackExecutor = '@nx/angular:webpack-browser';
8
- const mfEnvVar = 'NX_MF_DEV_SERVER_STATIC_REMOTES';
8
+ const mfEnvVar = 'NX_MF_DEV_REMOTES';
9
9
  nxJson.targetDefaults ??= {};
10
10
  nxJson.targetDefaults[webpackExecutor] ??= {};
11
11
  nxJson.targetDefaults[webpackExecutor].inputs ??= [
@@ -9,44 +9,59 @@ async function withModuleFederationForSSR(options, configOverride) {
9
9
  const { sharedLibraries, sharedDependencies, mappedRemotes } = await (0, utils_1.getModuleFederationConfig)(options, {
10
10
  isServer: true,
11
11
  });
12
- return (config) => ({
13
- ...(config ?? {}),
14
- target: false,
15
- output: {
16
- ...(config.output ?? {}),
17
- uniqueName: options.name,
18
- },
19
- optimization: {
20
- ...(config.optimization ?? {}),
21
- runtimeChunk: false,
22
- },
23
- resolve: {
24
- ...(config.resolve ?? {}),
25
- alias: {
26
- ...(config.resolve?.alias ?? {}),
27
- ...sharedLibraries.getAliases(),
12
+ return (config) => {
13
+ const updatedConfig = {
14
+ ...(config ?? {}),
15
+ target: false,
16
+ output: {
17
+ ...(config.output ?? {}),
18
+ uniqueName: options.name,
28
19
  },
29
- },
30
- plugins: [
31
- ...(config.plugins ?? []),
32
- new (require('@module-federation/node').UniversalFederationPlugin)({
33
- name: options.name,
34
- filename: 'remoteEntry.js',
35
- exposes: options.exposes,
36
- remotes: mappedRemotes,
37
- shared: {
38
- ...sharedDependencies,
39
- },
40
- library: {
41
- type: 'commonjs-module',
20
+ optimization: {
21
+ ...(config.optimization ?? {}),
22
+ runtimeChunk: false,
23
+ },
24
+ resolve: {
25
+ ...(config.resolve ?? {}),
26
+ alias: {
27
+ ...(config.resolve?.alias ?? {}),
28
+ ...sharedLibraries.getAliases(),
42
29
  },
43
- isServer: true,
44
- /**
45
- * Apply user-defined config override
46
- */
47
- ...(configOverride ? configOverride : {}),
48
- }, {}),
49
- sharedLibraries.getReplacementPlugin(),
50
- ],
51
- });
30
+ },
31
+ plugins: [
32
+ ...(config.plugins ?? []),
33
+ new (require('@module-federation/node').UniversalFederationPlugin)({
34
+ name: options.name,
35
+ filename: 'remoteEntry.js',
36
+ exposes: options.exposes,
37
+ remotes: mappedRemotes,
38
+ shared: {
39
+ ...sharedDependencies,
40
+ },
41
+ library: {
42
+ type: 'commonjs-module',
43
+ },
44
+ isServer: true,
45
+ /**
46
+ * Apply user-defined config override
47
+ */
48
+ ...(configOverride ? configOverride : {}),
49
+ runtimePlugins: process.env.NX_MF_DEV_REMOTES &&
50
+ !options.disableNxRuntimeLibraryControlPlugin
51
+ ? [
52
+ ...(configOverride?.runtimePlugins ?? []),
53
+ require.resolve('@nx/webpack/src/utils/module-federation/plugins/runtime-library-control.plugin.js'),
54
+ ]
55
+ : configOverride?.runtimePlugins,
56
+ }, {}),
57
+ sharedLibraries.getReplacementPlugin(),
58
+ ],
59
+ };
60
+ // The env var is only set from the module-federation-dev-server
61
+ // Attach the runtime plugin
62
+ updatedConfig.plugins.push(new (require('webpack').DefinePlugin)({
63
+ 'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
64
+ }));
65
+ return updatedConfig;
66
+ };
52
67
  }
@@ -8,47 +8,62 @@ async function withModuleFederation(options, configOverride) {
8
8
  return (config) => config;
9
9
  }
10
10
  const { sharedLibraries, sharedDependencies, mappedRemotes } = await (0, utils_1.getModuleFederationConfig)(options);
11
- return (config) => ({
12
- ...(config ?? {}),
13
- output: {
14
- ...(config.output ?? {}),
15
- uniqueName: options.name,
16
- publicPath: 'auto',
17
- },
18
- optimization: {
19
- ...(config.optimization ?? {}),
20
- runtimeChunk: false,
21
- },
22
- resolve: {
23
- ...(config.resolve ?? {}),
24
- alias: {
25
- ...(config.resolve?.alias ?? {}),
26
- ...sharedLibraries.getAliases(),
11
+ return (config) => {
12
+ const updatedConfig = {
13
+ ...(config ?? {}),
14
+ output: {
15
+ ...(config.output ?? {}),
16
+ uniqueName: options.name,
17
+ publicPath: 'auto',
27
18
  },
28
- },
29
- experiments: {
30
- ...(config.experiments ?? {}),
31
- outputModule: true,
32
- },
33
- plugins: [
34
- ...(config.plugins ?? []),
35
- new webpack_1.ModuleFederationPlugin({
36
- name: options.name,
37
- filename: 'remoteEntry.mjs',
38
- exposes: options.exposes,
39
- remotes: mappedRemotes,
40
- shared: {
41
- ...sharedDependencies,
42
- },
43
- library: {
44
- type: 'module',
19
+ optimization: {
20
+ ...(config.optimization ?? {}),
21
+ runtimeChunk: false,
22
+ },
23
+ resolve: {
24
+ ...(config.resolve ?? {}),
25
+ alias: {
26
+ ...(config.resolve?.alias ?? {}),
27
+ ...sharedLibraries.getAliases(),
45
28
  },
46
- /**
47
- * Apply user-defined config override
48
- */
49
- ...(configOverride ? configOverride : {}),
50
- }),
51
- sharedLibraries.getReplacementPlugin(),
52
- ],
53
- });
29
+ },
30
+ experiments: {
31
+ ...(config.experiments ?? {}),
32
+ outputModule: true,
33
+ },
34
+ plugins: [
35
+ ...(config.plugins ?? []),
36
+ new webpack_1.ModuleFederationPlugin({
37
+ name: options.name,
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/webpack/src/utils/module-federation/plugins/runtime-library-control.plugin.js'),
56
+ ]
57
+ : configOverride?.runtimePlugins,
58
+ }),
59
+ sharedLibraries.getReplacementPlugin(),
60
+ ],
61
+ };
62
+ // The env var is only set from the module-federation-dev-server
63
+ // Attach the runtime plugin
64
+ updatedConfig.plugins.push(new (require('webpack').DefinePlugin)({
65
+ 'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
66
+ }));
67
+ return updatedConfig;
68
+ };
54
69
  }
@@ -1,11 +0,0 @@
1
- import type { ExecutorContext } from '@nx/devkit';
2
- export type StaticRemoteConfig = {
3
- basePath: string;
4
- outputPath: string;
5
- urlSegment: string;
6
- };
7
- export type StaticRemotesConfig = {
8
- remotes: string[];
9
- config: Record<string, StaticRemoteConfig> | undefined;
10
- };
11
- export declare function parseStaticRemotesConfig(staticRemotes: string[] | undefined, context: ExecutorContext): StaticRemotesConfig;
@@ -1,17 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseStaticRemotesConfig = parseStaticRemotesConfig;
4
- const path_1 = require("path");
5
- function parseStaticRemotesConfig(staticRemotes, context) {
6
- if (!staticRemotes?.length) {
7
- return { remotes: [], config: undefined };
8
- }
9
- const config = {};
10
- for (const app of staticRemotes) {
11
- const outputPath = context.projectGraph.nodes[app].data.targets['build'].options.outputPath;
12
- const basePath = (0, path_1.dirname)(outputPath);
13
- const urlSegment = (0, path_1.basename)(outputPath);
14
- config[app] = { basePath, outputPath, urlSegment };
15
- }
16
- return { remotes: staticRemotes, config };
17
- }