@nx/react 0.0.0-pr-22179-271588f → 0.0.0-pr-26482-ebe2dba
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/LICENSE +1 -1
- package/README.md +1 -1
- package/index.d.ts +3 -1
- package/index.js +5 -3
- package/migrations.json +57 -160
- package/package.json +11 -9
- package/plugins/bundle-rollup.js +1 -1
- package/plugins/component-testing/index.js +5 -2
- package/plugins/component-testing/webpack-fallback.js +1 -1
- package/plugins/nx-react-webpack-plugin/lib/apply-react-config.d.ts +2 -1
- package/plugins/nx-react-webpack-plugin/lib/apply-react-config.js +33 -5
- package/plugins/storybook/index.js +1 -1
- package/plugins/with-react.d.ts +6 -1
- package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.d.ts +5 -1
- package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.js +58 -28
- package/src/executors/module-federation-dev-server/schema.json +25 -3
- package/src/generators/application/application.js +17 -4
- package/src/generators/application/files/base-webpack/webpack.config.js__tmpl__ +3 -3
- package/src/generators/application/lib/add-e2e.js +7 -6
- package/src/generators/application/lib/normalize-options.js +31 -4
- package/src/generators/application/schema.d.ts +3 -0
- package/src/generators/application/schema.json +2 -2
- package/src/generators/component/files/__fileName__.tsx__tmpl__ +3 -7
- package/src/generators/component/schema.d.ts +1 -1
- package/src/generators/component/schema.json +1 -1
- package/src/generators/hook/schema.d.ts +1 -1
- package/src/generators/hook/schema.json +2 -2
- package/src/generators/host/host.js +11 -0
- package/src/generators/host/schema.json +2 -2
- package/src/generators/library/lib/add-rollup-build-target.js +65 -28
- package/src/generators/redux/schema.d.ts +1 -1
- package/src/generators/redux/schema.json +1 -1
- package/src/generators/remote/lib/update-host-with-remote.js +1 -10
- package/src/generators/remote/remote.js +9 -0
- package/src/generators/remote/schema.json +2 -2
- package/src/generators/setup-tailwind/lib/add-tailwind-style-imports.js +7 -15
- package/src/generators/storybook-configuration/schema.json +3 -3
- package/src/migrations/{update-15-6-3/webpack-config-setup.d.ts → update-18-1-1/fix-target-defaults-inputs.d.ts} +1 -1
- package/src/migrations/update-18-1-1/fix-target-defaults-inputs.js +53 -0
- package/src/module-federation/with-module-federation.js +5 -0
- package/src/utils/add-mf-env-to-inputs.js +4 -1
- package/src/utils/ct-utils.js +1 -1
- package/src/utils/versions.d.ts +11 -11
- package/src/utils/versions.js +11 -11
- package/webpack-plugin.d.ts +1 -0
- package/webpack-plugin.js +5 -0
- package/src/migrations/update-15-3-0/install-webpack-rollup-dependencies.d.ts +0 -3
- package/src/migrations/update-15-3-0/install-webpack-rollup-dependencies.js +0 -37
- package/src/migrations/update-15-3-0/update-rollup-executor.d.ts +0 -3
- package/src/migrations/update-15-3-0/update-rollup-executor.js +0 -15
- package/src/migrations/update-15-6-3/webpack-config-setup.js +0 -103
|
@@ -7,9 +7,12 @@ const file_server_impl_1 = require("@nx/web/src/executors/file-server/file-serve
|
|
|
7
7
|
const module_federation_1 = require("@nx/webpack/src/utils/module-federation");
|
|
8
8
|
const async_iterable_1 = require("@nx/devkit/src/utils/async-iterable");
|
|
9
9
|
const wait_for_port_open_1 = require("@nx/web/src/utils/wait-for-port-open");
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
const cache_directory_1 = require("nx/src/utils/cache-directory");
|
|
11
|
+
const node_child_process_1 = require("node:child_process");
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
13
|
+
const node_fs_1 = require("node:fs");
|
|
12
14
|
const fs_1 = require("fs");
|
|
15
|
+
const path_1 = require("path");
|
|
13
16
|
function getBuildOptions(buildTarget, context) {
|
|
14
17
|
const target = (0, devkit_1.parseTargetString)(buildTarget, context);
|
|
15
18
|
const buildOptions = (0, devkit_1.readTargetOptions)(target, context);
|
|
@@ -31,10 +34,10 @@ function startStaticRemotesFileServer(staticRemotesConfig, context, options) {
|
|
|
31
34
|
}
|
|
32
35
|
}
|
|
33
36
|
if (shouldMoveToCommonLocation) {
|
|
34
|
-
commonOutputDirectory = (0,
|
|
37
|
+
commonOutputDirectory = (0, node_path_1.join)(devkit_1.workspaceRoot, 'tmp/static-remotes');
|
|
35
38
|
for (const app of staticRemotesConfig.remotes) {
|
|
36
39
|
const remoteConfig = staticRemotesConfig.config[app];
|
|
37
|
-
(0,
|
|
40
|
+
(0, node_fs_1.cpSync)(remoteConfig.outputPath, (0, node_path_1.join)(commonOutputDirectory, remoteConfig.urlSegment), {
|
|
38
41
|
force: true,
|
|
39
42
|
recursive: true,
|
|
40
43
|
});
|
|
@@ -55,27 +58,34 @@ function startStaticRemotesFileServer(staticRemotesConfig, context, options) {
|
|
|
55
58
|
}, context);
|
|
56
59
|
return staticRemotesIter;
|
|
57
60
|
}
|
|
58
|
-
async function
|
|
59
|
-
const
|
|
60
|
-
for (const app of remotes
|
|
61
|
-
const remoteProjectServeTarget = context.projectGraph.nodes[app].data.targets[
|
|
61
|
+
async function startRemotes(remotes, context, options, target = 'serve') {
|
|
62
|
+
const remoteIters = [];
|
|
63
|
+
for (const app of remotes) {
|
|
64
|
+
const remoteProjectServeTarget = context.projectGraph.nodes[app].data.targets[target];
|
|
62
65
|
const isUsingModuleFederationDevServerExecutor = remoteProjectServeTarget.executor.includes('module-federation-dev-server');
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
target: 'serve',
|
|
66
|
-
configuration: context.configurationName,
|
|
67
|
-
}, {
|
|
68
|
-
watch: true,
|
|
66
|
+
const configurationOverride = options.devRemotes?.find((r) => typeof r !== 'string' && r.remoteName === app)?.configuration;
|
|
67
|
+
const defaultOverrides = {
|
|
69
68
|
...(options.host ? { host: options.host } : {}),
|
|
70
69
|
...(options.ssl ? { ssl: options.ssl } : {}),
|
|
71
70
|
...(options.sslCert ? { sslCert: options.sslCert } : {}),
|
|
72
71
|
...(options.sslKey ? { sslKey: options.sslKey } : {}),
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
};
|
|
73
|
+
const overrides = target === 'serve'
|
|
74
|
+
? {
|
|
75
|
+
watch: true,
|
|
76
|
+
...(isUsingModuleFederationDevServerExecutor
|
|
77
|
+
? { isInitialHost: false }
|
|
78
|
+
: {}),
|
|
79
|
+
...defaultOverrides,
|
|
80
|
+
}
|
|
81
|
+
: { ...defaultOverrides };
|
|
82
|
+
remoteIters.push(await (0, devkit_1.runExecutor)({
|
|
83
|
+
project: app,
|
|
84
|
+
target,
|
|
85
|
+
configuration: configurationOverride ?? context.configurationName,
|
|
86
|
+
}, overrides, context));
|
|
77
87
|
}
|
|
78
|
-
return
|
|
88
|
+
return remoteIters;
|
|
79
89
|
}
|
|
80
90
|
async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options) {
|
|
81
91
|
if (!staticRemotesConfig.remotes.length) {
|
|
@@ -88,7 +98,7 @@ async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options)
|
|
|
88
98
|
}
|
|
89
99
|
process.env.NX_MF_DEV_SERVER_STATIC_REMOTES = JSON.stringify(mappedLocationOfRemotes);
|
|
90
100
|
await new Promise((res) => {
|
|
91
|
-
const staticProcess = (0,
|
|
101
|
+
const staticProcess = (0, node_child_process_1.fork)(nxBin, [
|
|
92
102
|
'run-many',
|
|
93
103
|
`--target=build`,
|
|
94
104
|
`--projects=${staticRemotesConfig.remotes.join(',')}`,
|
|
@@ -100,9 +110,13 @@ async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options)
|
|
|
100
110
|
cwd: context.root,
|
|
101
111
|
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
|
|
102
112
|
});
|
|
113
|
+
// File to debug build failures e.g. 2024-01-01T00_00_0_0Z-build.log'
|
|
114
|
+
const remoteBuildLogFile = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log`);
|
|
115
|
+
const stdoutStream = (0, node_fs_1.createWriteStream)(remoteBuildLogFile);
|
|
103
116
|
staticProcess.stdout.on('data', (data) => {
|
|
104
117
|
const ANSII_CODE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
|
|
105
118
|
const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
|
|
119
|
+
stdoutStream.write(stdoutString);
|
|
106
120
|
if (stdoutString.includes('Successfully ran target build')) {
|
|
107
121
|
staticProcess.stdout.removeAllListeners('data');
|
|
108
122
|
devkit_1.logger.info(`NX Built ${staticRemotesConfig.remotes.length} static remotes`);
|
|
@@ -111,8 +125,9 @@ async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options)
|
|
|
111
125
|
});
|
|
112
126
|
staticProcess.stderr.on('data', (data) => devkit_1.logger.info(data.toString()));
|
|
113
127
|
staticProcess.on('exit', (code) => {
|
|
128
|
+
stdoutStream.end();
|
|
114
129
|
if (code !== 0) {
|
|
115
|
-
throw new Error(`Remote failed to start.
|
|
130
|
+
throw new Error(`Remote failed to start. A complete log can be found in: ${remoteBuildLogFile}`);
|
|
116
131
|
}
|
|
117
132
|
});
|
|
118
133
|
process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
|
|
@@ -126,8 +141,8 @@ function parseStaticRemotesConfig(staticRemotes, context) {
|
|
|
126
141
|
const config = {};
|
|
127
142
|
for (const app of staticRemotes) {
|
|
128
143
|
const outputPath = context.projectGraph.nodes[app].data.targets['build'].options.outputPath;
|
|
129
|
-
const basePath = (0,
|
|
130
|
-
const urlSegment = (0,
|
|
144
|
+
const basePath = (0, node_path_1.dirname)(outputPath);
|
|
145
|
+
const urlSegment = (0, node_path_1.basename)(outputPath);
|
|
131
146
|
config[app] = { basePath, outputPath, urlSegment };
|
|
132
147
|
}
|
|
133
148
|
return { remotes: staticRemotes, config };
|
|
@@ -149,18 +164,32 @@ async function* moduleFederationDevServer(options, context) {
|
|
|
149
164
|
: (0, dev_server_impl_1.default)(options, context);
|
|
150
165
|
const p = context.projectsConfigurations.projects[context.projectName];
|
|
151
166
|
const buildOptions = getBuildOptions(options.buildTarget, context);
|
|
167
|
+
let pathToManifestFile = (0, node_path_1.join)(context.root, p.sourceRoot, 'assets/module-federation.manifest.json');
|
|
168
|
+
if (options.pathToManifestFile) {
|
|
169
|
+
const userPathToManifestFile = (0, node_path_1.join)(context.root, options.pathToManifestFile);
|
|
170
|
+
if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
|
|
171
|
+
throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
|
|
172
|
+
}
|
|
173
|
+
else if ((0, path_1.extname)(options.pathToManifestFile) !== '.json') {
|
|
174
|
+
throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
|
|
175
|
+
}
|
|
176
|
+
pathToManifestFile = userPathToManifestFile;
|
|
177
|
+
}
|
|
152
178
|
if (!options.isInitialHost) {
|
|
153
179
|
return yield* currIter;
|
|
154
180
|
}
|
|
155
181
|
const moduleFederationConfig = (0, module_federation_1.getModuleFederationConfig)(buildOptions.tsConfig, context.root, p.root, 'react');
|
|
156
|
-
const
|
|
182
|
+
const remoteNames = options.devRemotes?.map((r) => typeof r === 'string' ? r : r.remoteName);
|
|
183
|
+
const remotes = (0, module_federation_1.getRemotes)(remoteNames, options.skipRemotes, moduleFederationConfig, {
|
|
157
184
|
projectName: context.projectName,
|
|
158
185
|
projectGraph: context.projectGraph,
|
|
159
186
|
root: context.root,
|
|
160
|
-
});
|
|
187
|
+
}, pathToManifestFile);
|
|
161
188
|
if (remotes.devRemotes.length > 0 && !initialStaticRemotesPorts) {
|
|
162
189
|
options.staticRemotesPort = options.devRemotes.reduce((portToUse, r) => {
|
|
163
|
-
const
|
|
190
|
+
const remoteName = typeof r === 'string' ? r : r.remoteName;
|
|
191
|
+
const remotePort = context.projectGraph.nodes[remoteName].data.targets['serve'].options
|
|
192
|
+
.port;
|
|
164
193
|
if (remotePort >= portToUse) {
|
|
165
194
|
return remotePort + 1;
|
|
166
195
|
}
|
|
@@ -171,11 +200,12 @@ async function* moduleFederationDevServer(options, context) {
|
|
|
171
200
|
}
|
|
172
201
|
const staticRemotesConfig = parseStaticRemotesConfig(remotes.staticRemotes, context);
|
|
173
202
|
await buildStaticRemotes(staticRemotesConfig, nxBin, context, options);
|
|
174
|
-
const devRemoteIters = await
|
|
203
|
+
const devRemoteIters = await startRemotes(remotes.devRemotes, context, options, 'serve');
|
|
204
|
+
const dynamicRemotesIters = await startRemotes(remotes.dynamicRemotes, context, options, 'serve-static');
|
|
175
205
|
const staticRemotesIter = remotes.staticRemotes.length > 0
|
|
176
206
|
? startStaticRemotesFileServer(staticRemotesConfig, context, options)
|
|
177
207
|
: undefined;
|
|
178
|
-
return yield* (0, async_iterable_1.combineAsyncIterables)(currIter, ...devRemoteIters, ...(staticRemotesIter ? [staticRemotesIter] : []), (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
|
|
208
|
+
return yield* (0, async_iterable_1.combineAsyncIterables)(currIter, ...devRemoteIters, ...dynamicRemotesIters, ...(staticRemotesIter ? [staticRemotesIter] : []), (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
|
|
179
209
|
if (!options.isInitialHost) {
|
|
180
210
|
done();
|
|
181
211
|
return;
|
|
@@ -9,7 +9,24 @@
|
|
|
9
9
|
"devRemotes": {
|
|
10
10
|
"type": "array",
|
|
11
11
|
"items": {
|
|
12
|
-
"
|
|
12
|
+
"oneOf": [
|
|
13
|
+
{
|
|
14
|
+
"type": "string"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": {
|
|
19
|
+
"remoteName": {
|
|
20
|
+
"type": "string"
|
|
21
|
+
},
|
|
22
|
+
"configuration": {
|
|
23
|
+
"type": "string"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": ["remoteName"],
|
|
27
|
+
"additionalProperties": false
|
|
28
|
+
}
|
|
29
|
+
]
|
|
13
30
|
},
|
|
14
31
|
"description": "List of remote applications to run in development mode (i.e. using serve target).",
|
|
15
32
|
"x-priority": "important"
|
|
@@ -19,7 +36,7 @@
|
|
|
19
36
|
"items": {
|
|
20
37
|
"type": "string"
|
|
21
38
|
},
|
|
22
|
-
"description": "List of remote applications to not automatically serve, either statically or in development mode. This will not remove the remotes from the `module-federation.config` file, and therefore the application may still try to fetch these remotes.\nThis option is useful
|
|
39
|
+
"description": "List of remote applications to not automatically serve, either statically or in development mode. This will not remove the remotes from the `module-federation.config` file, and therefore the application may still try to fetch these remotes.\nThis option is useful if you have other means for serving the `remote` application(s).\n**NOTE:** Remotes that are not in the workspace will be skipped automatically.",
|
|
23
40
|
"x-priority": "important"
|
|
24
41
|
},
|
|
25
42
|
"buildTarget": {
|
|
@@ -109,6 +126,11 @@
|
|
|
109
126
|
"staticRemotesPort": {
|
|
110
127
|
"type": "number",
|
|
111
128
|
"description": "The port at which to serve the file-server for the static remotes."
|
|
129
|
+
},
|
|
130
|
+
"pathToManifestFile": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"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."
|
|
112
133
|
}
|
|
113
|
-
}
|
|
134
|
+
},
|
|
135
|
+
"examplesFile": "../../../docs/module-federation-dev-server-examples.md"
|
|
114
136
|
}
|
|
@@ -62,7 +62,6 @@ async function applicationGenerator(host, schema) {
|
|
|
62
62
|
exports.applicationGenerator = applicationGenerator;
|
|
63
63
|
async function applicationGeneratorInternal(host, schema) {
|
|
64
64
|
const tasks = [];
|
|
65
|
-
console.log('Well hello Katerina!');
|
|
66
65
|
const options = await (0, normalize_options_1.normalizeOptions)(host, schema);
|
|
67
66
|
(0, show_possible_warnings_1.showPossibleWarnings)(host, options);
|
|
68
67
|
const jsInitTask = await (0, js_1.initGenerator)(host, {
|
|
@@ -76,6 +75,20 @@ async function applicationGeneratorInternal(host, schema) {
|
|
|
76
75
|
skipFormat: true,
|
|
77
76
|
});
|
|
78
77
|
tasks.push(initTask);
|
|
78
|
+
if (!options.addPlugin) {
|
|
79
|
+
const nxJson = (0, devkit_1.readNxJson)(host);
|
|
80
|
+
nxJson.targetDefaults ??= {};
|
|
81
|
+
if (!Object.keys(nxJson.targetDefaults).includes('build')) {
|
|
82
|
+
nxJson.targetDefaults.build = {
|
|
83
|
+
cache: true,
|
|
84
|
+
dependsOn: ['^build'],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
else if (!nxJson.targetDefaults.build.dependsOn) {
|
|
88
|
+
nxJson.targetDefaults.build.dependsOn = ['^build'];
|
|
89
|
+
}
|
|
90
|
+
(0, devkit_1.updateNxJson)(host, nxJson);
|
|
91
|
+
}
|
|
79
92
|
if (options.bundler === 'webpack') {
|
|
80
93
|
const { webpackInitGenerator } = (0, devkit_1.ensurePackage)('@nx/webpack', versions_1.nxVersion);
|
|
81
94
|
const webpackInitTask = await webpackInitGenerator(host, {
|
|
@@ -144,7 +157,7 @@ async function applicationGeneratorInternal(host, schema) {
|
|
|
144
157
|
tsConfig: (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'tsconfig.app.json'),
|
|
145
158
|
target: 'web',
|
|
146
159
|
newProject: true,
|
|
147
|
-
|
|
160
|
+
framework: 'react',
|
|
148
161
|
});
|
|
149
162
|
tasks.push(rspackTask);
|
|
150
163
|
}
|
|
@@ -202,8 +215,8 @@ async function applicationGeneratorInternal(host, schema) {
|
|
|
202
215
|
devkit_1.logger.warn(`${chalk.bold('styled-jsx')} is not supported by ${chalk.bold('Rspack')}. We've added ${chalk.bold('babel-loader')} to your project, but using babel will slow down your build.`);
|
|
203
216
|
tasks.push((0, devkit_1.addDependenciesToPackageJson)(host, {}, { 'babel-loader': versions_1.babelLoaderVersion }));
|
|
204
217
|
host.write((0, devkit_1.joinPathFragments)(options.appProjectRoot, 'rspack.config.js'), (0, devkit_1.stripIndents) `
|
|
205
|
-
const { composePlugins, withNx,
|
|
206
|
-
module.exports = composePlugins(withNx(),
|
|
218
|
+
const { composePlugins, withNx, withReact } = require('@nx/rspack');
|
|
219
|
+
module.exports = composePlugins(withNx(), withReact(), (config) => {
|
|
207
220
|
config.module.rules.push({
|
|
208
221
|
test: /\\.[jt]sx$/i,
|
|
209
222
|
use: [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<% if (webpackPluginOptions) { %>
|
|
2
|
-
const {
|
|
3
|
-
const { NxReactWebpackPlugin } = require('@nx/react');
|
|
2
|
+
const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
|
|
3
|
+
const { NxReactWebpackPlugin } = require('@nx/react/webpack-plugin');
|
|
4
4
|
const { join } = require('path');
|
|
5
5
|
|
|
6
6
|
module.exports = {
|
|
@@ -11,7 +11,7 @@ module.exports = {
|
|
|
11
11
|
port: 4200
|
|
12
12
|
},
|
|
13
13
|
plugins: [
|
|
14
|
-
new
|
|
14
|
+
new NxAppWebpackPlugin({
|
|
15
15
|
tsConfig: '<%= webpackPluginOptions.tsConfig %>',
|
|
16
16
|
compiler: '<%= webpackPluginOptions.compiler %>',
|
|
17
17
|
main: '<%= webpackPluginOptions.main %>',
|
|
@@ -12,9 +12,10 @@ async function addE2e(tree, options) {
|
|
|
12
12
|
const hasNxBuildPlugin = (options.bundler === 'webpack' && (0, has_webpack_plugin_1.hasWebpackPlugin)(tree)) ||
|
|
13
13
|
(options.bundler === 'vite' && (0, has_vite_plugin_1.hasVitePlugin)(tree));
|
|
14
14
|
if (!hasNxBuildPlugin) {
|
|
15
|
-
(0, web_1.webStaticServeGenerator)(tree, {
|
|
15
|
+
await (0, web_1.webStaticServeGenerator)(tree, {
|
|
16
16
|
buildTarget: `${options.projectName}:build`,
|
|
17
17
|
targetName: 'serve-static',
|
|
18
|
+
spa: true,
|
|
18
19
|
});
|
|
19
20
|
}
|
|
20
21
|
const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/cypress', versions_1.nxVersion);
|
|
@@ -33,13 +34,13 @@ async function addE2e(tree, options) {
|
|
|
33
34
|
// the name and root are already normalized, instruct the generator to use them as is
|
|
34
35
|
bundler: options.bundler === 'rspack' ? 'webpack' : options.bundler,
|
|
35
36
|
skipFormat: true,
|
|
36
|
-
devServerTarget: `${options.projectName}
|
|
37
|
-
baseUrl:
|
|
37
|
+
devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`,
|
|
38
|
+
baseUrl: options.e2eWebServerAddress,
|
|
38
39
|
jsx: true,
|
|
39
40
|
rootProject: options.rootProject,
|
|
40
41
|
webServerCommands: hasNxBuildPlugin
|
|
41
42
|
? {
|
|
42
|
-
default: `nx run ${options.projectName}
|
|
43
|
+
default: `nx run ${options.projectName}:${options.e2eWebServerTarget}`,
|
|
43
44
|
production: `nx run ${options.projectName}:preview`,
|
|
44
45
|
}
|
|
45
46
|
: undefined,
|
|
@@ -65,8 +66,8 @@ async function addE2e(tree, options) {
|
|
|
65
66
|
js: false,
|
|
66
67
|
linter: options.linter,
|
|
67
68
|
setParserOptionsProject: options.setParserOptionsProject,
|
|
68
|
-
webServerCommand: `${(0, devkit_1.getPackageManagerCommand)().exec} nx
|
|
69
|
-
webServerAddress:
|
|
69
|
+
webServerCommand: `${(0, devkit_1.getPackageManagerCommand)().exec} nx ${options.e2eWebServerTarget} ${options.name}`,
|
|
70
|
+
webServerAddress: options.e2eWebServerAddress,
|
|
70
71
|
rootProject: options.rootProject,
|
|
71
72
|
addPlugin: options.addPlugin,
|
|
72
73
|
});
|
|
@@ -32,8 +32,35 @@ async function normalizeOptions(host, options, callingGenerator = '@nx/react:app
|
|
|
32
32
|
options.addPlugin ??= addPlugin;
|
|
33
33
|
options.rootProject = appProjectRoot === '.';
|
|
34
34
|
options.projectNameAndRootFormat = projectNameAndRootFormat;
|
|
35
|
+
let e2eWebServerTarget = 'serve';
|
|
36
|
+
if (options.addPlugin) {
|
|
37
|
+
if (nxJson.plugins) {
|
|
38
|
+
for (const plugin of nxJson.plugins) {
|
|
39
|
+
if (options.bundler === 'vite' &&
|
|
40
|
+
typeof plugin === 'object' &&
|
|
41
|
+
plugin.plugin === '@nx/vite/plugin' &&
|
|
42
|
+
plugin.options.serveTargetName) {
|
|
43
|
+
e2eWebServerTarget = plugin.options
|
|
44
|
+
.serveTargetName;
|
|
45
|
+
}
|
|
46
|
+
else if (options.bundler === 'webpack' &&
|
|
47
|
+
typeof plugin === 'object' &&
|
|
48
|
+
plugin.plugin === '@nx/webpack/plugin' &&
|
|
49
|
+
plugin.options.serveTargetName) {
|
|
50
|
+
e2eWebServerTarget = plugin.options
|
|
51
|
+
.serveTargetName;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
let e2ePort = options.devServerPort ?? 4200;
|
|
57
|
+
if (nxJson.targetDefaults?.[e2eWebServerTarget] &&
|
|
58
|
+
nxJson.targetDefaults?.[e2eWebServerTarget].options?.port) {
|
|
59
|
+
e2ePort = nxJson.targetDefaults?.[e2eWebServerTarget].options?.port;
|
|
60
|
+
}
|
|
35
61
|
const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
|
36
62
|
const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
|
63
|
+
const e2eWebServerAddress = `http://localhost:${e2ePort}`;
|
|
37
64
|
const parsedTags = options.tags
|
|
38
65
|
? options.tags.split(',').map((s) => s.trim())
|
|
39
66
|
: [];
|
|
@@ -42,9 +69,6 @@ async function normalizeOptions(host, options, callingGenerator = '@nx/react:app
|
|
|
42
69
|
? null
|
|
43
70
|
: options.style;
|
|
44
71
|
(0, assertion_1.assertValidStyle)(options.style);
|
|
45
|
-
if (options.bundler === 'vite' && options.unitTestRunner !== 'none') {
|
|
46
|
-
options.unitTestRunner = 'vitest';
|
|
47
|
-
}
|
|
48
72
|
const normalized = {
|
|
49
73
|
...options,
|
|
50
74
|
name: (0, devkit_1.names)(options.name).fileName,
|
|
@@ -52,6 +76,9 @@ async function normalizeOptions(host, options, callingGenerator = '@nx/react:app
|
|
|
52
76
|
appProjectRoot,
|
|
53
77
|
e2eProjectName,
|
|
54
78
|
e2eProjectRoot,
|
|
79
|
+
e2eWebServerAddress,
|
|
80
|
+
e2eWebServerTarget,
|
|
81
|
+
e2ePort,
|
|
55
82
|
parsedTags,
|
|
56
83
|
fileName,
|
|
57
84
|
styledModule,
|
|
@@ -63,7 +90,7 @@ async function normalizeOptions(host, options, callingGenerator = '@nx/react:app
|
|
|
63
90
|
normalized.compiler = normalized.compiler ?? 'babel';
|
|
64
91
|
normalized.bundler = normalized.bundler ?? 'webpack';
|
|
65
92
|
normalized.unitTestRunner = normalized.unitTestRunner ?? 'jest';
|
|
66
|
-
normalized.e2eTestRunner = normalized.e2eTestRunner ?? '
|
|
93
|
+
normalized.e2eTestRunner = normalized.e2eTestRunner ?? 'playwright';
|
|
67
94
|
normalized.inSourceTests = normalized.minimal || normalized.inSourceTests;
|
|
68
95
|
normalized.devServerPort ??= (0, find_free_port_1.findFreePort)(host);
|
|
69
96
|
normalized.minimal = normalized.minimal ?? false;
|
|
@@ -36,6 +36,9 @@ export interface NormalizedSchema<T extends Schema = Schema> extends T {
|
|
|
36
36
|
appProjectRoot: string;
|
|
37
37
|
e2eProjectName: string;
|
|
38
38
|
e2eProjectRoot: string;
|
|
39
|
+
e2eWebServerAddress: string;
|
|
40
|
+
e2eWebServerTarget: string;
|
|
41
|
+
e2ePort: number;
|
|
39
42
|
parsedTags: string[];
|
|
40
43
|
fileName: string;
|
|
41
44
|
styledModule: null | SupportedStyles;
|
|
@@ -122,10 +122,10 @@
|
|
|
122
122
|
},
|
|
123
123
|
"e2eTestRunner": {
|
|
124
124
|
"type": "string",
|
|
125
|
-
"enum": ["
|
|
125
|
+
"enum": ["playwright", "cypress", "none"],
|
|
126
126
|
"description": "Test runner to use for end to end (E2E) tests.",
|
|
127
127
|
"x-prompt": "Which E2E test runner would you like to use?",
|
|
128
|
-
"default": "
|
|
128
|
+
"default": "playwright"
|
|
129
129
|
},
|
|
130
130
|
"tags": {
|
|
131
131
|
"type": "string",
|
|
@@ -23,10 +23,6 @@ import { Route, Link } from 'react-router-dom';
|
|
|
23
23
|
var extras = '';
|
|
24
24
|
} %>
|
|
25
25
|
|
|
26
|
-
/* eslint-disable-next-line */
|
|
27
|
-
export interface <%= className %>Props {
|
|
28
|
-
}
|
|
29
|
-
|
|
30
26
|
<% if (styledModule && styledModule !== 'styled-jsx') { %>
|
|
31
27
|
const Styled<%= className %> = styled.div`
|
|
32
28
|
color: pink;
|
|
@@ -34,7 +30,7 @@ const Styled<%= className %> = styled.div`
|
|
|
34
30
|
<% }%>
|
|
35
31
|
<% if(!isNextPage) { %>
|
|
36
32
|
<% if (classComponent) { %>
|
|
37
|
-
export class <%= className %> extends Component
|
|
33
|
+
export class <%= className %> extends Component<{}> {
|
|
38
34
|
override render() {
|
|
39
35
|
return (
|
|
40
36
|
<<%= wrapper %><%- extras %>>
|
|
@@ -51,7 +47,7 @@ const Styled<%= className %> = styled.div`
|
|
|
51
47
|
}
|
|
52
48
|
}
|
|
53
49
|
<% } else { %>
|
|
54
|
-
export function <%= className %>(
|
|
50
|
+
export function <%= className %>() {
|
|
55
51
|
return (
|
|
56
52
|
<<%= wrapper %><%- extras %>>
|
|
57
53
|
<% if (styledModule === 'styled-jsx') { %><style jsx>{`div { color: pink; }`}</style><% } %>
|
|
@@ -69,7 +65,7 @@ const Styled<%= className %> = styled.div`
|
|
|
69
65
|
|
|
70
66
|
export default <%= className %>;
|
|
71
67
|
<% } else { %>
|
|
72
|
-
export default function <%= className %>(
|
|
68
|
+
export default function <%= className %>() {
|
|
73
69
|
return (
|
|
74
70
|
<<%= wrapper %><%- extras %>>
|
|
75
71
|
<% if (styledModule === 'styled-jsx') { %><style jsx>{`div { color: pink; }`}</style><% } %>
|
|
@@ -3,7 +3,7 @@ import { SupportedStyles } from '../../../typings/style';
|
|
|
3
3
|
export interface Schema {
|
|
4
4
|
name: string;
|
|
5
5
|
/**
|
|
6
|
-
* @deprecated Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx
|
|
6
|
+
* @deprecated Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20.
|
|
7
7
|
*/
|
|
8
8
|
project?: string;
|
|
9
9
|
style: SupportedStyles;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"$default": {
|
|
14
14
|
"$source": "projectName"
|
|
15
15
|
},
|
|
16
|
-
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx
|
|
16
|
+
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
|
|
17
17
|
},
|
|
18
18
|
"name": {
|
|
19
19
|
"type": "string",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export interface Schema {
|
|
2
2
|
name: string;
|
|
3
3
|
/**
|
|
4
|
-
* @deprecated Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx
|
|
4
|
+
* @deprecated Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20.
|
|
5
5
|
*/
|
|
6
6
|
project: string;
|
|
7
7
|
skipTests?: boolean;
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"$default": {
|
|
20
20
|
"$source": "projectName"
|
|
21
21
|
},
|
|
22
|
-
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx
|
|
22
|
+
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v20."
|
|
23
23
|
},
|
|
24
24
|
"name": {
|
|
25
25
|
"type": "string",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"type": "boolean",
|
|
57
57
|
"description": "Create hook at the source root rather than its own directory.",
|
|
58
58
|
"default": false,
|
|
59
|
-
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. It will be removed in Nx
|
|
59
|
+
"x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. It will be removed in Nx v20."
|
|
60
60
|
},
|
|
61
61
|
"export": {
|
|
62
62
|
"type": "boolean",
|
|
@@ -12,6 +12,7 @@ const normalize_remote_1 = require("./lib/normalize-remote");
|
|
|
12
12
|
const setup_ssr_for_host_1 = require("./lib/setup-ssr-for-host");
|
|
13
13
|
const update_module_federation_e2e_project_1 = require("./lib/update-module-federation-e2e-project");
|
|
14
14
|
const add_mf_env_to_inputs_1 = require("../../utils/add-mf-env-to-inputs");
|
|
15
|
+
const js_1 = require("@nx/js");
|
|
15
16
|
async function hostGenerator(host, schema) {
|
|
16
17
|
return hostGeneratorInternal(host, {
|
|
17
18
|
projectNameAndRootFormat: 'derived',
|
|
@@ -31,6 +32,16 @@ async function hostGeneratorInternal(host, schema) {
|
|
|
31
32
|
// TODO(colum): remove when MF works with Crystal
|
|
32
33
|
addPlugin: false,
|
|
33
34
|
};
|
|
35
|
+
// Check to see if remotes are provided and also check if --dynamic is provided
|
|
36
|
+
// if both are check that the remotes are valid names else throw an error.
|
|
37
|
+
if (options.dynamic && options.remotes?.length > 0) {
|
|
38
|
+
options.remotes.forEach((remote) => {
|
|
39
|
+
const isValidRemote = (0, js_1.isValidVariable)(remote);
|
|
40
|
+
if (!isValidRemote.isValid) {
|
|
41
|
+
throw new Error(`Invalid remote name provided: ${remote}. ${isValidRemote.message}`);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
34
45
|
const initTask = await (0, application_1.default)(host, {
|
|
35
46
|
...options,
|
|
36
47
|
// The target use-case is loading remotes as child routes, thus always enable routing.
|
|
@@ -103,10 +103,10 @@
|
|
|
103
103
|
},
|
|
104
104
|
"e2eTestRunner": {
|
|
105
105
|
"type": "string",
|
|
106
|
-
"enum": ["
|
|
106
|
+
"enum": ["playwright", "cypress", "none"],
|
|
107
107
|
"description": "Test runner to use for end to end (E2E) tests.",
|
|
108
108
|
"x-prompt": "Which E2E test runner would you like to use?",
|
|
109
|
-
"default": "
|
|
109
|
+
"default": "playwright"
|
|
110
110
|
},
|
|
111
111
|
"tags": {
|
|
112
112
|
"type": "string",
|