@gravity-ui/app-builder 0.29.3-beta.0 → 0.30.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/README.md +138 -0
- package/dist/cli.js +17 -22
- package/dist/commands/build/build-lib.js +5 -8
- package/dist/commands/build/build-service/client.js +3 -6
- package/dist/commands/build/build-service/index.js +4 -7
- package/dist/commands/build/build-service/server.js +11 -17
- package/dist/commands/build/index.js +3 -6
- package/dist/commands/dev/client.js +34 -63
- package/dist/commands/dev/index.js +26 -47
- package/dist/commands/dev/server.js +13 -42
- package/dist/common/babel/index.js +1 -4
- package/dist/common/babel/ui-preset.d.ts +1 -1
- package/dist/common/babel/ui-preset.js +0 -1
- package/dist/common/child-process/controllable-script.js +5 -32
- package/dist/common/child-process/utils.js +4 -30
- package/dist/common/command.js +1 -2
- package/dist/common/config.js +36 -45
- package/dist/common/env.js +3 -5
- package/dist/common/library/babel-plugin-replace-paths.js +2 -4
- package/dist/common/library/index.js +66 -95
- package/dist/common/logger/colors.js +2 -8
- package/dist/common/logger/index.js +17 -24
- package/dist/common/logger/log-config.js +3 -6
- package/dist/common/logger/pretty-time.js +2 -6
- package/dist/common/models/index.d.ts +66 -1
- package/dist/common/models/index.js +3 -8
- package/dist/common/paths.js +3 -28
- package/dist/common/s3-upload/compress.js +8 -12
- package/dist/common/s3-upload/create-plugin.js +9 -7
- package/dist/common/s3-upload/index.js +3 -9
- package/dist/common/s3-upload/s3-client.js +11 -37
- package/dist/common/s3-upload/upload.js +9 -38
- package/dist/common/s3-upload/webpack-plugin.js +5 -9
- package/dist/common/swc/compile.js +9 -12
- package/dist/common/swc/index.js +2 -7
- package/dist/common/swc/utils.js +6 -13
- package/dist/common/swc/watch.js +6 -9
- package/dist/common/typescript/compile.js +11 -14
- package/dist/common/typescript/diagnostic.js +11 -37
- package/dist/common/typescript/transformers.js +3 -29
- package/dist/common/typescript/utils.js +8 -18
- package/dist/common/typescript/watch.js +10 -13
- package/dist/common/utils.d.ts +3 -1
- package/dist/common/utils.js +16 -22
- package/dist/common/webpack/compile.js +16 -22
- package/dist/common/webpack/config.d.ts +0 -2
- package/dist/common/webpack/config.js +187 -137
- package/dist/common/webpack/node-externals.js +5 -34
- package/dist/common/webpack/progress-plugin.js +3 -6
- package/dist/common/webpack/public-path.d.ts +0 -1
- package/dist/common/webpack/public-path.js +1 -1
- package/dist/common/webpack/rspack.js +1 -5
- package/dist/common/webpack/runtime-versioning-plugin.d.ts +5 -0
- package/dist/common/webpack/runtime-versioning-plugin.js +20 -0
- package/dist/common/webpack/storybook.js +21 -53
- package/dist/common/webpack/utils.js +9 -36
- package/dist/common/webpack/worker/public-path.worker.d.ts +0 -1
- package/dist/common/webpack/worker/public-path.worker.js +2 -1
- package/dist/common/webpack/worker/worker-loader.js +4 -34
- package/dist/create-cli.d.ts +2 -2
- package/dist/create-cli.js +19 -48
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -27
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -330,3 +330,141 @@ worker.onmessage = ({data: {result}}) => {
|
|
|
330
330
|
|
|
331
331
|
worker.postMessage({a: 1, b: 2});
|
|
332
332
|
```
|
|
333
|
+
|
|
334
|
+
##### Module Federation
|
|
335
|
+
|
|
336
|
+
Module Federation is a Webpack 5 feature that enables micro-frontend architecture, where JavaScript applications can dynamically load code from each other at runtime.
|
|
337
|
+
|
|
338
|
+
`app-builder` uses `@module-federation/enhanced` for advanced Module Federation support.
|
|
339
|
+
|
|
340
|
+
- `moduleFederation` (`object`) — Module Federation configuration
|
|
341
|
+
- `name` (`string`) — unique name of the application in the Module Federation ecosystem. Required parameter.
|
|
342
|
+
- `version` (`string`) — application version. When specified, the entry file will be named `entry-{version}.js` instead of `entry.js`.
|
|
343
|
+
- `publicPath` (`string`) — base URL for loading resources of this micro-frontend. Required parameter.
|
|
344
|
+
- `remotes` (`string[]`) — list of remote application names that this application can load. Simplified alternative to `originalRemotes`.
|
|
345
|
+
- `originalRemotes` (`RemotesObject`) — full configuration of remote applications in Module Federation Plugin format.
|
|
346
|
+
- `remotesRuntimeVersioning` (`boolean`) — enables runtime versioning for remote applications.
|
|
347
|
+
- `isolateStyles` (`object`) — CSS style isolation settings to prevent conflicts between micro-frontends.
|
|
348
|
+
- `getPrefix` (`(entryName: string) => string`) — function to generate CSS class prefix.
|
|
349
|
+
- `prefixSelector` (`(prefix: string, selector: string, prefixedSelector: string, filePath: string) => string`) — function to add prefix to CSS selectors.
|
|
350
|
+
- Also supports all standard options from [@module-federation/enhanced](https://module-federation.io/), except `name` and `remotes`, such as:
|
|
351
|
+
- `filename` — entry file name (default `remoteEntry.js`)
|
|
352
|
+
- `exposes` — modules that this application exports
|
|
353
|
+
- `shared` — shared dependencies between applications
|
|
354
|
+
- `runtimePlugins` — plugins for Module Federation runtime
|
|
355
|
+
|
|
356
|
+
**Host Application Configuration Example:**
|
|
357
|
+
|
|
358
|
+
Host applications consume remote modules from other micro-frontends:
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
export default defineConfig({
|
|
362
|
+
client: {
|
|
363
|
+
moduleFederation: {
|
|
364
|
+
name: 'shell',
|
|
365
|
+
publicPath: 'https://cdn.example.com/my-app/',
|
|
366
|
+
// Simple remotes configuration
|
|
367
|
+
remotes: ['header', 'footer', 'sidebar'],
|
|
368
|
+
shared: {
|
|
369
|
+
react: {singleton: true, requiredVersion: '^18.0.0'},
|
|
370
|
+
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
|
|
371
|
+
lodash: {singleton: true},
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**Advanced Host Configuration:**
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
export default defineConfig({
|
|
382
|
+
client: {
|
|
383
|
+
moduleFederation: {
|
|
384
|
+
name: 'main-shell',
|
|
385
|
+
version: '2.1.0',
|
|
386
|
+
publicPath: 'https://cdn.example.com/my-app/',
|
|
387
|
+
// Detailed remotes configuration
|
|
388
|
+
originalRemotes: {
|
|
389
|
+
header: 'header@https://cdn.example.com/header/remoteEntry.js',
|
|
390
|
+
footer: 'footer@https://cdn.example.com/footer/remoteEntry.js',
|
|
391
|
+
userProfile: 'userProfile@https://cdn.example.com/user-profile/remoteEntry.js',
|
|
392
|
+
},
|
|
393
|
+
remotesRuntimeVersioning: true,
|
|
394
|
+
isolateStyles: {
|
|
395
|
+
getPrefix: (entryName) => `.app-${entryName}`,
|
|
396
|
+
prefixSelector: (prefix, selector, prefixedSelector, filePath) => {
|
|
397
|
+
if (
|
|
398
|
+
[prefix, ':root', 'html', 'body', '.g-root', '.remote-app'].some((item) =>
|
|
399
|
+
selector.startsWith(item),
|
|
400
|
+
) ||
|
|
401
|
+
filePath.includes('@gravity-ui/chartkit')
|
|
402
|
+
) {
|
|
403
|
+
return selector;
|
|
404
|
+
}
|
|
405
|
+
return prefixedSelector;
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
shared: {
|
|
409
|
+
react: {singleton: true, requiredVersion: '^18.0.0'},
|
|
410
|
+
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
|
|
411
|
+
lodash: {singleton: true},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**Remote Application Configuration Example:**
|
|
419
|
+
|
|
420
|
+
Remote applications expose their modules for consumption by host applications:
|
|
421
|
+
|
|
422
|
+
```ts
|
|
423
|
+
export default defineConfig({
|
|
424
|
+
client: {
|
|
425
|
+
moduleFederation: {
|
|
426
|
+
name: 'header',
|
|
427
|
+
publicPath: 'https://cdn.example.com/my-app/',
|
|
428
|
+
// Expose modules for other applications
|
|
429
|
+
exposes: {
|
|
430
|
+
'./Header': './src/components/Header',
|
|
431
|
+
'./Navigation': './src/components/Navigation',
|
|
432
|
+
'./UserMenu': './src/components/UserMenu',
|
|
433
|
+
},
|
|
434
|
+
shared: {
|
|
435
|
+
react: {singleton: true, requiredVersion: '^18.0.0'},
|
|
436
|
+
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
|
|
437
|
+
lodash: {singleton: true},
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
**Bidirectional Configuration Example:**
|
|
445
|
+
|
|
446
|
+
Applications can be both host and remote simultaneously:
|
|
447
|
+
|
|
448
|
+
```ts
|
|
449
|
+
export default defineConfig({
|
|
450
|
+
client: {
|
|
451
|
+
moduleFederation: {
|
|
452
|
+
name: 'dashboard',
|
|
453
|
+
version: '1.5.0',
|
|
454
|
+
publicPath: 'https://cdn.example.com/my-app/',
|
|
455
|
+
// Consume remote modules
|
|
456
|
+
remotes: ['charts', 'notifications'],
|
|
457
|
+
// Expose own modules
|
|
458
|
+
exposes: {
|
|
459
|
+
'./DashboardLayout': './src/layouts/DashboardLayout',
|
|
460
|
+
'./DataTable': './src/components/DataTable',
|
|
461
|
+
},
|
|
462
|
+
shared: {
|
|
463
|
+
react: {singleton: true, requiredVersion: '^18.0.0'},
|
|
464
|
+
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
|
|
465
|
+
lodash: {singleton: true},
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
});
|
|
470
|
+
```
|
package/dist/cli.js
CHANGED
|
@@ -1,44 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const util_1 = __importDefault(require("util"));
|
|
9
|
-
const common_tags_1 = require("common-tags");
|
|
10
|
-
require("./common/env");
|
|
11
|
-
const logger_1 = __importDefault(require("./common/logger"));
|
|
12
|
-
const create_cli_1 = require("./create-cli");
|
|
2
|
+
import semver from 'semver';
|
|
3
|
+
import util from 'util';
|
|
4
|
+
import { stripIndent } from 'common-tags';
|
|
5
|
+
import './common/env';
|
|
6
|
+
import logger from './common/logger';
|
|
7
|
+
import { createCli } from './create-cli';
|
|
13
8
|
const MIN_NODE_VERSION = '18.0.0';
|
|
14
9
|
const { version } = process;
|
|
15
|
-
if (!
|
|
10
|
+
if (!semver.satisfies(version, `>=${MIN_NODE_VERSION}`, {
|
|
16
11
|
includePrerelease: true,
|
|
17
12
|
})) {
|
|
18
|
-
|
|
13
|
+
logger.panic(stripIndent `
|
|
19
14
|
App-builder requires Node.js ${MIN_NODE_VERSION} or higher (you have ${version}).
|
|
20
15
|
Upgrade Node to the latest stable release.
|
|
21
|
-
`)
|
|
16
|
+
`);
|
|
22
17
|
}
|
|
23
|
-
if (
|
|
24
|
-
|
|
18
|
+
if (semver.prerelease(version)) {
|
|
19
|
+
logger.warning(stripIndent `
|
|
25
20
|
You are currently using a prerelease version of Node (${version}), which is not supported.
|
|
26
21
|
You can use this for testing, but we do not recommend it in production.
|
|
27
22
|
Before reporting any bugs, please test with a supported version of Node (>=${MIN_NODE_VERSION}).
|
|
28
|
-
`)
|
|
23
|
+
`);
|
|
29
24
|
}
|
|
30
25
|
process.on('unhandledRejection', (reason) => {
|
|
31
26
|
// This will exit the process in newer Node anyway so lets be consistent
|
|
32
27
|
// across versions and crash
|
|
33
28
|
// reason can be anything, it can be a message, an object, ANYTHING!
|
|
34
29
|
// we convert it to an error object
|
|
35
|
-
const error = reason instanceof Error ? reason : new Error(
|
|
36
|
-
|
|
30
|
+
const error = reason instanceof Error ? reason : new Error(util.format(reason));
|
|
31
|
+
logger.panic('UNHANDLED REJECTION', error);
|
|
37
32
|
});
|
|
38
33
|
process.on('uncaughtException', (error) => {
|
|
39
|
-
|
|
34
|
+
logger.panic('UNHANDLED EXCEPTION', error);
|
|
40
35
|
});
|
|
41
36
|
process.on('exit', (code) => {
|
|
42
|
-
|
|
37
|
+
logger.message(`Exit with code: ${code}`);
|
|
43
38
|
});
|
|
44
|
-
|
|
39
|
+
createCli(process.argv);
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const signal_exit_1 = require("signal-exit");
|
|
5
|
-
const controllable_script_1 = require("../../common/child-process/controllable-script");
|
|
6
|
-
function default_1(config) {
|
|
1
|
+
import { onExit } from 'signal-exit';
|
|
2
|
+
import { ControllableScript } from '../../common/child-process/controllable-script';
|
|
3
|
+
export default function (config) {
|
|
7
4
|
return new Promise((resolve, reject) => {
|
|
8
|
-
const build = new
|
|
5
|
+
const build = new ControllableScript(`
|
|
9
6
|
const {buildLibrary} = require(${JSON.stringify(require.resolve('../../common/library'))});
|
|
10
7
|
buildLibrary({lib: ${JSON.stringify(config.lib)}});
|
|
11
8
|
`, null);
|
|
@@ -26,7 +23,7 @@ function default_1(config) {
|
|
|
26
23
|
await build.stop('SIGTERM');
|
|
27
24
|
process.exit(1);
|
|
28
25
|
});
|
|
29
|
-
|
|
26
|
+
onExit((_code, signal) => {
|
|
30
27
|
build.stop(signal);
|
|
31
28
|
});
|
|
32
29
|
}, (error) => {
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const compile_1 = require("../../../common/webpack/compile");
|
|
5
|
-
function buildClient(config) {
|
|
6
|
-
return (0, compile_1.clientCompile)(config.client, config.configPath);
|
|
1
|
+
import { clientCompile } from '../../../common/webpack/compile';
|
|
2
|
+
export function buildClient(config) {
|
|
3
|
+
return clientCompile(config.client, config.configPath);
|
|
7
4
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
function default_1(config) {
|
|
6
|
-
const shouldCompileClient = (0, utils_1.shouldCompileTarget)(config.target, 'client');
|
|
7
|
-
const shouldCompileServer = (0, utils_1.shouldCompileTarget)(config.target, 'server');
|
|
1
|
+
import { shouldCompileTarget } from '../../../common/utils';
|
|
2
|
+
export default function (config) {
|
|
3
|
+
const shouldCompileClient = shouldCompileTarget(config.target, 'client');
|
|
4
|
+
const shouldCompileServer = shouldCompileTarget(config.target, 'server');
|
|
8
5
|
const compilations = [];
|
|
9
6
|
if (shouldCompileClient) {
|
|
10
7
|
compilations.push((async () => {
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.buildServer = buildServer;
|
|
7
|
-
const signal_exit_1 = require("signal-exit");
|
|
8
|
-
const controllable_script_1 = require("../../../common/child-process/controllable-script");
|
|
9
|
-
const paths_1 = __importDefault(require("../../../common/paths"));
|
|
10
|
-
const utils_1 = require("../../../common/utils");
|
|
1
|
+
import { onExit } from 'signal-exit';
|
|
2
|
+
import { ControllableScript } from '../../../common/child-process/controllable-script';
|
|
3
|
+
import paths from '../../../common/paths';
|
|
4
|
+
import { createRunFolder } from '../../../common/utils';
|
|
11
5
|
function createSWCBuildScript(config) {
|
|
12
6
|
return `
|
|
13
7
|
const {Logger} = require(${JSON.stringify(require.resolve('../../../common/logger'))});
|
|
@@ -16,8 +10,8 @@ const {compile} = require(${JSON.stringify(require.resolve('../../../common/swc/
|
|
|
16
10
|
const logger = new Logger('server', ${config.verbose});
|
|
17
11
|
compile({
|
|
18
12
|
logger,
|
|
19
|
-
outputPath: ${JSON.stringify(
|
|
20
|
-
projectPath: ${JSON.stringify(
|
|
13
|
+
outputPath: ${JSON.stringify(paths.appDist)},
|
|
14
|
+
projectPath: ${JSON.stringify(paths.appServer)},
|
|
21
15
|
});`;
|
|
22
16
|
}
|
|
23
17
|
function createTypescriptBuildScript(config) {
|
|
@@ -35,12 +29,12 @@ const {Logger} = require(${JSON.stringify(require.resolve('../../../common/logge
|
|
|
35
29
|
const {compile} = require(${JSON.stringify(require.resolve('../../../common/typescript/compile'))});
|
|
36
30
|
|
|
37
31
|
const logger = new Logger('server', ${config.verbose});
|
|
38
|
-
compile(ts, {logger, projectPath: ${JSON.stringify(
|
|
32
|
+
compile(ts, {logger, projectPath: ${JSON.stringify(paths.appServer)}});`;
|
|
39
33
|
}
|
|
40
|
-
function buildServer(config) {
|
|
41
|
-
|
|
34
|
+
export function buildServer(config) {
|
|
35
|
+
createRunFolder(config);
|
|
42
36
|
return new Promise((resolve, reject) => {
|
|
43
|
-
const build = new
|
|
37
|
+
const build = new ControllableScript(config.server.compiler === 'swc'
|
|
44
38
|
? createSWCBuildScript(config)
|
|
45
39
|
: createTypescriptBuildScript(config), null);
|
|
46
40
|
build.start().then(() => {
|
|
@@ -60,7 +54,7 @@ function buildServer(config) {
|
|
|
60
54
|
await build.stop('SIGTERM');
|
|
61
55
|
process.exit(1);
|
|
62
56
|
});
|
|
63
|
-
|
|
57
|
+
onExit((_code, signal) => {
|
|
64
58
|
build.stop(signal);
|
|
65
59
|
});
|
|
66
60
|
}, (error) => {
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.default = default_1;
|
|
4
|
-
const models_1 = require("../../common/models");
|
|
5
|
-
async function default_1(config) {
|
|
1
|
+
import { isLibraryConfig } from '../../common/models';
|
|
2
|
+
export default async function (config) {
|
|
6
3
|
process.env.NODE_ENV = 'production';
|
|
7
4
|
// eslint-disable-next-line security/detect-non-literal-require
|
|
8
|
-
const { default: build } = require(
|
|
5
|
+
const { default: build } = require(isLibraryConfig(config) ? './build-lib' : './build-service');
|
|
9
6
|
return build(config);
|
|
10
7
|
}
|
|
@@ -1,46 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.watchClientCompilation = watchClientCompilation;
|
|
30
|
-
const path = __importStar(require("node:path"));
|
|
31
|
-
const fs = __importStar(require("node:fs"));
|
|
32
|
-
const webpack_1 = __importDefault(require("webpack"));
|
|
33
|
-
const webpack_dev_server_1 = __importDefault(require("webpack-dev-server"));
|
|
34
|
-
const webpack_manifest_plugin_1 = require("webpack-manifest-plugin");
|
|
35
|
-
const webpack_assets_manifest_1 = __importDefault(require("webpack-assets-manifest"));
|
|
36
|
-
const utils_1 = require("../../common/utils");
|
|
37
|
-
const rspack_manifest_plugin_1 = require("rspack-manifest-plugin");
|
|
38
|
-
const core_1 = require("@rspack/core");
|
|
39
|
-
const dev_server_1 = require("@rspack/dev-server");
|
|
40
|
-
const paths_1 = __importDefault(require("../../common/paths"));
|
|
41
|
-
const logger_1 = require("../../common/logger");
|
|
42
|
-
const config_1 = require("../../common/webpack/config");
|
|
43
|
-
async function watchClientCompilation(config, onManifestReady) {
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import webpack from 'webpack';
|
|
4
|
+
import WebpackDevServer from 'webpack-dev-server';
|
|
5
|
+
import { getCompilerHooks } from 'webpack-manifest-plugin';
|
|
6
|
+
import WebpackAssetsManifest from 'webpack-assets-manifest';
|
|
7
|
+
import { deferredPromise, getAppRunPath } from '../../common/utils';
|
|
8
|
+
import { getCompilerHooks as getRspackCompilerHooks } from 'rspack-manifest-plugin';
|
|
9
|
+
import { rspack, } from '@rspack/core';
|
|
10
|
+
import { RspackDevServer } from '@rspack/dev-server';
|
|
11
|
+
import paths from '../../common/paths';
|
|
12
|
+
import { Logger } from '../../common/logger';
|
|
13
|
+
import { rspackConfigFactory, webpackConfigFactory } from '../../common/webpack/config';
|
|
14
|
+
export async function watchClientCompilation(config, onManifestReady) {
|
|
44
15
|
const clientCompilation = await buildDevServer(config);
|
|
45
16
|
const compiler = clientCompilation.compiler;
|
|
46
17
|
subscribeToManifestReadyEvent(compiler, onManifestReady);
|
|
@@ -48,7 +19,7 @@ async function watchClientCompilation(config, onManifestReady) {
|
|
|
48
19
|
}
|
|
49
20
|
async function buildDevServer(config) {
|
|
50
21
|
const bundler = config.client.bundler;
|
|
51
|
-
const logger = new
|
|
22
|
+
const logger = new Logger('client', config.verbose);
|
|
52
23
|
const { publicPath } = config.client;
|
|
53
24
|
const { webSocketPath = path.normalize(`/${publicPath}/sockjs-node`), writeToDisk, ...devServer } = config.client.devServer || {};
|
|
54
25
|
const normalizedConfig = { ...config.client, devServer: { ...devServer, webSocketPath } };
|
|
@@ -57,7 +28,7 @@ async function buildDevServer(config) {
|
|
|
57
28
|
let rspackConfigs = [];
|
|
58
29
|
if (bundler === 'webpack') {
|
|
59
30
|
webpackConfigs = [
|
|
60
|
-
await
|
|
31
|
+
await webpackConfigFactory({
|
|
61
32
|
webpackMode: "development" /* WebpackMode.Dev */,
|
|
62
33
|
config: normalizedConfig,
|
|
63
34
|
configPath: config.configPath,
|
|
@@ -65,8 +36,8 @@ async function buildDevServer(config) {
|
|
|
65
36
|
}),
|
|
66
37
|
];
|
|
67
38
|
if (isSsr) {
|
|
68
|
-
const ssrLogger = new
|
|
69
|
-
webpackConfigs.push(await
|
|
39
|
+
const ssrLogger = new Logger('client(SSR)', config.verbose);
|
|
40
|
+
webpackConfigs.push(await webpackConfigFactory({
|
|
70
41
|
webpackMode: "development" /* WebpackMode.Dev */,
|
|
71
42
|
config: normalizedConfig,
|
|
72
43
|
configPath: config.configPath,
|
|
@@ -77,7 +48,7 @@ async function buildDevServer(config) {
|
|
|
77
48
|
}
|
|
78
49
|
else {
|
|
79
50
|
rspackConfigs = [
|
|
80
|
-
await
|
|
51
|
+
await rspackConfigFactory({
|
|
81
52
|
webpackMode: "development" /* WebpackMode.Dev */,
|
|
82
53
|
config: normalizedConfig,
|
|
83
54
|
configPath: config.configPath,
|
|
@@ -85,8 +56,8 @@ async function buildDevServer(config) {
|
|
|
85
56
|
}),
|
|
86
57
|
];
|
|
87
58
|
if (isSsr) {
|
|
88
|
-
const ssrLogger = new
|
|
89
|
-
rspackConfigs.push(await
|
|
59
|
+
const ssrLogger = new Logger('client(SSR)', config.verbose);
|
|
60
|
+
rspackConfigs.push(await rspackConfigFactory({
|
|
90
61
|
webpackMode: "development" /* WebpackMode.Dev */,
|
|
91
62
|
config: normalizedConfig,
|
|
92
63
|
configPath: config.configPath,
|
|
@@ -98,14 +69,14 @@ async function buildDevServer(config) {
|
|
|
98
69
|
// Rspack multicompiler dont work with lazy compilation.
|
|
99
70
|
// Pass a single config to avoid multicompiler when SSR disabled.
|
|
100
71
|
const compiler = bundler === 'rspack'
|
|
101
|
-
?
|
|
102
|
-
: (
|
|
103
|
-
const staticFolder = path.resolve(
|
|
72
|
+
? rspack(isSsr ? rspackConfigs : rspackConfigs[0])
|
|
73
|
+
: webpack(webpackConfigs);
|
|
74
|
+
const staticFolder = path.resolve(paths.appDist, 'public');
|
|
104
75
|
const options = {
|
|
105
76
|
static: staticFolder,
|
|
106
77
|
setupMiddlewares(middlewares) {
|
|
107
78
|
if (config.client.lazyCompilation && bundler === 'rspack') {
|
|
108
|
-
const lazyCompilationMiddleware =
|
|
79
|
+
const lazyCompilationMiddleware = rspack.experiments.lazyCompilationMiddleware(compiler, rspackConfigs[0]?.experiments?.lazyCompilation);
|
|
109
80
|
return [lazyCompilationMiddleware, ...middlewares];
|
|
110
81
|
}
|
|
111
82
|
return middlewares;
|
|
@@ -117,7 +88,7 @@ async function buildDevServer(config) {
|
|
|
117
88
|
if (writeToDisk === true) {
|
|
118
89
|
return true;
|
|
119
90
|
}
|
|
120
|
-
if (isSsr && target.startsWith(
|
|
91
|
+
if (isSsr && target.startsWith(paths.appSsrBuild)) {
|
|
121
92
|
return true;
|
|
122
93
|
}
|
|
123
94
|
if (typeof writeToDisk === 'function') {
|
|
@@ -152,7 +123,7 @@ async function buildDevServer(config) {
|
|
|
152
123
|
};
|
|
153
124
|
const listenOn = options.port || options.ipc;
|
|
154
125
|
if (!listenOn) {
|
|
155
|
-
options.ipc = path.resolve(
|
|
126
|
+
options.ipc = path.resolve(getAppRunPath(config), 'client.sock');
|
|
156
127
|
}
|
|
157
128
|
const proxy = options.proxy || [];
|
|
158
129
|
if (config.client.lazyCompilation && bundler !== 'rspack') {
|
|
@@ -184,10 +155,10 @@ async function buildDevServer(config) {
|
|
|
184
155
|
options.proxy = proxy;
|
|
185
156
|
let server;
|
|
186
157
|
if (bundler === 'rspack') {
|
|
187
|
-
server = new
|
|
158
|
+
server = new RspackDevServer(options, compiler);
|
|
188
159
|
}
|
|
189
160
|
else {
|
|
190
|
-
server = new
|
|
161
|
+
server = new WebpackDevServer(options, compiler);
|
|
191
162
|
}
|
|
192
163
|
try {
|
|
193
164
|
await server.start();
|
|
@@ -214,21 +185,21 @@ function subscribeToManifestReadyEvent(compiler, onManifestReady) {
|
|
|
214
185
|
throw new Error('Something goes wrong!');
|
|
215
186
|
}
|
|
216
187
|
if (!isRspackCompiler(currentCompiler)) {
|
|
217
|
-
const assetsManifestPlugin = config.plugins.find((plugin) => plugin instanceof
|
|
188
|
+
const assetsManifestPlugin = config.plugins.find((plugin) => plugin instanceof WebpackAssetsManifest);
|
|
218
189
|
if (assetsManifestPlugin) {
|
|
219
|
-
const assetsManifestReady =
|
|
190
|
+
const assetsManifestReady = deferredPromise();
|
|
220
191
|
promises.push(assetsManifestReady.promise);
|
|
221
192
|
assetsManifestPlugin.hooks.done.tap('app-builder', assetsManifestReady.resolve);
|
|
222
193
|
}
|
|
223
194
|
}
|
|
224
|
-
const manifestReady =
|
|
195
|
+
const manifestReady = deferredPromise();
|
|
225
196
|
promises.push(manifestReady.promise);
|
|
226
197
|
if (isRspackCompiler(currentCompiler)) {
|
|
227
|
-
const { afterEmit } = (
|
|
198
|
+
const { afterEmit } = getRspackCompilerHooks(currentCompiler);
|
|
228
199
|
afterEmit.tap('app-builder', manifestReady.resolve);
|
|
229
200
|
}
|
|
230
201
|
else {
|
|
231
|
-
const { afterEmit } =
|
|
202
|
+
const { afterEmit } = getCompilerHooks(currentCompiler);
|
|
232
203
|
afterEmit.tap('app-builder', manifestReady.resolve);
|
|
233
204
|
}
|
|
234
205
|
}
|
|
@@ -1,61 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.default = default_1;
|
|
30
|
-
const path = __importStar(require("node:path"));
|
|
31
|
-
const nodemon_1 = __importDefault(require("nodemon"));
|
|
32
|
-
const signal_exit_1 = require("signal-exit");
|
|
33
|
-
const rimraf_1 = require("rimraf");
|
|
34
|
-
const utils_1 = require("../../common/utils");
|
|
35
|
-
const logger_1 = __importDefault(require("../../common/logger"));
|
|
36
|
-
const paths_1 = __importDefault(require("../../common/paths"));
|
|
37
|
-
async function default_1(config) {
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import nodemon from 'nodemon';
|
|
4
|
+
import { onExit } from 'signal-exit';
|
|
5
|
+
import { rimraf } from 'rimraf';
|
|
6
|
+
import { getAppRunPath, shouldCompileTarget } from '../../common/utils';
|
|
7
|
+
import logger from '../../common/logger';
|
|
8
|
+
import paths from '../../common/paths';
|
|
9
|
+
export default async function (config) {
|
|
38
10
|
process.env.NODE_ENV = 'development';
|
|
39
|
-
const shouldCompileClient =
|
|
40
|
-
const shouldCompileServer =
|
|
11
|
+
const shouldCompileClient = shouldCompileTarget(config.target, 'client');
|
|
12
|
+
const shouldCompileServer = shouldCompileTarget(config.target, 'server');
|
|
13
|
+
const appRunPath = getAppRunPath(config);
|
|
41
14
|
if (shouldCompileClient && shouldCompileServer) {
|
|
42
|
-
|
|
15
|
+
try {
|
|
16
|
+
fs.accessSync(appRunPath, fs.constants.W_OK | fs.constants.X_OK); // eslint-disable-line no-bitwise
|
|
17
|
+
rimraf.sync(appRunPath);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
logger.warning(`Failed to remove appRun path [${appRunPath}]: ${error}`);
|
|
21
|
+
}
|
|
43
22
|
}
|
|
44
23
|
let clientCompiled = !shouldCompileClient;
|
|
45
24
|
let serverCompiled = !shouldCompileServer;
|
|
46
25
|
let needToStartNodemon = shouldCompileServer;
|
|
47
|
-
const serverPath = path.resolve(
|
|
26
|
+
const serverPath = path.resolve(paths.appDist, 'server');
|
|
48
27
|
const { inspect, inspectBrk } = config.server;
|
|
49
28
|
const startNodemon = () => {
|
|
50
29
|
if (needToStartNodemon && serverCompiled && clientCompiled) {
|
|
51
|
-
|
|
30
|
+
logger.message('Starting application at', serverPath);
|
|
52
31
|
const nodeArgs = ['--enable-source-maps'];
|
|
53
32
|
if (inspect || inspectBrk) {
|
|
54
33
|
nodeArgs.push(`--${inspect ? 'inspect' : 'inspect-brk'}=:::${inspect || inspectBrk}`);
|
|
55
34
|
}
|
|
56
35
|
const serverWatch = config.server.watch ?? [];
|
|
57
36
|
const delay = config.server.watchThrottle;
|
|
58
|
-
const nodemonInstance = (
|
|
37
|
+
const nodemonInstance = nodemon({
|
|
59
38
|
ext: 'js json',
|
|
60
39
|
script: `${serverPath}/index.js`,
|
|
61
40
|
args: ['--dev', config.server.port ? `--port=${config.server.port}` : ''],
|
|
@@ -85,24 +64,24 @@ async function default_1(config) {
|
|
|
85
64
|
if (shouldCompileClient) {
|
|
86
65
|
const { watchClientCompilation } = await import('./client.js');
|
|
87
66
|
clientCompilation = await watchClientCompilation(config, () => {
|
|
88
|
-
|
|
67
|
+
logger.success('Manifest was compiled successfully');
|
|
89
68
|
clientCompiled = true;
|
|
90
69
|
startNodemon();
|
|
91
70
|
});
|
|
92
71
|
}
|
|
93
72
|
process.on('SIGINT', async () => {
|
|
94
|
-
|
|
73
|
+
logger.success('\nCleaning up...');
|
|
95
74
|
await serverCompilation?.stop('SIGINT');
|
|
96
75
|
await clientCompilation?.stop();
|
|
97
76
|
process.exit(1);
|
|
98
77
|
});
|
|
99
78
|
process.on('SIGTERM', async () => {
|
|
100
|
-
|
|
79
|
+
logger.success('\nCleaning up...');
|
|
101
80
|
await serverCompilation?.stop('SIGTERM');
|
|
102
81
|
await clientCompilation?.stop();
|
|
103
82
|
process.exit(1);
|
|
104
83
|
});
|
|
105
|
-
|
|
84
|
+
onExit((_code, signal) => {
|
|
106
85
|
serverCompilation?.stop(signal);
|
|
107
86
|
clientCompilation?.stop();
|
|
108
87
|
});
|