@tramvai/cli 2.110.0 → 2.111.1
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/lib/builder/webpack/tokens.d.ts +3 -0
- package/lib/commands/update/dependantLibs.d.ts +0 -1
- package/lib/commands/update/dependantLibs.js +3 -24
- package/lib/commands/update/dependantLibs.js.map +1 -1
- package/lib/commands/update/updatePackageJson.js +3 -5
- package/lib/commands/update/updatePackageJson.js.map +1 -1
- package/lib/di/tokens/config.d.ts +1 -0
- package/lib/library/webpack/application/client/common.js +7 -1
- package/lib/library/webpack/application/client/common.js.map +1 -1
- package/lib/library/webpack/application/server/prod.js +24 -0
- package/lib/library/webpack/application/server/prod.js.map +1 -1
- package/lib/library/webpack/blocks/optimize.js +4 -0
- package/lib/library/webpack/blocks/optimize.js.map +1 -1
- package/lib/library/webpack/child-app/client/common.js +7 -1
- package/lib/library/webpack/child-app/client/common.js.map +1 -1
- package/lib/library/webpack/child-app/moduleFederationShared.js +4 -4
- package/lib/library/webpack/plugins/ModuleFederationFixRange.d.ts +23 -0
- package/lib/library/webpack/plugins/ModuleFederationFixRange.js +125 -0
- package/lib/library/webpack/plugins/ModuleFederationFixRange.js.map +1 -0
- package/lib/schema/autogeneratedSchema.json +21 -3
- package/lib/typings/configEntry/cli.d.ts +7 -1
- package/lib/utils/tramvaiVersions.d.ts +3 -0
- package/lib/utils/tramvaiVersions.js +30 -0
- package/lib/utils/tramvaiVersions.js.map +1 -0
- package/package.json +8 -8
- package/schema.json +21 -3
- package/src/commands/update/dependantLibs.ts +1 -23
- package/src/commands/update/updatePackageJson.ts +2 -5
- package/src/library/swc/__integration__/__snapshots__/swc.build.test.ts.snap +149 -196
- package/src/library/swc/__integration__/__snapshots__/swc.start.test.ts.snap +30 -20
- package/src/library/webpack/application/client/common.ts +9 -1
- package/src/library/webpack/application/server/prod.ts +25 -0
- package/src/library/webpack/blocks/optimize.ts +4 -0
- package/src/library/webpack/child-app/client/common.ts +9 -1
- package/src/library/webpack/child-app/moduleFederationShared.ts +4 -4
- package/src/library/webpack/plugins/ModuleFederationFixRange.ts +174 -0
- package/src/models/config.spec.ts +4 -0
- package/src/schema/autogeneratedSchema.json +21 -3
- package/src/schema/tramvai.spec.ts +2 -0
- package/src/typings/configEntry/cli.ts +7 -1
- package/src/utils/tramvaiVersions.ts +26 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
exports[`client: create-token-pure.ts 1`] = `
|
|
4
4
|
"__webpack_require__.r(__webpack_exports__);
|
|
5
5
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
6
|
-
/* harmony export */
|
|
6
|
+
/* harmony export */ TEST_TOKEN: function() { return /* binding */ TEST_TOKEN; }
|
|
7
7
|
/* harmony export */ });
|
|
8
8
|
/* harmony import */ var _tramvai_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/library/swc/__integration__/mocks/tramvai-core.ts");
|
|
9
9
|
/* provided dependency */ var __react_refresh_utils__ = __webpack_require__("../../node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js");
|
|
@@ -149,7 +149,7 @@ __webpack_require__.$Refresh$.register(_c, "SvgLogo");
|
|
|
149
149
|
exports[`client: lazy-component.tsx 1`] = `
|
|
150
150
|
"__webpack_require__.r(__webpack_exports__);
|
|
151
151
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
152
|
-
/* harmony export */
|
|
152
|
+
/* harmony export */ Component: function() { return /* binding */ Component; }
|
|
153
153
|
/* harmony export */ });
|
|
154
154
|
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("webpack/sharing/consume/default/react/jsx-dev-runtime/react/jsx-dev-runtime");
|
|
155
155
|
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__);
|
|
@@ -242,13 +242,15 @@ if (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Pr
|
|
|
242
242
|
exports[`client: node-env.ts 1`] = `
|
|
243
243
|
"__webpack_require__.r(__webpack_exports__);
|
|
244
244
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
245
|
-
/* harmony export */
|
|
245
|
+
/* harmony export */ func: function() { return /* binding */ func; }
|
|
246
246
|
/* harmony export */ });
|
|
247
247
|
/* provided dependency */ var __react_refresh_utils__ = __webpack_require__("../../node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js");
|
|
248
248
|
__webpack_require__.$Refresh$.runtime = __webpack_require__("../../node_modules/react-refresh/runtime.js");
|
|
249
249
|
|
|
250
250
|
let internalFunc;
|
|
251
|
-
if (true)
|
|
251
|
+
if (true) {
|
|
252
|
+
internalFunc = ()=>"Are you developer, for sure?";
|
|
253
|
+
}
|
|
252
254
|
if (false) {}
|
|
253
255
|
const func = ()=>{
|
|
254
256
|
return internalFunc();
|
|
@@ -292,7 +294,7 @@ if (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Pr
|
|
|
292
294
|
exports[`client: provider-stack.ts 1`] = `
|
|
293
295
|
"__webpack_require__.r(__webpack_exports__);
|
|
294
296
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
295
|
-
/* harmony export */
|
|
297
|
+
/* harmony export */ providers: function() { return /* binding */ providers; }
|
|
296
298
|
/* harmony export */ });
|
|
297
299
|
/* harmony import */ var _tramvai_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/library/swc/__integration__/mocks/tramvai-core.ts");
|
|
298
300
|
/* harmony import */ var _create_token_pure__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/library/swc/__integration__/create-token-pure.ts");
|
|
@@ -350,7 +352,7 @@ if (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Pr
|
|
|
350
352
|
exports[`client: react-svg.tsx 1`] = `
|
|
351
353
|
"__webpack_require__.r(__webpack_exports__);
|
|
352
354
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
353
|
-
/* harmony export */
|
|
355
|
+
/* harmony export */ Component: function() { return /* binding */ Component; }
|
|
354
356
|
/* harmony export */ });
|
|
355
357
|
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("webpack/sharing/consume/default/react/jsx-dev-runtime/react/jsx-dev-runtime");
|
|
356
358
|
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__);
|
|
@@ -415,7 +417,7 @@ if (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Pr
|
|
|
415
417
|
exports[`client: server.inline.ts 1`] = `
|
|
416
418
|
"__webpack_require__.r(__webpack_exports__);
|
|
417
419
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
418
|
-
/* harmony export */
|
|
420
|
+
/* harmony export */ ForBrowser: function() { return /* binding */ ForBrowser; }
|
|
419
421
|
/* harmony export */ });
|
|
420
422
|
/* provided dependency */ var __react_refresh_utils__ = __webpack_require__("../../node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js");
|
|
421
423
|
__webpack_require__.$Refresh$.runtime = __webpack_require__("../../node_modules/react-refresh/runtime.js");
|
|
@@ -465,13 +467,16 @@ if (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Pr
|
|
|
465
467
|
exports[`client: typeof-window.ts 1`] = `
|
|
466
468
|
"__webpack_require__.r(__webpack_exports__);
|
|
467
469
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
468
|
-
/* harmony export */
|
|
470
|
+
/* harmony export */ func: function() { return /* binding */ func; }
|
|
469
471
|
/* harmony export */ });
|
|
470
472
|
/* provided dependency */ var __react_refresh_utils__ = __webpack_require__("../../node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js");
|
|
471
473
|
__webpack_require__.$Refresh$.runtime = __webpack_require__("../../node_modules/react-refresh/runtime.js");
|
|
472
474
|
|
|
473
475
|
let internalFunc;
|
|
474
|
-
|
|
476
|
+
if (true) {
|
|
477
|
+
internalFunc = ()=>"Hello, I'm in browser";
|
|
478
|
+
}
|
|
479
|
+
if (false) {}
|
|
475
480
|
const func = ()=>{
|
|
476
481
|
return internalFunc();
|
|
477
482
|
};
|
|
@@ -514,7 +519,7 @@ if (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Pr
|
|
|
514
519
|
exports[`server: create-token-pure.ts 1`] = `
|
|
515
520
|
"__webpack_require__.r(__webpack_exports__);
|
|
516
521
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
517
|
-
/* harmony export */
|
|
522
|
+
/* harmony export */ TEST_TOKEN: function() { return /* binding */ TEST_TOKEN; }
|
|
518
523
|
/* harmony export */ });
|
|
519
524
|
/* harmony import */ var _tramvai_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/library/swc/__integration__/mocks/tramvai-core.ts");
|
|
520
525
|
|
|
@@ -609,11 +614,11 @@ const SvgLogo = (props)=>/*#__PURE__*/ (0,react_jsx_dev_runtime__WEBPACK_IMPORTE
|
|
|
609
614
|
exports[`server: lazy-component.tsx 1`] = `
|
|
610
615
|
"__webpack_require__.r(__webpack_exports__);
|
|
611
616
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
612
|
-
/* harmony export */
|
|
617
|
+
/* harmony export */ Component: function() { return /* binding */ Component; }
|
|
613
618
|
/* harmony export */ });
|
|
614
619
|
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("webpack/sharing/consume/default/react/jsx-dev-runtime/react/jsx-dev-runtime");
|
|
615
620
|
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__);
|
|
616
|
-
/* harmony import */ var _swc_helpers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("../../node_modules/@swc/helpers/
|
|
621
|
+
/* harmony import */ var _swc_helpers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("../../node_modules/@swc/helpers/esm/_interop_require_wildcard.js");
|
|
617
622
|
/* harmony import */ var _tramvai_react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/library/swc/__integration__/mocks/tramvai-react.ts");
|
|
618
623
|
|
|
619
624
|
|
|
@@ -629,7 +634,7 @@ const LazyComponent = (0,_tramvai_react__WEBPACK_IMPORTED_MODULE_1__.lazy)({
|
|
|
629
634
|
const key = this.resolve(props);
|
|
630
635
|
return !!__webpack_require__.m[key];
|
|
631
636
|
},
|
|
632
|
-
importAsync: ()=>Promise.resolve().then(()=>(0,_swc_helpers__WEBPACK_IMPORTED_MODULE_2__
|
|
637
|
+
importAsync: ()=>Promise.resolve().then(()=>(0,_swc_helpers__WEBPACK_IMPORTED_MODULE_2__._interop_require_wildcard)(__webpack_require__(/* webpackChunkName: "components-lazy-inner" */ "./src/library/swc/__integration__/components/lazy-inner.tsx"))),
|
|
633
638
|
requireAsync (props) {
|
|
634
639
|
return this.importAsync(props).then((resolved)=>{
|
|
635
640
|
return resolved;
|
|
@@ -665,10 +670,12 @@ const Component = ()=>{
|
|
|
665
670
|
exports[`server: node-env.ts 1`] = `
|
|
666
671
|
"__webpack_require__.r(__webpack_exports__);
|
|
667
672
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
668
|
-
/* harmony export */
|
|
673
|
+
/* harmony export */ func: function() { return /* binding */ func; }
|
|
669
674
|
/* harmony export */ });
|
|
670
675
|
let internalFunc;
|
|
671
|
-
if (true)
|
|
676
|
+
if (true) {
|
|
677
|
+
internalFunc = ()=>"Are you developer, for sure?";
|
|
678
|
+
}
|
|
672
679
|
if (false) {}
|
|
673
680
|
const func = ()=>{
|
|
674
681
|
return internalFunc();
|
|
@@ -681,7 +688,7 @@ const func = ()=>{
|
|
|
681
688
|
exports[`server: provider-stack.ts 1`] = `
|
|
682
689
|
"__webpack_require__.r(__webpack_exports__);
|
|
683
690
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
684
|
-
/* harmony export */
|
|
691
|
+
/* harmony export */ providers: function() { return /* binding */ providers; }
|
|
685
692
|
/* harmony export */ });
|
|
686
693
|
/* harmony import */ var _tramvai_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/library/swc/__integration__/mocks/tramvai-core.ts");
|
|
687
694
|
/* harmony import */ var _create_token_pure__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/library/swc/__integration__/create-token-pure.ts");
|
|
@@ -705,7 +712,7 @@ const providers = [
|
|
|
705
712
|
exports[`server: react-svg.tsx 1`] = `
|
|
706
713
|
"__webpack_require__.r(__webpack_exports__);
|
|
707
714
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
708
|
-
/* harmony export */
|
|
715
|
+
/* harmony export */ Component: function() { return /* binding */ Component; }
|
|
709
716
|
/* harmony export */ });
|
|
710
717
|
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("webpack/sharing/consume/default/react/jsx-dev-runtime/react/jsx-dev-runtime");
|
|
711
718
|
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__);
|
|
@@ -733,7 +740,7 @@ const Component = ()=>{
|
|
|
733
740
|
exports[`server: server.inline.ts 1`] = `
|
|
734
741
|
"__webpack_require__.r(__webpack_exports__);
|
|
735
742
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
736
|
-
/* harmony export */
|
|
743
|
+
/* harmony export */ ForBrowser: function() { return /* binding */ ForBrowser; }
|
|
737
744
|
/* harmony export */ });
|
|
738
745
|
var ForBrowser = /*#__PURE__*/ function() {
|
|
739
746
|
"use strict";
|
|
@@ -753,10 +760,13 @@ ForBrowser.prop = "static";
|
|
|
753
760
|
exports[`server: typeof-window.ts 1`] = `
|
|
754
761
|
"__webpack_require__.r(__webpack_exports__);
|
|
755
762
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
756
|
-
/* harmony export */
|
|
763
|
+
/* harmony export */ func: function() { return /* binding */ func; }
|
|
757
764
|
/* harmony export */ });
|
|
758
765
|
let internalFunc;
|
|
759
|
-
|
|
766
|
+
if (false) {}
|
|
767
|
+
if (true) {
|
|
768
|
+
internalFunc = ()=>"I'm a big server";
|
|
769
|
+
}
|
|
760
770
|
const func = ()=>{
|
|
761
771
|
return internalFunc();
|
|
762
772
|
};
|
|
@@ -20,9 +20,11 @@ import { pagesResolve } from '../../blocks/pagesResolve';
|
|
|
20
20
|
import { configToEnv } from '../../blocks/configToEnv';
|
|
21
21
|
import { DEFAULT_STATS_OPTIONS, DEFAULT_STATS_FIELDS } from '../../constants/stats';
|
|
22
22
|
import { pwaBlock } from '../../blocks/pwa/client';
|
|
23
|
+
import type { ModuleFederationFixRangeOptions } from '../../plugins/ModuleFederationFixRange';
|
|
24
|
+
import { ModuleFederationFixRange } from '../../plugins/ModuleFederationFixRange';
|
|
23
25
|
|
|
24
26
|
export default (configManager: ConfigManager<ApplicationConfigEntry>) => (config: Config) => {
|
|
25
|
-
const { polyfill, fileSystemPages } = configManager;
|
|
27
|
+
const { polyfill, fileSystemPages, shared } = configManager;
|
|
26
28
|
|
|
27
29
|
const portal = path.resolve(configManager.rootDir, `packages/${process.env.APP_ID}/portal.js`);
|
|
28
30
|
const polyfillPath = path.resolve(configManager.rootDir, polyfill ?? 'src/polyfill');
|
|
@@ -52,6 +54,12 @@ export default (configManager: ConfigManager<ApplicationConfigEntry>) => (config
|
|
|
52
54
|
.when(portalExists, (cfg) => cfg.entry('portal').add(portal))
|
|
53
55
|
.when(polyfillExists, (cfg) => cfg.entry('polyfill').add(polyfillPath));
|
|
54
56
|
|
|
57
|
+
config.plugin('module-federation-validate-duplicates').use(ModuleFederationFixRange, [
|
|
58
|
+
{
|
|
59
|
+
flexibleTramvaiVersions: shared.flexibleTramvaiVersions,
|
|
60
|
+
} as ModuleFederationFixRangeOptions,
|
|
61
|
+
]);
|
|
62
|
+
|
|
55
63
|
config
|
|
56
64
|
.plugin('stats-plugin')
|
|
57
65
|
.use(StatsWriterPlugin, [
|
|
@@ -29,6 +29,30 @@ export const webpackServerConfig = ({
|
|
|
29
29
|
config.optimization.set('moduleIds', 'named');
|
|
30
30
|
// prevent modules from concatenation in single module to easier debug
|
|
31
31
|
config.optimization.set('concatenateModules', false);
|
|
32
|
+
|
|
33
|
+
config.plugin('terser').use(TerserPlugin, [
|
|
34
|
+
{
|
|
35
|
+
extractComments: false,
|
|
36
|
+
terserOptions: {
|
|
37
|
+
ecma: 5, // на сервере в страницу встраивается код, который может подключаться через import и terser его соптимизирует в es6
|
|
38
|
+
mangle: false,
|
|
39
|
+
// сохраняем имена функций, чтобы легче было найти ошибку в трамвае
|
|
40
|
+
keep_fnames: true,
|
|
41
|
+
compress: {
|
|
42
|
+
passes: 2,
|
|
43
|
+
drop_debugger: !debug,
|
|
44
|
+
dead_code: true,
|
|
45
|
+
},
|
|
46
|
+
output: {
|
|
47
|
+
comments: true,
|
|
48
|
+
semicolons: false,
|
|
49
|
+
preserve_annotations: true,
|
|
50
|
+
indent_start: 2,
|
|
51
|
+
beautify: true,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
]);
|
|
32
56
|
} else {
|
|
33
57
|
config.plugin('terser').use(TerserPlugin, [
|
|
34
58
|
{
|
|
@@ -39,6 +63,7 @@ export const webpackServerConfig = ({
|
|
|
39
63
|
// сохраняем имена функций, чтобы легче было найти ошибку в трамвае
|
|
40
64
|
keep_fnames: true,
|
|
41
65
|
compress: {
|
|
66
|
+
passes: 2,
|
|
42
67
|
drop_debugger: !debug,
|
|
43
68
|
dead_code: true,
|
|
44
69
|
},
|
|
@@ -8,9 +8,11 @@ import files from '../../blocks/filesClient';
|
|
|
8
8
|
import nodeClient from '../../blocks/nodeClient';
|
|
9
9
|
import postcssAssets from '../../blocks/postcssAssets';
|
|
10
10
|
import type { ChildAppConfigEntry } from '../../../../typings/configEntry/child-app';
|
|
11
|
+
import type { ModuleFederationFixRangeOptions } from '../../plugins/ModuleFederationFixRange';
|
|
12
|
+
import { ModuleFederationFixRange } from '../../plugins/ModuleFederationFixRange';
|
|
11
13
|
|
|
12
14
|
export default (configManager: ConfigManager<ChildAppConfigEntry>) => (config: Config) => {
|
|
13
|
-
const { name, version } = configManager;
|
|
15
|
+
const { name, version, shared } = configManager;
|
|
14
16
|
config.name('client');
|
|
15
17
|
|
|
16
18
|
config.batch(common(configManager));
|
|
@@ -32,5 +34,11 @@ export default (configManager: ConfigManager<ChildAppConfigEntry>) => (config: C
|
|
|
32
34
|
},
|
|
33
35
|
]);
|
|
34
36
|
|
|
37
|
+
config.plugin('module-federation-validate-duplicates').use(ModuleFederationFixRange, [
|
|
38
|
+
{
|
|
39
|
+
flexibleTramvaiVersions: shared.flexibleTramvaiVersions,
|
|
40
|
+
} as ModuleFederationFixRangeOptions,
|
|
41
|
+
]);
|
|
42
|
+
|
|
35
43
|
config.batch(files(configManager)).batch(nodeClient(configManager));
|
|
36
44
|
};
|
|
@@ -20,24 +20,24 @@ export const getSharedModules = (
|
|
|
20
20
|
} = configManager;
|
|
21
21
|
const isChild = type === 'child-app';
|
|
22
22
|
|
|
23
|
-
let
|
|
23
|
+
let defaultDependenciesList = defaultTramvaiDependencies ? DEFAULT_DEPENDENCIES_LIST : [];
|
|
24
24
|
|
|
25
25
|
if (typeof defaultTramvaiDependencies === 'undefined') {
|
|
26
26
|
if (type === 'child-app') {
|
|
27
|
-
|
|
27
|
+
defaultDependenciesList = DEFAULT_DEPENDENCIES_LIST;
|
|
28
28
|
} else if (type === 'application') {
|
|
29
29
|
const packageJson = safeRequire(path.resolve(rootDir, 'package.json'), true);
|
|
30
30
|
|
|
31
31
|
// add default dependencies only if child-app is in use to minimize bundle size for apps
|
|
32
32
|
// without child-apps
|
|
33
33
|
if (packageJson?.dependencies?.['@tramvai/module-child-app']) {
|
|
34
|
-
|
|
34
|
+
defaultDependenciesList = DEFAULT_DEPENDENCIES_LIST;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
return {
|
|
40
|
-
...
|
|
40
|
+
...defaultDependenciesList.concat(deps).reduce((acc, dep) => {
|
|
41
41
|
const { name, singleton = false } = typeof dep === 'string' ? { name: dep } : dep;
|
|
42
42
|
|
|
43
43
|
acc[name] = {
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type webpack from 'webpack';
|
|
2
|
+
import type { Compiler, NormalModule } from 'webpack';
|
|
3
|
+
import { sync as resolve } from 'resolve';
|
|
4
|
+
import type packageJson from 'package-json';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
// eslint-disable-next-line no-restricted-imports
|
|
7
|
+
import { parseRange } from 'webpack/lib/util/semver';
|
|
8
|
+
import { isDependantLib, isUnifiedVersion } from '../../../utils/tramvaiVersions';
|
|
9
|
+
|
|
10
|
+
const PLUGIN_NAME = 'ModuleFederationValidateDuplicates';
|
|
11
|
+
|
|
12
|
+
type SemverRange = [number, number, number, number];
|
|
13
|
+
|
|
14
|
+
interface SharedModuleOptions {
|
|
15
|
+
shareKey: string;
|
|
16
|
+
requiredVersion?: SemverRange;
|
|
17
|
+
importResolved: string;
|
|
18
|
+
singleton?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface SharedModule extends NormalModule {
|
|
22
|
+
options?: SharedModuleOptions;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const resolvePackageVersion = (name: string, basedir: string) => {
|
|
26
|
+
try {
|
|
27
|
+
const packageJsonPath = resolve(`${name}/package.json`, {
|
|
28
|
+
basedir,
|
|
29
|
+
});
|
|
30
|
+
const packageJson: packageJson.FullMetadataOptions = require(packageJsonPath);
|
|
31
|
+
|
|
32
|
+
return packageJson.version;
|
|
33
|
+
} catch (error: any) {
|
|
34
|
+
console.warn(`ModuleFederation: could not infer version for package "${name}"`);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export interface ModuleFederationFixRangeOptions {
|
|
39
|
+
flexibleTramvaiVersions: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class ModuleFederationFixRange implements webpack.WebpackPluginInstance {
|
|
43
|
+
private flexibleTramvaiVersions: boolean;
|
|
44
|
+
// { name: { importResolved: { number }} }
|
|
45
|
+
private sharedModules: Map<string, Map<string, Set<number>>> = new Map();
|
|
46
|
+
|
|
47
|
+
constructor({ flexibleTramvaiVersions }: ModuleFederationFixRangeOptions) {
|
|
48
|
+
this.flexibleTramvaiVersions = flexibleTramvaiVersions ?? false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
apply(compiler: Compiler) {
|
|
52
|
+
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (_, { normalModuleFactory }) => {
|
|
53
|
+
normalModuleFactory.hooks.factorize.intercept({
|
|
54
|
+
register: (tap) => {
|
|
55
|
+
if (tap.name === 'ConsumeSharedPlugin') {
|
|
56
|
+
const originalFn = tap.fn;
|
|
57
|
+
// eslint-disable-next-line no-param-reassign
|
|
58
|
+
tap.fn = async (...args) => {
|
|
59
|
+
const module: SharedModule | undefined = await originalFn(...args);
|
|
60
|
+
|
|
61
|
+
if (module?.options) {
|
|
62
|
+
this.fixVersionRange(module);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return module;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return tap;
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
compiler.hooks.done.tap(PLUGIN_NAME, () => {
|
|
75
|
+
const duplicates: Array<{ name: string; paths: string[] }> = [];
|
|
76
|
+
const criticalDuplicates: Array<{ name: string; path: string }> = [];
|
|
77
|
+
|
|
78
|
+
for (const [name, shared] of this.sharedModules) {
|
|
79
|
+
if (shared.size > 1) {
|
|
80
|
+
duplicates.push({
|
|
81
|
+
name,
|
|
82
|
+
paths: [...shared.keys()],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
for (const [path, versions] of shared) {
|
|
87
|
+
if (versions.size > 1) {
|
|
88
|
+
criticalDuplicates.push({ name, path });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// reset sharedModules info after compilation has ended
|
|
94
|
+
this.sharedModules = new Map();
|
|
95
|
+
|
|
96
|
+
if (duplicates.length) {
|
|
97
|
+
console.warn(`⚠️ ModuleFederation: Found duplicates for next shared modules:
|
|
98
|
+
${duplicates
|
|
99
|
+
.map(({ name, paths }) => {
|
|
100
|
+
return `\t${chalk.yellowBright(name)}: ${paths.join(', ')}`;
|
|
101
|
+
})
|
|
102
|
+
.join('\n')}
|
|
103
|
+
`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (criticalDuplicates.length) {
|
|
107
|
+
console.error(
|
|
108
|
+
`❗ ModuleFederation: Found duplicates for shared modules with different major versions that are resolved to the same path:
|
|
109
|
+
${criticalDuplicates
|
|
110
|
+
.map(({ name, path }) => {
|
|
111
|
+
return `\t${chalk.red(name)}: ${path}`;
|
|
112
|
+
})
|
|
113
|
+
.join('\n')}`
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
throw new Error(
|
|
117
|
+
'ModuleFederation: Different major versions have resolved to the same path for shared modules, please review errors above'
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
fixVersionRange(module: SharedModule) {
|
|
124
|
+
const {
|
|
125
|
+
options,
|
|
126
|
+
options: { shareKey: name, singleton, importResolved },
|
|
127
|
+
context,
|
|
128
|
+
} = module;
|
|
129
|
+
let { requiredVersion } = options;
|
|
130
|
+
|
|
131
|
+
// ignore singletons as the actual version won't change anything
|
|
132
|
+
// and usually it is just a react and co libraries
|
|
133
|
+
if (!requiredVersion && context && !singleton) {
|
|
134
|
+
const version = resolvePackageVersion(name, context);
|
|
135
|
+
if (version) {
|
|
136
|
+
requiredVersion = parseRange(version);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!requiredVersion) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (requiredVersion && this.flexibleTramvaiVersions) {
|
|
145
|
+
const isTramvai = isUnifiedVersion(name) || isDependantLib(name);
|
|
146
|
+
|
|
147
|
+
if (isTramvai && requiredVersion[0] > 2) {
|
|
148
|
+
// 1 is used for `^` range modifier
|
|
149
|
+
// see https://github.com/webpack/webpack/blob/56363993156e06a1230c9759eba277a22e6b6604/lib/util/semver.js#LL235C20-L235C20
|
|
150
|
+
requiredVersion[0] = 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// change version in webpack module
|
|
155
|
+
options.requiredVersion = requiredVersion;
|
|
156
|
+
|
|
157
|
+
let shared = this.sharedModules.get(name);
|
|
158
|
+
|
|
159
|
+
if (!shared) {
|
|
160
|
+
shared = new Map();
|
|
161
|
+
this.sharedModules.set(name, shared);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let versions = shared.get(importResolved);
|
|
165
|
+
|
|
166
|
+
if (!versions) {
|
|
167
|
+
versions = new Set();
|
|
168
|
+
shared.set(importResolved, versions);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// save major version of the semver array
|
|
172
|
+
versions.add(requiredVersion[1]);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -103,6 +103,7 @@ it('should populate defaults for config', () => {
|
|
|
103
103
|
"serverApiDir": "src/api",
|
|
104
104
|
"shared": {
|
|
105
105
|
"deps": [],
|
|
106
|
+
"flexibleTramvaiVersions": true,
|
|
106
107
|
},
|
|
107
108
|
"sourceMap": false,
|
|
108
109
|
"splitChunks": {
|
|
@@ -159,6 +160,7 @@ it('should populate defaults for config', () => {
|
|
|
159
160
|
"root": "packages/child-app",
|
|
160
161
|
"shared": {
|
|
161
162
|
"deps": [],
|
|
163
|
+
"flexibleTramvaiVersions": true,
|
|
162
164
|
},
|
|
163
165
|
"sourceMap": false,
|
|
164
166
|
"terser": {
|
|
@@ -336,6 +338,7 @@ it('should populate defaults for overridable options', () => {
|
|
|
336
338
|
"serverApiDir": "src/api",
|
|
337
339
|
"shared": {
|
|
338
340
|
"deps": [],
|
|
341
|
+
"flexibleTramvaiVersions": true,
|
|
339
342
|
},
|
|
340
343
|
"sourceMap": false,
|
|
341
344
|
"splitChunks": {
|
|
@@ -406,6 +409,7 @@ it('should populate defaults for overridable options', () => {
|
|
|
406
409
|
"root": "packages/child-app",
|
|
407
410
|
"shared": {
|
|
408
411
|
"deps": [],
|
|
412
|
+
"flexibleTramvaiVersions": true,
|
|
409
413
|
},
|
|
410
414
|
"sourceMap": {
|
|
411
415
|
"development": true,
|
|
@@ -1225,7 +1225,13 @@
|
|
|
1225
1225
|
"properties": {
|
|
1226
1226
|
"defaultTramvaiDependencies": {
|
|
1227
1227
|
"title": "Should default dependencies list be added to shared list",
|
|
1228
|
-
"description": "It includes the list of commonly used dependencies in the child-apps\nBy default, it is enabled in application in case of",
|
|
1228
|
+
"description": "It includes the list of commonly used dependencies in the child-apps\nBy default, it is enabled in application in case of tramvai/module-child-app is specified in package.json\nand for child-apps",
|
|
1229
|
+
"type": "boolean"
|
|
1230
|
+
},
|
|
1231
|
+
"flexibleTramvaiVersions": {
|
|
1232
|
+
"title": "add caret range specifier for tramvai dependencies",
|
|
1233
|
+
"description": "minimal versions are inferred from package.json",
|
|
1234
|
+
"default": true,
|
|
1229
1235
|
"type": "boolean"
|
|
1230
1236
|
},
|
|
1231
1237
|
"deps": {
|
|
@@ -1746,7 +1752,13 @@
|
|
|
1746
1752
|
"properties": {
|
|
1747
1753
|
"defaultTramvaiDependencies": {
|
|
1748
1754
|
"title": "Should default dependencies list be added to shared list",
|
|
1749
|
-
"description": "It includes the list of commonly used dependencies in the child-apps\nBy default, it is enabled in application in case of",
|
|
1755
|
+
"description": "It includes the list of commonly used dependencies in the child-apps\nBy default, it is enabled in application in case of tramvai/module-child-app is specified in package.json\nand for child-apps",
|
|
1756
|
+
"type": "boolean"
|
|
1757
|
+
},
|
|
1758
|
+
"flexibleTramvaiVersions": {
|
|
1759
|
+
"title": "add caret range specifier for tramvai dependencies",
|
|
1760
|
+
"description": "minimal versions are inferred from package.json",
|
|
1761
|
+
"default": true,
|
|
1750
1762
|
"type": "boolean"
|
|
1751
1763
|
},
|
|
1752
1764
|
"deps": {
|
|
@@ -2267,7 +2279,13 @@
|
|
|
2267
2279
|
"properties": {
|
|
2268
2280
|
"defaultTramvaiDependencies": {
|
|
2269
2281
|
"title": "Should default dependencies list be added to shared list",
|
|
2270
|
-
"description": "It includes the list of commonly used dependencies in the child-apps\nBy default, it is enabled in application in case of",
|
|
2282
|
+
"description": "It includes the list of commonly used dependencies in the child-apps\nBy default, it is enabled in application in case of tramvai/module-child-app is specified in package.json\nand for child-apps",
|
|
2283
|
+
"type": "boolean"
|
|
2284
|
+
},
|
|
2285
|
+
"flexibleTramvaiVersions": {
|
|
2286
|
+
"title": "add caret range specifier for tramvai dependencies",
|
|
2287
|
+
"description": "minimal versions are inferred from package.json",
|
|
2288
|
+
"default": true,
|
|
2271
2289
|
"type": "boolean"
|
|
2272
2290
|
},
|
|
2273
2291
|
"deps": {
|
|
@@ -126,6 +126,7 @@ describe('JSON schema для tramvai.json', () => {
|
|
|
126
126
|
"serverApiDir": "src/api",
|
|
127
127
|
"shared": {
|
|
128
128
|
"deps": [],
|
|
129
|
+
"flexibleTramvaiVersions": true,
|
|
129
130
|
},
|
|
130
131
|
"sourceMap": false,
|
|
131
132
|
"splitChunks": {
|
|
@@ -182,6 +183,7 @@ describe('JSON schema для tramvai.json', () => {
|
|
|
182
183
|
"root": "src/module",
|
|
183
184
|
"shared": {
|
|
184
185
|
"deps": [],
|
|
186
|
+
"flexibleTramvaiVersions": true,
|
|
185
187
|
},
|
|
186
188
|
"sourceMap": false,
|
|
187
189
|
"terser": {
|
|
@@ -287,10 +287,16 @@ export interface CliConfigEntry extends ConfigEntry {
|
|
|
287
287
|
/**
|
|
288
288
|
* @title Should default dependencies list be added to shared list
|
|
289
289
|
* @description It includes the list of commonly used dependencies in the child-apps
|
|
290
|
-
* By default, it is enabled in application in case of
|
|
290
|
+
* By default, it is enabled in application in case of tramvai/module-child-app is specified in package.json
|
|
291
291
|
* and for child-apps
|
|
292
292
|
*/
|
|
293
293
|
defaultTramvaiDependencies?: boolean;
|
|
294
|
+
/**
|
|
295
|
+
* @title add caret range specifier for tramvai dependencies
|
|
296
|
+
* @description minimal versions are inferred from package.json
|
|
297
|
+
* @default true
|
|
298
|
+
*/
|
|
299
|
+
flexibleTramvaiVersions: boolean;
|
|
294
300
|
/**
|
|
295
301
|
* @title list of the dependencies that will be shared
|
|
296
302
|
* @default []
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// map of packages that is not in unified versioning
|
|
2
|
+
// but we still want to update it
|
|
3
|
+
// actual version to update will be calculated from the some of the @tramvai/module
|
|
4
|
+
export const DEPENDANT_LIBS_MAP = new Map([
|
|
5
|
+
['@tinkoff/logger', '@tramvai/module-log'],
|
|
6
|
+
['@tinkoff/dippy', '@tramvai/core'],
|
|
7
|
+
['@tinkoff/router', '@tramvai/module-router'],
|
|
8
|
+
['@tinkoff/url', '@tramvai/module-common'],
|
|
9
|
+
['@tinkoff/errors', '@tramvai/module-common'],
|
|
10
|
+
['@tinkoff/roles', '@tramvai/module-authenticate'],
|
|
11
|
+
['@tinkoff/pubsub', '@tramvai/module-common'],
|
|
12
|
+
['@tinkoff/hook-runner', '@tramvai/module-common'],
|
|
13
|
+
['@tinkoff/htmlpagebuilder', '@tramvai/module-render'],
|
|
14
|
+
['@tinkoff/browser-timings', '@tramvai/module-metrics'],
|
|
15
|
+
['@tinkoff/meta-tags-generate', '@tramvai/module-render'],
|
|
16
|
+
['@tinkoff/pack-polyfills', ''],
|
|
17
|
+
['@tinkoff/browserslist-config', '@tramvai/cli'],
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
export const isUnifiedVersion = (name: string) => {
|
|
21
|
+
return name.startsWith('@tramvai');
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const isDependantLib = (name: string) => {
|
|
25
|
+
return DEPENDANT_LIBS_MAP.has(name);
|
|
26
|
+
};
|