@nx/rspack 0.0.0-pr-28218-5048fd1

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.
Files changed (133) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +117 -0
  3. package/executors.json +35 -0
  4. package/generators.json +31 -0
  5. package/migrations.json +98 -0
  6. package/module-federation.d.ts +1 -0
  7. package/module-federation.js +4 -0
  8. package/package.json +49 -0
  9. package/plugin.d.ts +2 -0
  10. package/plugin.js +6 -0
  11. package/src/executors/dev-server/dev-server.impl.d.ts +6 -0
  12. package/src/executors/dev-server/dev-server.impl.js +50 -0
  13. package/src/executors/dev-server/lib/get-dev-server-config.d.ts +4 -0
  14. package/src/executors/dev-server/lib/get-dev-server-config.js +69 -0
  15. package/src/executors/dev-server/lib/serve-path.d.ts +3 -0
  16. package/src/executors/dev-server/lib/serve-path.js +44 -0
  17. package/src/executors/dev-server/schema.d.ts +12 -0
  18. package/src/executors/dev-server/schema.json +45 -0
  19. package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.d.ts +6 -0
  20. package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.js +177 -0
  21. package/src/executors/module-federation-dev-server/schema.d.ts +18 -0
  22. package/src/executors/module-federation-dev-server/schema.json +98 -0
  23. package/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.d.ts +21 -0
  24. package/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.js +214 -0
  25. package/src/executors/module-federation-ssr-dev-server/schema.json +79 -0
  26. package/src/executors/module-federation-static-server/module-federation-static-server.impl.d.ts +12 -0
  27. package/src/executors/module-federation-static-server/module-federation-static-server.impl.js +244 -0
  28. package/src/executors/module-federation-static-server/schema.d.ts +3 -0
  29. package/src/executors/module-federation-static-server/schema.json +14 -0
  30. package/src/executors/rspack/rspack.impl.d.ts +6 -0
  31. package/src/executors/rspack/rspack.impl.js +118 -0
  32. package/src/executors/rspack/schema.d.ts +34 -0
  33. package/src/executors/rspack/schema.json +177 -0
  34. package/src/executors/ssr-dev-server/lib/wait-until-server-is-listening.d.ts +1 -0
  35. package/src/executors/ssr-dev-server/lib/wait-until-server-is-listening.js +39 -0
  36. package/src/executors/ssr-dev-server/schema.d.ts +11 -0
  37. package/src/executors/ssr-dev-server/schema.json +36 -0
  38. package/src/executors/ssr-dev-server/ssr-dev-server.impl.d.ts +8 -0
  39. package/src/executors/ssr-dev-server/ssr-dev-server.impl.js +38 -0
  40. package/src/generators/application/application.d.ts +3 -0
  41. package/src/generators/application/application.js +90 -0
  42. package/src/generators/application/lib/create-ts-config.d.ts +3 -0
  43. package/src/generators/application/lib/create-ts-config.js +49 -0
  44. package/src/generators/application/lib/normalize-options.d.ts +5 -0
  45. package/src/generators/application/lib/normalize-options.js +42 -0
  46. package/src/generators/application/schema.d.ts +16 -0
  47. package/src/generators/application/schema.json +98 -0
  48. package/src/generators/configuration/configuration.d.ts +4 -0
  49. package/src/generators/configuration/configuration.js +79 -0
  50. package/src/generators/configuration/schema.d.ts +12 -0
  51. package/src/generators/configuration/schema.json +73 -0
  52. package/src/generators/init/init.d.ts +5 -0
  53. package/src/generators/init/init.js +71 -0
  54. package/src/generators/init/schema.d.ts +11 -0
  55. package/src/generators/init/schema.json +31 -0
  56. package/src/generators/preset/preset.d.ts +3 -0
  57. package/src/generators/preset/preset.js +34 -0
  58. package/src/generators/preset/schema.d.ts +18 -0
  59. package/src/generators/preset/schema.json +71 -0
  60. package/src/index.d.ts +6 -0
  61. package/src/index.js +9 -0
  62. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.d.ts +2 -0
  63. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +9 -0
  64. package/src/plugins/generate-package-json-plugin.d.ts +12 -0
  65. package/src/plugins/generate-package-json-plugin.js +46 -0
  66. package/src/plugins/plugin.d.ts +9 -0
  67. package/src/plugins/plugin.js +149 -0
  68. package/src/utils/config.d.ts +17 -0
  69. package/src/utils/config.js +22 -0
  70. package/src/utils/create-compiler.d.ts +7 -0
  71. package/src/utils/create-compiler.js +33 -0
  72. package/src/utils/generator-utils.d.ts +34 -0
  73. package/src/utils/generator-utils.js +444 -0
  74. package/src/utils/get-copy-patterns.d.ts +9 -0
  75. package/src/utils/get-copy-patterns.js +22 -0
  76. package/src/utils/jest-utils.d.ts +1 -0
  77. package/src/utils/jest-utils.js +8 -0
  78. package/src/utils/mode-utils.d.ts +2 -0
  79. package/src/utils/mode-utils.js +6 -0
  80. package/src/utils/model.d.ts +6 -0
  81. package/src/utils/model.js +2 -0
  82. package/src/utils/module-federation/build-static.remotes.d.ts +4 -0
  83. package/src/utils/module-federation/build-static.remotes.js +69 -0
  84. package/src/utils/module-federation/dependencies.d.ts +6 -0
  85. package/src/utils/module-federation/dependencies.js +56 -0
  86. package/src/utils/module-federation/get-remotes-for-host.d.ts +16 -0
  87. package/src/utils/module-federation/get-remotes-for-host.js +99 -0
  88. package/src/utils/module-federation/index.d.ts +6 -0
  89. package/src/utils/module-federation/index.js +9 -0
  90. package/src/utils/module-federation/models/index.d.ts +47 -0
  91. package/src/utils/module-federation/models/index.js +2 -0
  92. package/src/utils/module-federation/package-json.d.ts +8 -0
  93. package/src/utils/module-federation/package-json.js +12 -0
  94. package/src/utils/module-federation/parse-static-remotes-config.d.ts +13 -0
  95. package/src/utils/module-federation/parse-static-remotes-config.js +34 -0
  96. package/src/utils/module-federation/plugins/runtime-library-control.plugin.d.ts +3 -0
  97. package/src/utils/module-federation/plugins/runtime-library-control.plugin.js +54 -0
  98. package/src/utils/module-federation/public-api.d.ts +8 -0
  99. package/src/utils/module-federation/public-api.js +20 -0
  100. package/src/utils/module-federation/remotes.d.ts +19 -0
  101. package/src/utils/module-federation/remotes.js +77 -0
  102. package/src/utils/module-federation/secondary-entry-points.d.ts +12 -0
  103. package/src/utils/module-federation/secondary-entry-points.js +104 -0
  104. package/src/utils/module-federation/share.d.ts +48 -0
  105. package/src/utils/module-federation/share.js +235 -0
  106. package/src/utils/module-federation/start-remote-proxies.d.ts +5 -0
  107. package/src/utils/module-federation/start-remote-proxies.js +45 -0
  108. package/src/utils/module-federation/start-ssr-remote-proxies.d.ts +5 -0
  109. package/src/utils/module-federation/start-ssr-remote-proxies.js +59 -0
  110. package/src/utils/module-federation/typescript.d.ts +4 -0
  111. package/src/utils/module-federation/typescript.js +53 -0
  112. package/src/utils/module-federation/with-module-federation/package-json.d.ts +8 -0
  113. package/src/utils/module-federation/with-module-federation/package-json.js +12 -0
  114. package/src/utils/module-federation/with-module-federation/utils.d.ts +12 -0
  115. package/src/utils/module-federation/with-module-federation/utils.js +76 -0
  116. package/src/utils/module-federation/with-module-federation/with-module-federation-ssr.d.ts +3 -0
  117. package/src/utils/module-federation/with-module-federation/with-module-federation-ssr.js +55 -0
  118. package/src/utils/module-federation/with-module-federation/with-module-federation.d.ts +8 -0
  119. package/src/utils/module-federation/with-module-federation/with-module-federation.js +70 -0
  120. package/src/utils/normalize-assets.d.ts +1 -0
  121. package/src/utils/normalize-assets.js +42 -0
  122. package/src/utils/read-rspack-options.d.ts +10 -0
  123. package/src/utils/read-rspack-options.js +37 -0
  124. package/src/utils/resolve-user-defined-rspack-config.d.ts +3 -0
  125. package/src/utils/resolve-user-defined-rspack-config.js +38 -0
  126. package/src/utils/versions.d.ts +21 -0
  127. package/src/utils/versions.js +24 -0
  128. package/src/utils/with-nx.d.ts +3 -0
  129. package/src/utils/with-nx.js +187 -0
  130. package/src/utils/with-react.d.ts +3 -0
  131. package/src/utils/with-react.js +69 -0
  132. package/src/utils/with-web.d.ts +9 -0
  133. package/src/utils/with-web.js +106 -0
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startProxies = startProxies;
4
+ exports.default = moduleFederationStaticServer;
5
+ const tslib_1 = require("tslib");
6
+ const devkit_1 = require("@nx/devkit");
7
+ const async_iterable_1 = require("@nx/devkit/src/utils/async-iterable");
8
+ const file_server_impl_1 = tslib_1.__importDefault(require("@nx/web/src/executors/file-server/file-server.impl"));
9
+ const wait_for_port_open_1 = require("@nx/web/src/utils/wait-for-port-open");
10
+ const child_process_1 = require("child_process");
11
+ const fs_1 = require("fs");
12
+ const path_1 = require("path");
13
+ const module_federation_1 = require("../../utils/module-federation");
14
+ const build_static_remotes_1 = require("../../utils/module-federation/build-static.remotes");
15
+ const parse_static_remotes_config_1 = require("../../utils/module-federation/parse-static-remotes-config");
16
+ function getBuildAndServeOptionsFromServeTarget(serveTarget, context) {
17
+ const target = (0, devkit_1.parseTargetString)(serveTarget, context);
18
+ const serveOptions = (0, devkit_1.readTargetOptions)(target, context);
19
+ const buildTarget = (0, devkit_1.parseTargetString)(serveOptions.buildTarget, context);
20
+ const buildOptions = (0, devkit_1.readTargetOptions)(buildTarget, context);
21
+ let pathToManifestFile = (0, path_1.join)(context.root, context.projectGraph.nodes[context.projectName].data.sourceRoot, 'assets/module-federation.manifest.json');
22
+ if (serveOptions.pathToManifestFile) {
23
+ const userPathToManifestFile = (0, path_1.join)(context.root, serveOptions.pathToManifestFile);
24
+ if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
25
+ throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
26
+ }
27
+ else if ((0, path_1.extname)(serveOptions.pathToManifestFile) !== '.json') {
28
+ throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
29
+ }
30
+ pathToManifestFile = userPathToManifestFile;
31
+ }
32
+ return {
33
+ buildTarget,
34
+ buildOptions,
35
+ serveOptions,
36
+ pathToManifestFile,
37
+ };
38
+ }
39
+ async function buildHost(nxBin, buildTarget, context) {
40
+ await new Promise((res, rej) => {
41
+ const staticProcess = (0, child_process_1.fork)(nxBin, [
42
+ `run`,
43
+ `${buildTarget.project}:${buildTarget.target}${buildTarget.configuration
44
+ ? `:${buildTarget.configuration}`
45
+ : context.configurationName
46
+ ? `:${context.configurationName}`
47
+ : ''}`,
48
+ ], {
49
+ cwd: context.root,
50
+ stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
51
+ });
52
+ staticProcess.stdout.on('data', (data) => {
53
+ const ANSII_CODE_REGEX =
54
+ // eslint-disable-next-line no-control-regex
55
+ /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
56
+ const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
57
+ // in addition to writing into the stdout stream, also show error directly in console
58
+ // so the error is easily discoverable. 'ERROR in' is the key word to search in webpack output.
59
+ if (stdoutString.includes('ERROR in')) {
60
+ devkit_1.logger.log(stdoutString);
61
+ }
62
+ if (stdoutString.includes('Successfully ran target build')) {
63
+ staticProcess.stdout.removeAllListeners('data');
64
+ devkit_1.logger.info(`NX Built host`);
65
+ res();
66
+ }
67
+ });
68
+ staticProcess.stderr.on('data', (data) => devkit_1.logger.info(data.toString()));
69
+ staticProcess.once('exit', (code) => {
70
+ staticProcess.stdout.removeAllListeners('data');
71
+ staticProcess.stderr.removeAllListeners('data');
72
+ if (code !== 0) {
73
+ rej(`Host failed to build. See above for details.`);
74
+ }
75
+ else {
76
+ res();
77
+ }
78
+ });
79
+ process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
80
+ process.on('exit', () => staticProcess.kill('SIGTERM'));
81
+ });
82
+ }
83
+ function moveToTmpDirectory(staticRemotesConfig, hostOutputPath, hostUrlSegment) {
84
+ const commonOutputDirectory = (0, path_1.join)(devkit_1.workspaceRoot, 'tmp/static-module-federation');
85
+ for (const app of staticRemotesConfig.remotes) {
86
+ const remoteConfig = staticRemotesConfig.config[app];
87
+ (0, fs_1.cpSync)(remoteConfig.outputPath, (0, path_1.join)(commonOutputDirectory, remoteConfig.urlSegment), {
88
+ force: true,
89
+ recursive: true,
90
+ });
91
+ }
92
+ (0, fs_1.cpSync)(hostOutputPath, (0, path_1.join)(commonOutputDirectory, hostUrlSegment), {
93
+ force: true,
94
+ recursive: true,
95
+ });
96
+ const cleanup = () => {
97
+ (0, fs_1.rmSync)(commonOutputDirectory, { force: true, recursive: true });
98
+ };
99
+ process.on('SIGTERM', () => {
100
+ cleanup();
101
+ });
102
+ process.on('exit', () => {
103
+ cleanup();
104
+ });
105
+ return commonOutputDirectory;
106
+ }
107
+ function startProxies(staticRemotesConfig, hostServeOptions, mappedLocationOfHost, mappedLocationsOfRemotes, sslOptions) {
108
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
109
+ const { createProxyMiddleware } = require('http-proxy-middleware');
110
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
111
+ const express = require('express');
112
+ let sslCert;
113
+ let sslKey;
114
+ if (sslOptions && sslOptions.pathToCert && sslOptions.pathToKey) {
115
+ if ((0, fs_1.existsSync)(sslOptions.pathToCert) && (0, fs_1.existsSync)(sslOptions.pathToKey)) {
116
+ sslCert = (0, fs_1.readFileSync)(sslOptions.pathToCert);
117
+ sslKey = (0, fs_1.readFileSync)(sslOptions.pathToKey);
118
+ }
119
+ else {
120
+ devkit_1.logger.warn(`Encountered SSL options in project.json, however, the certificate files do not exist in the filesystem. Using http.`);
121
+ devkit_1.logger.warn(`Attempted to find '${sslOptions.pathToCert}' and '${sslOptions.pathToKey}'.`);
122
+ }
123
+ }
124
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
125
+ const http = require('http');
126
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
127
+ const https = require('https');
128
+ devkit_1.logger.info(`NX Starting static remotes proxies...`);
129
+ for (const app of staticRemotesConfig.remotes) {
130
+ const expressProxy = express();
131
+ expressProxy.use(createProxyMiddleware({
132
+ target: mappedLocationsOfRemotes[app],
133
+ changeOrigin: true,
134
+ secure: sslCert ? false : undefined,
135
+ }));
136
+ const proxyServer = (sslCert ? https : http)
137
+ .createServer({ cert: sslCert, key: sslKey }, expressProxy)
138
+ .listen(staticRemotesConfig.config[app].port);
139
+ process.on('SIGTERM', () => proxyServer.close());
140
+ process.on('exit', () => proxyServer.close());
141
+ }
142
+ devkit_1.logger.info(`NX Static remotes proxies started successfully`);
143
+ devkit_1.logger.info(`NX Starting static host proxy...`);
144
+ const expressProxy = express();
145
+ expressProxy.use(createProxyMiddleware({
146
+ target: mappedLocationOfHost,
147
+ changeOrigin: true,
148
+ secure: sslCert ? false : undefined,
149
+ pathRewrite: (path) => {
150
+ let pathRewrite = path;
151
+ for (const app of staticRemotesConfig.remotes) {
152
+ if (path.endsWith(app)) {
153
+ pathRewrite = '/';
154
+ break;
155
+ }
156
+ }
157
+ return pathRewrite;
158
+ },
159
+ }));
160
+ const proxyServer = (sslCert ? https : http)
161
+ .createServer({ cert: sslCert, key: sslKey }, expressProxy)
162
+ .listen(hostServeOptions.port);
163
+ process.on('SIGTERM', () => proxyServer.close());
164
+ process.on('exit', () => proxyServer.close());
165
+ devkit_1.logger.info('NX Static host proxy started successfully');
166
+ }
167
+ async function* moduleFederationStaticServer(schema, context) {
168
+ // Force Node to resolve to look for the nx binary that is inside node_modules
169
+ const nxBin = require.resolve('nx/bin/nx');
170
+ // Get the remotes from the module federation config
171
+ const p = context.projectsConfigurations.projects[context.projectName];
172
+ const options = getBuildAndServeOptionsFromServeTarget(schema.serveTarget, context);
173
+ const moduleFederationConfig = (0, module_federation_1.getModuleFederationConfig)(options.buildOptions.tsConfig, context.root, p.root, 'react');
174
+ const remotes = (0, module_federation_1.getRemotes)([], options.serveOptions.skipRemotes, moduleFederationConfig, {
175
+ projectName: context.projectName,
176
+ projectGraph: context.projectGraph,
177
+ root: context.root,
178
+ }, options.pathToManifestFile);
179
+ const staticRemotesConfig = (0, parse_static_remotes_config_1.parseStaticRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context);
180
+ options.serveOptions.staticRemotesPort ??= remotes.staticRemotePort;
181
+ const mappedLocationsOfStaticRemotes = await (0, build_static_remotes_1.buildStaticRemotes)(staticRemotesConfig, nxBin, context, options.serveOptions);
182
+ // Build the host
183
+ const hostUrlSegment = (0, path_1.basename)(options.buildOptions.outputPath);
184
+ const mappedLocationOfHost = `http${options.serveOptions.ssl ? 's' : ''}://${options.serveOptions.host}:${options.serveOptions.staticRemotesPort}/${hostUrlSegment}`;
185
+ await buildHost(nxBin, options.buildTarget, context);
186
+ // Move to a temporary directory
187
+ const commonOutputDirectory = moveToTmpDirectory(staticRemotesConfig, options.buildOptions.outputPath, hostUrlSegment);
188
+ // File Serve the temporary directory
189
+ const staticFileServerIter = (0, file_server_impl_1.default)({
190
+ cors: true,
191
+ watch: false,
192
+ staticFilePath: commonOutputDirectory,
193
+ parallel: false,
194
+ spa: false,
195
+ withDeps: false,
196
+ host: options.serveOptions.host,
197
+ port: options.serveOptions.staticRemotesPort,
198
+ ssl: options.serveOptions.ssl,
199
+ sslCert: options.serveOptions.sslCert,
200
+ sslKey: options.serveOptions.sslKey,
201
+ cacheSeconds: -1,
202
+ }, context);
203
+ // express proxy all of it
204
+ startProxies(staticRemotesConfig, options.serveOptions, mappedLocationOfHost, mappedLocationsOfStaticRemotes, options.serveOptions.ssl
205
+ ? {
206
+ pathToCert: (0, path_1.join)(devkit_1.workspaceRoot, options.serveOptions.sslCert),
207
+ pathToKey: (0, path_1.join)(devkit_1.workspaceRoot, options.serveOptions.sslKey),
208
+ }
209
+ : undefined);
210
+ return yield* (0, async_iterable_1.combineAsyncIterables)(staticFileServerIter, (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
211
+ const host = options.serveOptions.host ?? 'localhost';
212
+ const baseUrl = `http${options.serveOptions.ssl ? 's' : ''}://${host}:${options.serveOptions.port}`;
213
+ if (remotes.remotePorts.length === 0) {
214
+ const portsToWaitFor = [options.serveOptions.staticRemotesPort];
215
+ await Promise.all(portsToWaitFor.map((port) => (0, wait_for_port_open_1.waitForPortOpen)(port, {
216
+ retries: 480,
217
+ retryDelay: 2500,
218
+ host: host,
219
+ })));
220
+ devkit_1.logger.info(`NX Server ready at ${baseUrl}`);
221
+ next({ success: true, baseUrl: baseUrl });
222
+ done();
223
+ return;
224
+ }
225
+ try {
226
+ const portsToWaitFor = staticFileServerIter
227
+ ? [options.serveOptions.staticRemotesPort, ...remotes.remotePorts]
228
+ : [...remotes.remotePorts];
229
+ await Promise.all(portsToWaitFor.map((port) => (0, wait_for_port_open_1.waitForPortOpen)(port, {
230
+ retries: 480,
231
+ retryDelay: 2500,
232
+ host: host,
233
+ })));
234
+ devkit_1.logger.info(`NX Server ready at ${baseUrl}`);
235
+ next({ success: true, baseUrl: baseUrl });
236
+ }
237
+ catch (err) {
238
+ throw new Error(`Failed to start. Check above for any errors.`);
239
+ }
240
+ finally {
241
+ done();
242
+ }
243
+ }));
244
+ }
@@ -0,0 +1,3 @@
1
+ export interface ModuleFederationStaticServerSchema {
2
+ serveTarget: string;
3
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": 2,
3
+ "outputCapture": "direct-nodejs",
4
+ "title": "Module Federation Static Dev Server",
5
+ "description": "Serve a host application statically along with it's remotes.",
6
+ "cli": "nx",
7
+ "type": "object",
8
+ "properties": {
9
+ "serveTarget": {
10
+ "type": "string"
11
+ }
12
+ },
13
+ "required": ["serveTarget"]
14
+ }
@@ -0,0 +1,6 @@
1
+ import { ExecutorContext } from '@nx/devkit';
2
+ import { RspackExecutorSchema } from './schema';
3
+ export default function runExecutor(options: RspackExecutorSchema, context: ExecutorContext): AsyncGenerator<{
4
+ success: boolean;
5
+ outfile?: string;
6
+ }, void, undefined>;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = runExecutor;
4
+ const tslib_1 = require("tslib");
5
+ const devkit_1 = require("@nx/devkit");
6
+ const async_iterable_1 = require("@nx/devkit/src/utils/async-iterable");
7
+ const js_1 = require("@nx/js");
8
+ const fs_1 = require("fs");
9
+ const path = tslib_1.__importStar(require("path"));
10
+ const create_compiler_1 = require("../../utils/create-compiler");
11
+ const mode_utils_1 = require("../../utils/mode-utils");
12
+ async function* runExecutor(options, context) {
13
+ process.env.NODE_ENV ??= options.mode ?? 'production';
14
+ if ((0, mode_utils_1.isMode)(process.env.NODE_ENV)) {
15
+ options.mode = process.env.NODE_ENV;
16
+ }
17
+ if (options.typeCheck) {
18
+ await executeTypeCheck(options, context);
19
+ }
20
+ // Mimic --clean from webpack.
21
+ (0, fs_1.rmSync)(path.join(context.root, options.outputPath), {
22
+ force: true,
23
+ recursive: true,
24
+ });
25
+ const compiler = await (0, create_compiler_1.createCompiler)(options, context);
26
+ const iterable = (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
27
+ if (options.watch) {
28
+ const watcher = compiler.watch({}, async (err, stats) => {
29
+ if (err) {
30
+ devkit_1.logger.error(err);
31
+ next({ success: false });
32
+ return;
33
+ }
34
+ if (!compiler || !stats) {
35
+ devkit_1.logger.error(new Error('Compiler or stats not available'));
36
+ next({ success: false });
37
+ return;
38
+ }
39
+ const statsOptions = getStatsOptions(compiler);
40
+ const printedStats = stats.toString(statsOptions);
41
+ // Avoid extra empty line when `stats: 'none'`
42
+ if (printedStats) {
43
+ console.error(printedStats);
44
+ }
45
+ next({
46
+ success: !stats.hasErrors(),
47
+ outfile: path.resolve(context.root, options.outputPath, 'main.js'),
48
+ });
49
+ });
50
+ registerCleanupCallback(() => {
51
+ watcher.close(() => {
52
+ devkit_1.logger.info('Watcher closed');
53
+ });
54
+ });
55
+ }
56
+ else {
57
+ compiler.run(async (err, stats) => {
58
+ compiler.close(() => {
59
+ if (err) {
60
+ devkit_1.logger.error(err);
61
+ next({ success: false });
62
+ return;
63
+ }
64
+ if (!compiler || !stats) {
65
+ devkit_1.logger.error(new Error('Compiler or stats not available'));
66
+ next({ success: false });
67
+ return;
68
+ }
69
+ const statsOptions = getStatsOptions(compiler);
70
+ const printedStats = stats.toString(statsOptions);
71
+ // Avoid extra empty line when `stats: 'none'`
72
+ if (printedStats) {
73
+ console.error(printedStats);
74
+ }
75
+ next({
76
+ success: !stats.hasErrors(),
77
+ outfile: path.resolve(context.root, options.outputPath, 'main.js'),
78
+ });
79
+ done();
80
+ });
81
+ });
82
+ }
83
+ });
84
+ yield* iterable;
85
+ }
86
+ // copied from packages/esbuild/src/executors/esbuild/esbuild.impl.ts
87
+ function registerCleanupCallback(callback) {
88
+ const wrapped = () => {
89
+ callback();
90
+ process.off('SIGINT', wrapped);
91
+ process.off('SIGTERM', wrapped);
92
+ process.off('exit', wrapped);
93
+ };
94
+ process.on('SIGINT', wrapped);
95
+ process.on('SIGTERM', wrapped);
96
+ process.on('exit', wrapped);
97
+ }
98
+ async function executeTypeCheck(options, context) {
99
+ const projectConfiguration = context.projectGraph.nodes[context.projectName].data;
100
+ const result = await (0, js_1.runTypeCheck)({
101
+ workspaceRoot: path.resolve(projectConfiguration.root),
102
+ tsConfigPath: options.tsConfig,
103
+ mode: 'noEmit',
104
+ });
105
+ await (0, js_1.printDiagnostics)(result.errors, result.warnings);
106
+ if (result.errors.length > 0) {
107
+ throw new Error('Found type errors. See above.');
108
+ }
109
+ }
110
+ function getStatsOptions(compiler) {
111
+ return (0, create_compiler_1.isMultiCompiler)(compiler)
112
+ ? {
113
+ children: compiler.compilers.map((compiler) => compiler.options ? compiler.options.stats : undefined),
114
+ }
115
+ : compiler.options
116
+ ? compiler.options.stats
117
+ : undefined;
118
+ }
@@ -0,0 +1,34 @@
1
+ import type { Mode } from '@rspack/core';
2
+
3
+ export interface RspackExecutorSchema {
4
+ target: 'web' | 'node';
5
+ main: string;
6
+ index?: string;
7
+ tsConfig: string;
8
+ typeCheck?: boolean;
9
+ outputPath: string;
10
+ outputFileName?: string;
11
+ indexHtml?: string;
12
+ mode?: Mode;
13
+ watch?: boolean;
14
+ baseHref?: string;
15
+ deployUrl?: string;
16
+
17
+ rspackConfig: string;
18
+ optimization?: boolean | OptimizationOptions;
19
+ sourceMap?: boolean | string;
20
+ assets?: any[];
21
+ extractLicenses?: boolean;
22
+ fileReplacements?: FileReplacement[];
23
+ generatePackageJson?: boolean;
24
+ }
25
+
26
+ export interface FileReplacement {
27
+ replace: string;
28
+ with: string;
29
+ }
30
+
31
+ export interface OptimizationOptions {
32
+ scripts: boolean;
33
+ styles: boolean;
34
+ }
@@ -0,0 +1,177 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "version": 2,
4
+ "title": "Rspack build executor",
5
+ "description": "Run Rspack via an executor for a project.",
6
+ "type": "object",
7
+ "properties": {
8
+ "target": {
9
+ "type": "string",
10
+ "description": "The platform to target (e.g. web, node).",
11
+ "enum": ["web", "node"]
12
+ },
13
+ "main": {
14
+ "type": "string",
15
+ "description": "The main entry file."
16
+ },
17
+ "outputPath": {
18
+ "type": "string",
19
+ "description": "The output path for the bundle."
20
+ },
21
+ "outputFileName": {
22
+ "type": "string",
23
+ "description": "The main output entry file"
24
+ },
25
+ "tsConfig": {
26
+ "type": "string",
27
+ "description": "The tsconfig file to build the project."
28
+ },
29
+ "typeCheck": {
30
+ "type": "boolean",
31
+ "description": "Skip the type checking."
32
+ },
33
+ "indexHtml": {
34
+ "type": "string",
35
+ "description": "The path to the index.html file."
36
+ },
37
+ "index": {
38
+ "type": "string",
39
+ "description": "HTML File which will be contain the application.",
40
+ "x-completion-type": "file",
41
+ "x-completion-glob": "**/*@(.html|.htm)"
42
+ },
43
+ "baseHref": {
44
+ "type": "string",
45
+ "description": "Base url for the application being built."
46
+ },
47
+ "deployUrl": {
48
+ "type": "string",
49
+ "description": "URL where the application will be deployed."
50
+ },
51
+ "rspackConfig": {
52
+ "type": "string",
53
+ "description": "The path to the rspack config file."
54
+ },
55
+ "optimization": {
56
+ "description": "Enables optimization of the build output.",
57
+ "oneOf": [
58
+ {
59
+ "type": "object",
60
+ "properties": {
61
+ "scripts": {
62
+ "type": "boolean",
63
+ "description": "Enables optimization of the scripts output.",
64
+ "default": true
65
+ },
66
+ "styles": {
67
+ "type": "boolean",
68
+ "description": "Enables optimization of the styles output.",
69
+ "default": true
70
+ }
71
+ },
72
+ "additionalProperties": false
73
+ },
74
+ {
75
+ "type": "boolean"
76
+ }
77
+ ]
78
+ },
79
+ "sourceMap": {
80
+ "description": "Output sourcemaps. Use 'hidden' for use with error reporting tools without generating sourcemap comment.",
81
+ "default": true,
82
+ "oneOf": [
83
+ {
84
+ "type": "boolean"
85
+ },
86
+ {
87
+ "type": "string"
88
+ }
89
+ ]
90
+ },
91
+ "assets": {
92
+ "type": "array",
93
+ "description": "List of static application assets.",
94
+ "default": [],
95
+ "items": {
96
+ "$ref": "#/definitions/assetPattern"
97
+ }
98
+ },
99
+ "extractLicenses": {
100
+ "type": "boolean",
101
+ "description": "Extract all licenses in a separate file.",
102
+ "default": true
103
+ },
104
+ "fileReplacements": {
105
+ "description": "Replace files with other files in the build.",
106
+ "type": "array",
107
+ "items": {
108
+ "type": "object",
109
+ "properties": {
110
+ "replace": {
111
+ "type": "string",
112
+ "description": "The file to be replaced.",
113
+ "x-completion-type": "file"
114
+ },
115
+ "with": {
116
+ "type": "string",
117
+ "description": "The file to replace with.",
118
+ "x-completion-type": "file"
119
+ }
120
+ },
121
+ "additionalProperties": false,
122
+ "required": ["replace", "with"]
123
+ },
124
+ "default": []
125
+ },
126
+ "mode": {
127
+ "type": "string",
128
+ "description": "Mode to run the build in.",
129
+ "enum": ["development", "production", "none"]
130
+ },
131
+ "generatePackageJson": {
132
+ "type": "boolean",
133
+ "description": "Generates a `package.json` and pruned lock file with the project's `node_module` dependencies populated for installing in a container. If a `package.json` exists in the project's directory, it will be reused with dependencies populated."
134
+ }
135
+ },
136
+ "required": ["target", "main", "outputPath", "tsConfig", "rspackConfig"],
137
+ "definitions": {
138
+ "assetPattern": {
139
+ "oneOf": [
140
+ {
141
+ "type": "object",
142
+ "properties": {
143
+ "glob": {
144
+ "type": "string",
145
+ "description": "The pattern to match."
146
+ },
147
+ "input": {
148
+ "type": "string",
149
+ "description": "The input directory path in which to apply 'glob'. Defaults to the project root."
150
+ },
151
+ "ignore": {
152
+ "description": "An array of globs to ignore.",
153
+ "type": "array",
154
+ "items": {
155
+ "type": "string"
156
+ }
157
+ },
158
+ "output": {
159
+ "type": "string",
160
+ "description": "Absolute path within the output."
161
+ },
162
+ "watch": {
163
+ "type": "boolean",
164
+ "description": "Enable re-building when files change.",
165
+ "default": false
166
+ }
167
+ },
168
+ "additionalProperties": false,
169
+ "required": ["glob", "input", "output"]
170
+ },
171
+ {
172
+ "type": "string"
173
+ }
174
+ ]
175
+ }
176
+ }
177
+ }
@@ -0,0 +1 @@
1
+ export declare function waitUntilServerIsListening(port: number): Promise<void>;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.waitUntilServerIsListening = waitUntilServerIsListening;
4
+ const tslib_1 = require("tslib");
5
+ const net = tslib_1.__importStar(require("net"));
6
+ function waitUntilServerIsListening(port) {
7
+ const allowedErrorCodes = ['ECONNREFUSED', 'ECONNRESET'];
8
+ const maxAttempts = 25;
9
+ let attempts = 0;
10
+ const client = new net.Socket();
11
+ const cleanup = () => {
12
+ client.removeAllListeners('connect');
13
+ client.removeAllListeners('error');
14
+ client.end();
15
+ client.destroy();
16
+ client.unref();
17
+ };
18
+ return new Promise((resolve, reject) => {
19
+ const listen = () => {
20
+ client.once('connect', () => {
21
+ cleanup();
22
+ resolve();
23
+ });
24
+ client.on('error', (err) => {
25
+ if (attempts > maxAttempts ||
26
+ !allowedErrorCodes.includes(err['code'])) {
27
+ cleanup();
28
+ reject(err);
29
+ }
30
+ else {
31
+ attempts++;
32
+ setTimeout(listen, 100 * attempts);
33
+ }
34
+ });
35
+ client.connect({ port, host: 'localhost' });
36
+ };
37
+ listen();
38
+ });
39
+ }
@@ -0,0 +1,11 @@
1
+ interface TargetOptions {
2
+ [key: string]: string | boolean | number | TargetOptions;
3
+ }
4
+
5
+ export interface RspackSsrDevServerOptions {
6
+ browserTarget: string;
7
+ serverTarget: string;
8
+ port: number;
9
+ browserTargetOptions: TargetOptions;
10
+ serverTargetOptions: TargetOptions;
11
+ }