@nx/angular 17.0.0-beta.8 → 17.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/angular",
3
- "version": "17.0.0-beta.8",
3
+ "version": "17.0.0-rc.0",
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, 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- Upgrading AngularJS applications \n\n- Single Component Application Modules (SCAMs) \n\n- NgRx helpers. \n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -79,14 +79,15 @@
79
79
  "webpack": "^5.80.0",
80
80
  "webpack-merge": "^5.8.0",
81
81
  "enquirer": "^2.3.6",
82
- "@nx/devkit": "17.0.0-beta.8",
83
- "@nx/cypress": "17.0.0-beta.8",
84
- "@nx/jest": "17.0.0-beta.8",
85
- "@nx/js": "17.0.0-beta.8",
86
- "@nx/eslint": "17.0.0-beta.8",
87
- "@nx/webpack": "17.0.0-beta.8",
88
- "@nx/workspace": "17.0.0-beta.8",
89
- "@nrwl/angular": "17.0.0-beta.8"
82
+ "@nx/devkit": "17.0.0-rc.0",
83
+ "@nx/cypress": "17.0.0-rc.0",
84
+ "@nx/jest": "17.0.0-rc.0",
85
+ "@nx/js": "17.0.0-rc.0",
86
+ "@nx/eslint": "17.0.0-rc.0",
87
+ "@nx/webpack": "17.0.0-rc.0",
88
+ "@nx/web": "17.0.0-rc.0",
89
+ "@nx/workspace": "17.0.0-rc.0",
90
+ "@nrwl/angular": "17.0.0-rc.0"
90
91
  },
91
92
  "peerDependencies": {
92
93
  "@angular-devkit/build-angular": ">= 14.0.0 < 17.0.0",
@@ -1,5 +1,5 @@
1
1
  import type { Schema } from './schema';
2
2
  import { executeWebpackDevServerBuilder } from '../webpack-dev-server/webpack-dev-server.impl';
3
- export declare function executeModuleFederationDevServerBuilder(schema: Schema, context: import('@angular-devkit/architect').BuilderContext): ReturnType<typeof executeWebpackDevServerBuilder>;
3
+ export declare function executeModuleFederationDevServerBuilder(schema: Schema, context: import('@angular-devkit/architect').BuilderContext): ReturnType<typeof executeWebpackDevServerBuilder | any>;
4
4
  declare const _default: any;
5
5
  export default _default;
@@ -9,12 +9,41 @@ const executor_utils_1 = require("nx/src/command-line/run/executor-utils");
9
9
  const module_federation_1 = require("../utilities/module-federation");
10
10
  const fs_1 = require("fs");
11
11
  const path_1 = require("path");
12
- const find_matching_projects_1 = require("nx/src/utils/find-matching-projects");
12
+ const module_federation_2 = require("@nx/webpack/src/utils/module-federation");
13
+ const child_process_1 = require("child_process");
14
+ const rxjs_1 = require("rxjs");
13
15
  function executeModuleFederationDevServerBuilder(schema, context) {
16
+ const nxBin = require.resolve('nx');
14
17
  const { ...options } = schema;
15
18
  const projectGraph = (0, devkit_1.readCachedProjectGraph)();
16
19
  const { projects: workspaceProjects } = (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
17
20
  const project = workspaceProjects[context.target.project];
21
+ const staticFileServer = (0, rxjs_1.from)(Promise.resolve().then(() => require('@nx/web/src/executors/file-server/file-server.impl'))).pipe((0, rxjs_1.switchMap)((fileServerExecutor) => fileServerExecutor.default({
22
+ port: options.port,
23
+ host: options.host,
24
+ ssl: options.ssl,
25
+ buildTarget: options.browserTarget,
26
+ parallel: false,
27
+ spa: false,
28
+ withDeps: false,
29
+ cors: true,
30
+ }, {
31
+ projectGraph,
32
+ root: context.workspaceRoot,
33
+ target: projectGraph.nodes[context.target.project].data.targets[context.target.target],
34
+ targetName: context.target.target,
35
+ projectName: context.target.project,
36
+ configurationName: context.target.configuration,
37
+ cwd: context.currentDirectory,
38
+ isVerbose: options.verbose,
39
+ projectsConfigurations: (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph),
40
+ nxJsonConfiguration: (0, devkit_1.readNxJson)(),
41
+ })));
42
+ const webpackDevServer = (0, webpack_dev_server_impl_1.executeWebpackDevServerBuilder)(options, context);
43
+ const currExecutor = options.static ? staticFileServer : webpackDevServer;
44
+ if (options.isInitialHost === false) {
45
+ return currExecutor;
46
+ }
18
47
  let pathToManifestFile = (0, path_1.join)(context.workspaceRoot, project.sourceRoot, 'assets/module-federation.manifest.json');
19
48
  if (options.pathToManifestFile) {
20
49
  const userPathToManifestFile = (0, path_1.join)(context.workspaceRoot, options.pathToManifestFile);
@@ -27,47 +56,80 @@ function executeModuleFederationDevServerBuilder(schema, context) {
27
56
  pathToManifestFile = userPathToManifestFile;
28
57
  }
29
58
  (0, module_federation_1.validateDevRemotes)(options, workspaceProjects);
30
- const remotesToSkip = new Set((0, find_matching_projects_1.findMatchingProjects)(options.skipRemotes, projectGraph.nodes) ?? []);
31
- if (remotesToSkip.size > 0) {
32
- devkit_1.logger.info(`Remotes not served automatically: ${[...remotesToSkip].join(', ')}`);
59
+ const moduleFederationConfig = (0, module_federation_2.getModuleFederationConfig)(project.targets.build.options.tsConfig, context.workspaceRoot, project.root, 'angular');
60
+ const remotes = (0, module_federation_2.getRemotes)(options.devRemotes, options.skipRemotes, moduleFederationConfig, {
61
+ projectName: project.name,
62
+ projectGraph,
63
+ root: context.workspaceRoot,
64
+ }, pathToManifestFile);
65
+ let isCollectingStaticRemoteOutput = true;
66
+ for (const app of remotes.staticRemotes) {
67
+ const remoteProjectServeTarget = projectGraph.nodes[app].data.targets['serve-static'];
68
+ const isUsingModuleFederationDevServerExecutor = remoteProjectServeTarget.executor.includes('module-federation-dev-server');
69
+ let outWithErr = [];
70
+ const staticProcess = (0, child_process_1.fork)(nxBin, [
71
+ 'run',
72
+ `${app}:serve-static${context.target.configuration ? `:${context.target.configuration}` : ''}`,
73
+ ...(isUsingModuleFederationDevServerExecutor
74
+ ? [`--isInitialHost=false`]
75
+ : []),
76
+ ], {
77
+ cwd: context.workspaceRoot,
78
+ stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
79
+ });
80
+ staticProcess.stdout.on('data', (data) => {
81
+ if (isCollectingStaticRemoteOutput) {
82
+ outWithErr.push(data.toString());
83
+ }
84
+ else {
85
+ outWithErr = null;
86
+ staticProcess.stdout.removeAllListeners('data');
87
+ }
88
+ });
89
+ staticProcess.stderr.on('data', (data) => devkit_1.logger.info(data.toString()));
90
+ staticProcess.on('exit', (code) => {
91
+ if (code !== 0) {
92
+ devkit_1.logger.info(outWithErr.join(''));
93
+ throw new Error(`Remote failed to start. See above for errors.`);
94
+ }
95
+ });
96
+ process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
97
+ process.on('exit', () => staticProcess.kill('SIGTERM'));
33
98
  }
34
- const staticRemotes = (0, module_federation_1.getStaticRemotes)(project, context, workspaceProjects, remotesToSkip);
35
- const dynamicRemotes = (0, module_federation_1.getDynamicRemotes)(project, context, workspaceProjects, remotesToSkip, pathToManifestFile);
36
- const remotes = [...staticRemotes, ...dynamicRemotes];
37
- const devServeRemotes = !options.devRemotes
38
- ? []
39
- : Array.isArray(options.devRemotes)
40
- ? (0, find_matching_projects_1.findMatchingProjects)(options.devRemotes, projectGraph.nodes)
41
- : (0, find_matching_projects_1.findMatchingProjects)([options.devRemotes], projectGraph.nodes);
42
- for (const remote of remotes) {
43
- const isDev = devServeRemotes.includes(remote);
44
- const target = isDev ? 'serve' : 'serve-static';
45
- if (!workspaceProjects[remote].targets?.[target]) {
46
- throw new Error(`Could not find "${target}" target in "${remote}" project.`);
99
+ const devRemotes$ = [];
100
+ for (const app of remotes.devRemotes) {
101
+ if (!workspaceProjects[app].targets?.['serve']) {
102
+ throw new Error(`Could not find "serve" target in "${app}" project.`);
47
103
  }
48
- else if (!workspaceProjects[remote].targets?.[target].executor) {
49
- throw new Error(`Could not find executor for "${target}" target in "${remote}" project.`);
104
+ else if (!workspaceProjects[app].targets?.['serve'].executor) {
105
+ throw new Error(`Could not find executor for "serve" target in "${app}" project.`);
50
106
  }
51
107
  const runOptions = {};
52
- if (options.verbose) {
53
- const [collection, executor] = workspaceProjects[remote].targets[target].executor.split(':');
54
- const { schema } = (0, executor_utils_1.getExecutorInformation)(collection, executor, devkit_1.workspaceRoot);
55
- if (schema.additionalProperties || 'verbose' in schema.properties) {
56
- runOptions.verbose = options.verbose;
57
- }
108
+ const [collection, executor] = workspaceProjects[app].targets['serve'].executor.split(':');
109
+ const isUsingModuleFederationDevServerExecutor = executor.includes('module-federation-dev-server');
110
+ const { schema } = (0, executor_utils_1.getExecutorInformation)(collection, executor, devkit_1.workspaceRoot);
111
+ if ((options.verbose && schema.additionalProperties) ||
112
+ 'verbose' in schema.properties) {
113
+ runOptions.verbose = options.verbose;
114
+ }
115
+ if (isUsingModuleFederationDevServerExecutor) {
116
+ runOptions.isInitialHost = false;
58
117
  }
59
- (0, ngcli_adapter_1.scheduleTarget)(context.workspaceRoot, {
60
- project: remote,
61
- target,
118
+ const serve$ = (0, ngcli_adapter_1.scheduleTarget)(context.workspaceRoot, {
119
+ project: app,
120
+ target: 'serve',
62
121
  configuration: context.target.configuration,
63
122
  runOptions,
64
123
  }, options.verbose).then((obs) => {
65
124
  obs.toPromise().catch((err) => {
66
- throw new Error(`Remote '${remote}' failed to serve correctly due to the following: \r\n${err.toString()}`);
125
+ throw new Error(`Remote '${app}' failed to serve correctly due to the following: \r\n${err.toString()}`);
67
126
  });
68
127
  });
128
+ devRemotes$.push(serve$);
69
129
  }
70
- return (0, webpack_dev_server_impl_1.executeWebpackDevServerBuilder)(options, context);
130
+ return devRemotes$.length > 0
131
+ ? (0, rxjs_1.combineLatest)([...devRemotes$]).pipe((0, rxjs_1.concatMap)(() => currExecutor))
132
+ : currExecutor;
71
133
  }
72
134
  exports.executeModuleFederationDevServerBuilder = executeModuleFederationDevServerBuilder;
73
135
  exports.default = require('@angular-devkit/architect').createBuilder(executeModuleFederationDevServerBuilder);
@@ -20,4 +20,6 @@ export interface Schema {
20
20
  devRemotes?: string[];
21
21
  skipRemotes?: string[];
22
22
  pathToManifestFile?: string;
23
+ static?: boolean;
24
+ isInitialHost?: boolean;
23
25
  }
@@ -122,6 +122,16 @@
122
122
  "pathToManifestFile": {
123
123
  "type": "string",
124
124
  "description": "Path to a Module Federation manifest file (e.g. `my/path/to/module-federation.manifest.json`) containing the dynamic remote applications relative to the workspace root."
125
+ },
126
+ "static": {
127
+ "type": "boolean",
128
+ "description": "Whether to use a static file server instead of the webpack-dev-server. This should be used for remote applications that are also host applications."
129
+ },
130
+ "isInitialHost": {
131
+ "type": "boolean",
132
+ "description": "Whether the host that is running this executor is the first in the project tree to do so.",
133
+ "default": true,
134
+ "x-priority": "internal"
125
135
  }
126
136
  },
127
137
  "additionalProperties": false,