@tramvai/cli 2.112.0 → 2.117.2
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/api/benchmark/build.js +6 -9
- package/lib/api/benchmark/build.js.map +1 -1
- package/lib/api/benchmark/index.js +4 -0
- package/lib/api/benchmark/index.js.map +1 -1
- package/lib/api/benchmark/start.js +10 -10
- package/lib/api/benchmark/start.js.map +1 -1
- package/lib/api/benchmark/types.d.ts +2 -0
- package/lib/api/benchmark/utils/stats.d.ts +6 -1
- package/lib/api/benchmark/utils/stats.js +9 -1
- package/lib/api/benchmark/utils/stats.js.map +1 -1
- package/lib/api/build/index.d.ts +1 -0
- package/lib/api/build/index.js.map +1 -1
- package/lib/api/start/index.d.ts +1 -0
- package/lib/api/start/index.js.map +1 -1
- package/lib/builder/webpack/providers/shared.js +12 -3
- package/lib/builder/webpack/providers/shared.js.map +1 -1
- package/lib/builder/webpack/utils/maxMemoryRss.d.ts +1 -0
- package/lib/builder/webpack/utils/maxMemoryRss.js +15 -0
- package/lib/builder/webpack/utils/maxMemoryRss.js.map +1 -0
- package/lib/builder/webpack/utils/runWebpack.js +6 -0
- package/lib/builder/webpack/utils/runWebpack.js.map +1 -1
- package/lib/commands/benchmark/benchmark.js +15 -7
- package/lib/commands/benchmark/benchmark.js.map +1 -1
- package/lib/config/constants.js +1 -1
- package/lib/config/constants.js.map +1 -1
- package/lib/di/providers/builder.js +10 -0
- package/lib/di/providers/builder.js.map +1 -1
- package/lib/di/tokens/builder.d.ts +5 -0
- package/lib/di/tokens/builder.js +2 -1
- package/lib/di/tokens/builder.js.map +1 -1
- package/lib/library/babel/plugins/fill-action-name.js +1 -2
- package/lib/library/babel/plugins/fill-action-name.js.map +1 -1
- package/lib/library/swc/index.d.ts +2 -2
- package/lib/library/swc/index.js +2 -4
- package/lib/library/swc/index.js.map +1 -1
- package/lib/library/webpack/blocks/js.js +25 -47
- package/lib/library/webpack/blocks/js.js.map +1 -1
- package/lib/library/webpack/blocks/pagesResolve.js.map +1 -1
- package/lib/library/webpack/blocks/pwa/client.js +1 -1
- package/lib/library/webpack/blocks/pwa/client.js.map +1 -1
- package/lib/library/webpack/blocks/serverInline.d.ts +1 -1
- package/lib/library/webpack/blocks/serverInline.js +8 -12
- package/lib/library/webpack/blocks/serverInline.js.map +1 -1
- package/lib/library/webpack/blocks/ts.d.ts +1 -1
- package/lib/library/webpack/blocks/ts.js +6 -6
- package/lib/library/webpack/blocks/ts.js.map +1 -1
- package/lib/library/webpack/loaders/pagesResolve.d.ts +2 -2
- package/lib/library/webpack/loaders/pagesResolve.js +9 -3
- package/lib/library/webpack/loaders/pagesResolve.js.map +1 -1
- package/lib/library/webpack/plugins/ModuleFederationFixRange.d.ts +1 -1
- package/lib/library/webpack/plugins/ModuleFederationFixRange.js +70 -68
- package/lib/library/webpack/plugins/ModuleFederationFixRange.js.map +1 -1
- package/lib/library/webpack/plugins/WebpackBar/utils/log-update.js +7 -1
- package/lib/library/webpack/plugins/WebpackBar/utils/log-update.js.map +1 -1
- package/lib/library/webpack/utils/files.js +4 -2
- package/lib/library/webpack/utils/files.js.map +1 -1
- package/lib/library/webpack/utils/transpiler.d.ts +1 -1
- package/lib/library/webpack/utils/transpiler.js +1 -1
- package/lib/library/webpack/utils/transpiler.js.map +1 -1
- package/lib/schema/autogeneratedSchema.json +4 -0
- package/lib/typings/build/Builder.d.ts +1 -0
- package/lib/typings/configEntry/application.d.ts +4 -0
- package/package.json +9 -7
- package/schema.json +4 -0
- package/src/api/benchmark/build.ts +4 -14
- package/src/api/benchmark/index.ts +9 -1
- package/src/api/benchmark/start.ts +7 -14
- package/src/api/benchmark/types.ts +6 -1
- package/src/api/benchmark/utils/stats.ts +17 -1
- package/src/api/build/index.ts +1 -0
- package/src/api/start/__integration__/start.test.ts +2 -2
- package/src/api/start/index.ts +1 -0
- package/src/builder/webpack/providers/shared.ts +15 -4
- package/src/builder/webpack/utils/maxMemoryRss.ts +12 -0
- package/src/builder/webpack/utils/runWebpack.ts +9 -0
- package/src/commands/benchmark/benchmark.ts +17 -7
- package/src/config/constants.ts +1 -1
- package/src/di/providers/builder.ts +10 -0
- package/src/di/tokens/builder.ts +2 -0
- package/src/library/babel/plugins/fill-action-name.ts +1 -2
- package/src/library/swc/__integration__/__snapshots__/swc.build.test.ts.snap +7 -24
- package/src/library/swc/__integration__/__snapshots__/swc.start.test.ts.snap +11 -23
- package/src/library/swc/index.ts +4 -6
- package/src/library/webpack/blocks/js.ts +27 -51
- package/src/library/webpack/blocks/pagesResolve.ts +2 -1
- package/src/library/webpack/blocks/pwa/client.ts +1 -1
- package/src/library/webpack/blocks/serverInline.ts +14 -12
- package/src/library/webpack/blocks/ts.ts +6 -7
- package/src/library/webpack/loaders/pagesResolve.ts +12 -4
- package/src/library/webpack/plugins/ModuleFederationFixRange.ts +92 -87
- package/src/library/webpack/plugins/WebpackBar/utils/log-update.ts +7 -1
- package/src/library/webpack/utils/files.ts +9 -6
- package/src/library/webpack/utils/transpiler.ts +16 -18
- package/src/schema/autogeneratedSchema.json +4 -0
- package/src/typings/build/Builder.ts +1 -0
- package/src/typings/configEntry/application.ts +4 -0
- /package/src/api/start/__integration__/__fixtures__/app/routes/{about.tsx → about/index.tsx} +0 -0
- /package/src/api/start/__integration__/__fixtures__/app/routes/{home.tsx → home/index.tsx} +0 -0
package/src/library/swc/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import browserslist from 'browserslist';
|
|
|
5
5
|
import envTargets from '@tinkoff/browserslist-config';
|
|
6
6
|
import { sync as resolve } from 'resolve';
|
|
7
7
|
import findCacheDir from 'find-cache-dir';
|
|
8
|
-
import type {
|
|
8
|
+
import type { Options as SwcOptions } from '@swc/core';
|
|
9
9
|
import type { TranspilerConfig } from '../webpack/utils/transpiler';
|
|
10
10
|
|
|
11
11
|
const TRAMVAI_SWC_TARGET_PATH = '@tramvai/swc-integration/target/wasm32-wasi';
|
|
@@ -13,7 +13,7 @@ const TRAMVAI_SWC_TARGET_PATH = '@tramvai/swc-integration/target/wasm32-wasi';
|
|
|
13
13
|
const NOT_SUPPORTED_FIELDS = ['alias', 'generateDataQaTag', 'enableFillActionNamePlugin'];
|
|
14
14
|
let warningWasShown = false;
|
|
15
15
|
|
|
16
|
-
export const getSwcOptions = (config: TranspilerConfig):
|
|
16
|
+
export const getSwcOptions = (config: TranspilerConfig): SwcOptions => {
|
|
17
17
|
const {
|
|
18
18
|
env = 'development',
|
|
19
19
|
target,
|
|
@@ -109,9 +109,9 @@ Having swc config may conflict with @tramvai/cli configuration`
|
|
|
109
109
|
module: {
|
|
110
110
|
type: modules || 'es6',
|
|
111
111
|
},
|
|
112
|
+
isModule: 'unknown',
|
|
112
113
|
jsc: {
|
|
113
|
-
|
|
114
|
-
// externalHelpers: true,
|
|
114
|
+
externalHelpers: true,
|
|
115
115
|
parser: {
|
|
116
116
|
syntax: typescript ? 'typescript' : 'ecmascript',
|
|
117
117
|
decorators: true,
|
|
@@ -129,8 +129,6 @@ Having swc config may conflict with @tramvai/cli configuration`
|
|
|
129
129
|
globals: {
|
|
130
130
|
// let the webpack replace NODE_ENV as replacement with swc may mess up with tests
|
|
131
131
|
envs: [],
|
|
132
|
-
// @ts-ignore
|
|
133
|
-
// TODO: there is not typings for typeofs, but the field is mentioned in docs
|
|
134
132
|
typeofs: removeTypeofWindow
|
|
135
133
|
? {
|
|
136
134
|
window: isServer ? 'undefined' : 'object',
|
|
@@ -2,7 +2,6 @@ import type Config from 'webpack-chain';
|
|
|
2
2
|
import { modernLibsFilter } from '@tinkoff/is-modern-lib';
|
|
3
3
|
import { createWorkerPoolTranspiler } from '../utils/workersPool';
|
|
4
4
|
import type { ConfigManager } from '../../../config/configManager';
|
|
5
|
-
import type { TranspilerConfig } from '../utils/transpiler';
|
|
6
5
|
import { getTranspilerConfig, addTranspilerLoader } from '../utils/transpiler';
|
|
7
6
|
import type { CliConfigEntry } from '../../../typings/configEntry/cli';
|
|
8
7
|
|
|
@@ -10,56 +9,33 @@ import type { CliConfigEntry } from '../../../typings/configEntry/cli';
|
|
|
10
9
|
export default (configManager: ConfigManager<CliConfigEntry>) => (config: Config) => {
|
|
11
10
|
const { transpileOnlyModernLibs } = configManager;
|
|
12
11
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
)
|
|
25
|
-
.use('transpiler');
|
|
12
|
+
const rule = config.module
|
|
13
|
+
.rule('js')
|
|
14
|
+
.test(/\.[cm]?js[x]?$/)
|
|
15
|
+
// TODO: разобраться почему на винде все плохо с thread-loader
|
|
16
|
+
.when(process.platform !== 'win32' && !configManager.debug, (cfg) =>
|
|
17
|
+
cfg
|
|
18
|
+
.use('thread')
|
|
19
|
+
.loader('thread-loader')
|
|
20
|
+
.options(createWorkerPoolTranspiler(configManager))
|
|
21
|
+
.end()
|
|
22
|
+
);
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
rule
|
|
25
|
+
.oneOf('project')
|
|
26
|
+
.exclude.add(/node_modules/)
|
|
27
|
+
.end()
|
|
28
|
+
.use('transpiler')
|
|
29
|
+
.batch(addTranspilerLoader(configManager, getTranspilerConfig(configManager)));
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
.end()
|
|
41
|
-
.batch(jsRule(getTranspilerConfig(configManager, { hot: false })))
|
|
42
|
-
.merge({
|
|
43
|
-
// TODO: некоторые пакеты неправильно описывают импорты для es модулей
|
|
44
|
-
// https://github.com/babel/babel/issues/12058
|
|
45
|
-
resolve: { fullySpecified: false },
|
|
46
|
-
});
|
|
47
|
-
} else {
|
|
48
|
-
config.module
|
|
49
|
-
.rule('js:project')
|
|
50
|
-
.exclude.add(/node_modules/)
|
|
51
|
-
.end()
|
|
52
|
-
.batch(jsRule(getTranspilerConfig(configManager)));
|
|
53
|
-
|
|
54
|
-
config.module
|
|
55
|
-
.rule('js:node_modules')
|
|
56
|
-
.include.add(/node_modules/)
|
|
57
|
-
.end()
|
|
58
|
-
.batch(jsRule(getTranspilerConfig(configManager, { hot: false })))
|
|
59
|
-
.merge({
|
|
60
|
-
// TODO: некоторые пакеты неправильно описывают импорты для es модулей
|
|
61
|
-
// https://github.com/babel/babel/issues/12058
|
|
62
|
-
resolve: { fullySpecified: false },
|
|
63
|
-
});
|
|
64
|
-
}
|
|
31
|
+
rule
|
|
32
|
+
.oneOf('node_module')
|
|
33
|
+
.when(transpileOnlyModernLibs, (cfg) => cfg.include.add(modernLibsFilter))
|
|
34
|
+
.merge({
|
|
35
|
+
// true value forces to use file extensions for importing mjs modules
|
|
36
|
+
// but we want to use mjs if it exists anyway
|
|
37
|
+
resolve: { fullySpecified: false },
|
|
38
|
+
})
|
|
39
|
+
.use('transpiler')
|
|
40
|
+
.batch(addTranspilerLoader(configManager, getTranspilerConfig(configManager, { hot: false })));
|
|
65
41
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import type Config from 'webpack-chain';
|
|
3
|
+
import type { PagesResolveOptions } from '../loaders/pagesResolve';
|
|
3
4
|
import type { ConfigManager } from '../../../config/configManager';
|
|
4
5
|
import type { ApplicationConfigEntry } from '../../../typings/configEntry/application';
|
|
5
6
|
|
|
@@ -20,7 +21,7 @@ export const pagesResolve =
|
|
|
20
21
|
rootDir: configManager.rootDir,
|
|
21
22
|
root: configManager.root,
|
|
22
23
|
extensions: config.resolve.extensions.values(),
|
|
23
|
-
})
|
|
24
|
+
} as PagesResolveOptions)
|
|
24
25
|
.end()
|
|
25
26
|
// babel-loader is required to process this file
|
|
26
27
|
.enforce('pre');
|
|
@@ -26,7 +26,7 @@ export const pwaBlock =
|
|
|
26
26
|
config.batch(pwaSharedBlock(configManager));
|
|
27
27
|
|
|
28
28
|
if (
|
|
29
|
-
!safeRequireResolve('@tramvai/module-progressive-web-app') &&
|
|
29
|
+
!safeRequireResolve('@tramvai/module-progressive-web-app', true) &&
|
|
30
30
|
(pwa.workbox?.enabled || pwa.webmanifest?.enabled)
|
|
31
31
|
) {
|
|
32
32
|
throw Error('PWA functional requires @tramvai/module-progressive-web-app installed');
|
|
@@ -1,25 +1,27 @@
|
|
|
1
|
-
import Config from 'webpack-chain';
|
|
1
|
+
import type Config from 'webpack-chain';
|
|
2
2
|
import type { ConfigManager } from '../../../config/configManager';
|
|
3
3
|
import type { CliConfigEntry } from '../../../typings/configEntry/cli';
|
|
4
|
-
import
|
|
5
|
-
import ts from './ts';
|
|
4
|
+
import { addTranspilerLoader, getTranspilerConfig } from '../utils/transpiler';
|
|
6
5
|
|
|
7
6
|
export const serverInline = (configManager: ConfigManager<CliConfigEntry>) => (config: Config) => {
|
|
8
7
|
// создаём клиентский конфиг и отключаем modern режим
|
|
9
8
|
const clientConfigManager = configManager.withSettings({ buildType: 'client', modern: false });
|
|
10
9
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
const addInlineHandler = (type: string, extension: string) => {
|
|
10
|
+
const addInlineHandler = (type: string) => {
|
|
14
11
|
config.module
|
|
15
12
|
.rule(type)
|
|
16
13
|
.oneOf('inline')
|
|
17
|
-
.before('
|
|
18
|
-
.test(new RegExp(`\\.inline(\\.es)?\\.${
|
|
19
|
-
.
|
|
14
|
+
.before('project')
|
|
15
|
+
.test(new RegExp(`\\.inline(\\.es)?\\.${type}$`))
|
|
16
|
+
.use('transpiler')
|
|
17
|
+
.batch(
|
|
18
|
+
addTranspilerLoader(
|
|
19
|
+
clientConfigManager,
|
|
20
|
+
getTranspilerConfig(clientConfigManager, { typescript: type === 'ts' })
|
|
21
|
+
)
|
|
22
|
+
);
|
|
20
23
|
};
|
|
21
24
|
|
|
22
|
-
addInlineHandler('js
|
|
23
|
-
addInlineHandler('
|
|
24
|
-
addInlineHandler('ts:project', 'ts');
|
|
25
|
+
addInlineHandler('js');
|
|
26
|
+
addInlineHandler('ts');
|
|
25
27
|
};
|
|
@@ -7,13 +7,12 @@ import type { CliConfigEntry } from '../../../typings/configEntry/cli';
|
|
|
7
7
|
export default (configManager: ConfigManager<CliConfigEntry>) => (config: Config) => {
|
|
8
8
|
const transpilerConfig = getTranspilerConfig(configManager, { typescript: true });
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
.rule('ts
|
|
10
|
+
config.module
|
|
11
|
+
.rule('ts')
|
|
12
12
|
.test(/\.ts[x]?$/)
|
|
13
13
|
.exclude.add(/node_modules/)
|
|
14
14
|
.end()
|
|
15
|
-
|
|
16
|
-
// TODO разобраться почему на винде все плохо с thread-loader
|
|
15
|
+
// TODO: разобраться почему на винде все плохо с thread-loader
|
|
17
16
|
.when(process.platform !== 'win32', (cfg) =>
|
|
18
17
|
cfg
|
|
19
18
|
.use('thread')
|
|
@@ -21,7 +20,7 @@ export default (configManager: ConfigManager<CliConfigEntry>) => (config: Config
|
|
|
21
20
|
.options(createWorkerPoolTranspiler(configManager))
|
|
22
21
|
.end()
|
|
23
22
|
)
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
.oneOf('project')
|
|
24
|
+
.use('transpiler')
|
|
25
|
+
.batch(addTranspilerLoader(configManager, transpilerConfig));
|
|
27
26
|
};
|
|
@@ -8,7 +8,7 @@ const LAYOUT_FILENAME = '_layout.tsx';
|
|
|
8
8
|
const ERROR_BOUNDARY_FILENAME = '_error.tsx';
|
|
9
9
|
const WILDCARD_TOKEN = '[...';
|
|
10
10
|
|
|
11
|
-
interface
|
|
11
|
+
export interface PagesResolveOptions {
|
|
12
12
|
rootDir: string;
|
|
13
13
|
root: string;
|
|
14
14
|
extensions: string[];
|
|
@@ -22,8 +22,9 @@ const removeExtension = (filename: string): string => {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
// eslint-disable-next-line func-style
|
|
25
|
-
const pagesResolve: LoaderDefinitionFunction<
|
|
25
|
+
const pagesResolve: LoaderDefinitionFunction<PagesResolveOptions> = function () {
|
|
26
26
|
const { fileSystemPages, rootDir, root, extensions } = this.getOptions();
|
|
27
|
+
const extensionsRegexp = new RegExp(`\\.(${extensions.map((ext) => ext.slice(1)).join('|')})$`);
|
|
27
28
|
const fsLayouts: string[] = [];
|
|
28
29
|
const fsErrorBoundaries: string[] = [];
|
|
29
30
|
const fsWildcards: string[] = [];
|
|
@@ -34,9 +35,11 @@ const pagesResolve: LoaderDefinitionFunction<Options> = function () {
|
|
|
34
35
|
const filesToPages = ({
|
|
35
36
|
pagesRootDirectory,
|
|
36
37
|
isRoutes = false,
|
|
38
|
+
test,
|
|
37
39
|
}: {
|
|
38
40
|
pagesRootDirectory: string;
|
|
39
41
|
isRoutes?: boolean;
|
|
42
|
+
test: RegExp;
|
|
40
43
|
}) => {
|
|
41
44
|
const pagesDir = path.resolve(rootDir, root, pagesRootDirectory);
|
|
42
45
|
|
|
@@ -51,9 +54,10 @@ const pagesResolve: LoaderDefinitionFunction<Options> = function () {
|
|
|
51
54
|
|
|
52
55
|
for (const file of pagesFiles) {
|
|
53
56
|
const extname = path.extname(file);
|
|
54
|
-
const
|
|
57
|
+
const normalizedFile = file.replace(/\\/g, '/');
|
|
55
58
|
|
|
56
|
-
if (
|
|
59
|
+
if (test.test(normalizedFile)) {
|
|
60
|
+
const name = normalizedFile.replace(new RegExp(`\\${extname}$`), '');
|
|
57
61
|
const pageComponentName = `@/${pagesRootDirectory}/${name}`;
|
|
58
62
|
const pageComponentPath = path.resolve(pagesDir, name).replace(/\\/g, '\\\\');
|
|
59
63
|
const chunkname = pageComponentName.replace(/\//g, '_');
|
|
@@ -112,11 +116,15 @@ const pagesResolve: LoaderDefinitionFunction<Options> = function () {
|
|
|
112
116
|
? filesToPages({
|
|
113
117
|
pagesRootDirectory: fileSystemPages.routesDir,
|
|
114
118
|
isRoutes: true,
|
|
119
|
+
test: new RegExp(`index${extensionsRegexp.source}`),
|
|
115
120
|
})
|
|
116
121
|
: [];
|
|
117
122
|
const fsPages = fileSystemPages.pagesDir
|
|
118
123
|
? filesToPages({
|
|
119
124
|
pagesRootDirectory: fileSystemPages.pagesDir,
|
|
125
|
+
test: fileSystemPages.componentsPattern
|
|
126
|
+
? new RegExp(fileSystemPages.componentsPattern)
|
|
127
|
+
: extensionsRegexp,
|
|
120
128
|
})
|
|
121
129
|
: [];
|
|
122
130
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type webpack from 'webpack';
|
|
2
2
|
import type { Compiler, NormalModule } from 'webpack';
|
|
3
|
-
import {
|
|
4
|
-
import type packageJson from 'package-json';
|
|
5
|
-
import chalk from 'chalk';
|
|
3
|
+
import { WebpackError } from 'webpack';
|
|
6
4
|
// eslint-disable-next-line no-restricted-imports
|
|
7
|
-
import { parseRange } from 'webpack/lib/util/semver';
|
|
5
|
+
import { parseRange, satisfy } from 'webpack/lib/util/semver';
|
|
8
6
|
import { isDependantLib, isUnifiedVersion } from '../../../utils/tramvaiVersions';
|
|
9
7
|
|
|
10
8
|
const PLUGIN_NAME = 'ModuleFederationValidateDuplicates';
|
|
@@ -22,19 +20,6 @@ interface SharedModule extends NormalModule {
|
|
|
22
20
|
options?: SharedModuleOptions;
|
|
23
21
|
}
|
|
24
22
|
|
|
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
23
|
export interface ModuleFederationFixRangeOptions {
|
|
39
24
|
flexibleTramvaiVersions: boolean;
|
|
40
25
|
}
|
|
@@ -42,14 +27,14 @@ export interface ModuleFederationFixRangeOptions {
|
|
|
42
27
|
export class ModuleFederationFixRange implements webpack.WebpackPluginInstance {
|
|
43
28
|
private flexibleTramvaiVersions: boolean;
|
|
44
29
|
// { name: { importResolved: { number }} }
|
|
45
|
-
private sharedModules: Map<string, Map<string, Set<
|
|
30
|
+
private sharedModules: Map<string, Map<string, Set<SharedModule>>> = new Map();
|
|
46
31
|
|
|
47
32
|
constructor({ flexibleTramvaiVersions }: ModuleFederationFixRangeOptions) {
|
|
48
33
|
this.flexibleTramvaiVersions = flexibleTramvaiVersions ?? false;
|
|
49
34
|
}
|
|
50
35
|
|
|
51
36
|
apply(compiler: Compiler) {
|
|
52
|
-
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (
|
|
37
|
+
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory }) => {
|
|
53
38
|
normalModuleFactory.hooks.factorize.intercept({
|
|
54
39
|
register: (tap) => {
|
|
55
40
|
if (tap.name === 'ConsumeSharedPlugin') {
|
|
@@ -59,7 +44,24 @@ export class ModuleFederationFixRange implements webpack.WebpackPluginInstance {
|
|
|
59
44
|
const module: SharedModule | undefined = await originalFn(...args);
|
|
60
45
|
|
|
61
46
|
if (module?.options) {
|
|
62
|
-
|
|
47
|
+
const { shareKey: name, importResolved } = module.options;
|
|
48
|
+
|
|
49
|
+
let shared = this.sharedModules.get(name);
|
|
50
|
+
|
|
51
|
+
if (!shared) {
|
|
52
|
+
shared = new Map();
|
|
53
|
+
this.sharedModules.set(name, shared);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let modules = shared.get(importResolved);
|
|
57
|
+
|
|
58
|
+
if (!modules) {
|
|
59
|
+
modules = new Set();
|
|
60
|
+
shared.set(importResolved, modules);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// save major version of the semver array
|
|
64
|
+
modules.add(module);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
return module;
|
|
@@ -69,71 +71,91 @@ export class ModuleFederationFixRange implements webpack.WebpackPluginInstance {
|
|
|
69
71
|
return tap;
|
|
70
72
|
},
|
|
71
73
|
});
|
|
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
74
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
75
|
+
// eslint-disable-next-line max-statements
|
|
76
|
+
compilation.hooks.optimizeDependencies.tap(PLUGIN_NAME, () => {
|
|
77
|
+
for (const [name, sharedModulesByName] of this.sharedModules.entries()) {
|
|
78
|
+
const hasDuplicates = sharedModulesByName.size > 1;
|
|
79
|
+
|
|
80
|
+
for (const [importResolved, sharedModulesByPath] of sharedModulesByName.entries()) {
|
|
81
|
+
if (hasDuplicates) {
|
|
82
|
+
const error = new WebpackError(
|
|
83
|
+
`This file is a duplicate for a module "${name}" that resolved to different path`
|
|
84
|
+
);
|
|
85
|
+
error.file = importResolved;
|
|
86
|
+
compilation.warnings.push(error);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let validModule: SharedModule;
|
|
90
|
+
let validVersion: string;
|
|
91
|
+
const invalidModules = new Set<SharedModule>();
|
|
92
|
+
|
|
93
|
+
for (const sharedModule of sharedModulesByPath) {
|
|
94
|
+
const connections = compilation.moduleGraph.getOutgoingConnections(sharedModule);
|
|
95
|
+
|
|
96
|
+
for (const { module } of connections) {
|
|
97
|
+
const resolvedVersion = module.resourceResolveData?.descriptionFileData?.version;
|
|
98
|
+
this.fixVersionRange(sharedModule, resolvedVersion);
|
|
99
|
+
|
|
100
|
+
const requiredVersion = sharedModule?.options?.requiredVersion;
|
|
101
|
+
|
|
102
|
+
if (requiredVersion && resolvedVersion) {
|
|
103
|
+
if (satisfy(requiredVersion, resolvedVersion)) {
|
|
104
|
+
validModule = sharedModule;
|
|
105
|
+
validVersion = resolvedVersion;
|
|
106
|
+
} else {
|
|
107
|
+
invalidModules.add(sharedModule);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// there should by only one outgoing module for ConsumeSharedModule
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (invalidModules.size > 0 && validModule) {
|
|
116
|
+
for (const sharedModule of invalidModules) {
|
|
117
|
+
const error = new WebpackError(
|
|
118
|
+
`Shared module has been actually resolved to ${validVersion} instead of the expected`
|
|
119
|
+
);
|
|
120
|
+
error.module = sharedModule;
|
|
121
|
+
compilation.warnings.push(error);
|
|
122
|
+
|
|
123
|
+
// replace invalid module with valid version (invalid anyway are resolved to wrong version)
|
|
124
|
+
// to prevent any issues with shared dependencies
|
|
125
|
+
compilation.moduleGraph.moveModuleConnections(
|
|
126
|
+
sharedModule,
|
|
127
|
+
validModule,
|
|
128
|
+
(connection) => {
|
|
129
|
+
// ignore any outgoing connections as we want to ignore that module entirely and all its dependencies
|
|
130
|
+
return connection.originModule !== sharedModule;
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
89
135
|
}
|
|
90
136
|
}
|
|
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
137
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
}
|
|
138
|
+
// reset sharedModules info after validation
|
|
139
|
+
this.sharedModules = new Map();
|
|
140
|
+
});
|
|
120
141
|
});
|
|
121
142
|
}
|
|
122
143
|
|
|
123
|
-
fixVersionRange(
|
|
144
|
+
fixVersionRange(sharedModule: SharedModule, resolvedVersion?: string) {
|
|
124
145
|
const {
|
|
125
146
|
options,
|
|
126
|
-
options: { shareKey: name, singleton
|
|
147
|
+
options: { shareKey: name, singleton },
|
|
127
148
|
context,
|
|
128
|
-
} =
|
|
149
|
+
} = sharedModule;
|
|
129
150
|
let { requiredVersion } = options;
|
|
130
151
|
|
|
152
|
+
// if version was not resolved automatically then get the version
|
|
153
|
+
// from actual module
|
|
131
154
|
// ignore singletons as the actual version won't change anything
|
|
132
155
|
// and usually it is just a react and co libraries
|
|
133
156
|
if (!requiredVersion && context && !singleton) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
requiredVersion = parseRange(version);
|
|
157
|
+
if (resolvedVersion) {
|
|
158
|
+
requiredVersion = parseRange(resolvedVersion);
|
|
137
159
|
}
|
|
138
160
|
}
|
|
139
161
|
|
|
@@ -153,22 +175,5 @@ ${criticalDuplicates
|
|
|
153
175
|
|
|
154
176
|
// change version in webpack module
|
|
155
177
|
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
178
|
}
|
|
174
179
|
}
|
|
@@ -69,6 +69,7 @@ export default class LogUpdate {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
this._onData(data);
|
|
72
|
+
return stream.write[originalWrite].call(stream, data, ...args);
|
|
72
73
|
};
|
|
73
74
|
|
|
74
75
|
// Backup original write fn
|
|
@@ -93,7 +94,12 @@ export default class LogUpdate {
|
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
_onData(data) {
|
|
96
|
-
|
|
97
|
+
const str = String(data);
|
|
98
|
+
const lines = str.split('\n').length - 1;
|
|
99
|
+
if (lines > 0) {
|
|
100
|
+
this.prevLineCount += lines;
|
|
101
|
+
this.extraLines += data;
|
|
102
|
+
}
|
|
97
103
|
}
|
|
98
104
|
|
|
99
105
|
render(lines) {
|
|
@@ -14,12 +14,15 @@ export const addSvgrLoader = (
|
|
|
14
14
|
.rule('svgr')
|
|
15
15
|
.test(/\.svg$/)
|
|
16
16
|
// @todo: `issuer: /\.tsx?$/` нужен или нет?
|
|
17
|
-
.set('resourceQuery', /react/)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
.set('resourceQuery', /react/)
|
|
18
|
+
.use('svgr-transpiler')
|
|
19
|
+
.batch(
|
|
20
|
+
addTranspilerLoader(configManager, {
|
|
21
|
+
...transpilerConfig,
|
|
22
|
+
typescript: true,
|
|
23
|
+
})
|
|
24
|
+
)
|
|
25
|
+
.end();
|
|
23
26
|
|
|
24
27
|
svgrConfig.use('svgr').loader('@svgr/webpack').options({ babel: false, svgo: svgoOptions }).end();
|
|
25
28
|
};
|
|
@@ -25,29 +25,27 @@ export type TranspilerConfig = {
|
|
|
25
25
|
rootDir: string;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
export const addTranspilerLoader =
|
|
29
|
-
configManager: ConfigManager<CliConfigEntry>,
|
|
30
|
-
rule: Config.Use
|
|
31
|
-
|
|
32
|
-
) => {
|
|
33
|
-
const { loader } = configManager.experiments.transpilation;
|
|
28
|
+
export const addTranspilerLoader =
|
|
29
|
+
(configManager: ConfigManager<CliConfigEntry>, transpilerConfig: TranspilerConfig) =>
|
|
30
|
+
(rule: Config.Use) => {
|
|
31
|
+
const { loader } = configManager.experiments.transpilation;
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
if (loader === 'swc') {
|
|
34
|
+
try {
|
|
35
|
+
resolve('@tramvai/swc-integration/package.json', { basedir: configManager.rootDir });
|
|
36
|
+
} catch (error) {
|
|
37
|
+
throw new Error(`You are using swc loader for the transpilation, but required module is not installed.
|
|
40
38
|
Please run "npx tramvai add --dev @tramvai/swc-integration" to fix the problem
|
|
41
39
|
`);
|
|
42
|
-
|
|
40
|
+
}
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
return rule.loader('swc-loader').options(getSwcOptions(transpilerConfig)).end();
|
|
43
|
+
}
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
};
|
|
45
|
+
if (loader === 'babel') {
|
|
46
|
+
return rule.loader('babel-loader').options(babelConfig(transpilerConfig)).end();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
51
49
|
|
|
52
50
|
export const getTranspilerConfig = (
|
|
53
51
|
configManager: ConfigManager<CliConfigEntry>,
|
|
@@ -158,6 +158,10 @@ export interface ApplicationConfigEntry extends CliConfigEntry {
|
|
|
158
158
|
* @default "pages"
|
|
159
159
|
*/
|
|
160
160
|
pagesDir: string | false;
|
|
161
|
+
/**
|
|
162
|
+
* @title Test Regexp to add only files with specific name to list of FS Components
|
|
163
|
+
*/
|
|
164
|
+
componentsPattern: string;
|
|
161
165
|
};
|
|
162
166
|
/**
|
|
163
167
|
* @title Configure the options on webpack splitChunks
|
/package/src/api/start/__integration__/__fixtures__/app/routes/{about.tsx → about/index.tsx}
RENAMED
|
File without changes
|
|
File without changes
|