@tramvai/cli 5.53.80 → 5.53.94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/README.md +1 -1
  2. package/lib/api/analyze/index.d.ts.map +1 -1
  3. package/lib/api/analyze/index.js +1 -13
  4. package/lib/api/analyze/index.js.map +1 -1
  5. package/lib/api/benchmark/build.d.ts +1 -6
  6. package/lib/api/benchmark/build.d.ts.map +1 -1
  7. package/lib/api/benchmark/build.js +59 -23
  8. package/lib/api/benchmark/build.js.map +1 -1
  9. package/lib/api/benchmark/const.d.ts +2 -0
  10. package/lib/api/benchmark/const.d.ts.map +1 -0
  11. package/lib/api/benchmark/const.js +5 -0
  12. package/lib/api/benchmark/const.js.map +1 -0
  13. package/lib/api/benchmark/index.d.ts +4 -6
  14. package/lib/api/benchmark/index.d.ts.map +1 -1
  15. package/lib/api/benchmark/index.js.map +1 -1
  16. package/lib/api/benchmark/start.d.ts +1 -7
  17. package/lib/api/benchmark/start.d.ts.map +1 -1
  18. package/lib/api/benchmark/start.js +56 -49
  19. package/lib/api/benchmark/start.js.map +1 -1
  20. package/lib/api/benchmark/types.d.ts +76 -12
  21. package/lib/api/benchmark/types.d.ts.map +1 -1
  22. package/lib/api/benchmark/utils/compilationUtils.d.ts +4 -0
  23. package/lib/api/benchmark/utils/compilationUtils.d.ts.map +1 -0
  24. package/lib/api/benchmark/utils/compilationUtils.js +157 -0
  25. package/lib/api/benchmark/utils/compilationUtils.js.map +1 -0
  26. package/lib/api/benchmark/utils/stats.d.ts +2 -7
  27. package/lib/api/benchmark/utils/stats.d.ts.map +1 -1
  28. package/lib/api/benchmark/utils/stats.js +36 -22
  29. package/lib/api/benchmark/utils/stats.js.map +1 -1
  30. package/lib/api/build/index.d.ts +1 -0
  31. package/lib/api/build/index.d.ts.map +1 -1
  32. package/lib/api/build/index.js.map +1 -1
  33. package/lib/api/index.js +1 -1
  34. package/lib/api/index.js.map +1 -1
  35. package/lib/api/start/index.d.ts +1 -0
  36. package/lib/api/start/index.d.ts.map +1 -1
  37. package/lib/api/start/index.js.map +1 -1
  38. package/lib/builder/webpack/analyzePlugins/rsdoctor.d.ts +5 -5
  39. package/lib/builder/webpack/analyzePlugins/rsdoctor.d.ts.map +1 -1
  40. package/lib/builder/webpack/analyzePlugins/rsdoctor.js +7 -9
  41. package/lib/builder/webpack/analyzePlugins/rsdoctor.js.map +1 -1
  42. package/lib/builder/webpack/index.d.ts.map +1 -1
  43. package/lib/builder/webpack/index.js +14 -12
  44. package/lib/builder/webpack/index.js.map +1 -1
  45. package/lib/builder/webpack/providers/build/client.d.ts.map +1 -1
  46. package/lib/builder/webpack/providers/build/client.js +3 -2
  47. package/lib/builder/webpack/providers/build/client.js.map +1 -1
  48. package/lib/builder/webpack/providers/build/server.d.ts.map +1 -1
  49. package/lib/builder/webpack/providers/build/server.js +3 -2
  50. package/lib/builder/webpack/providers/build/server.js.map +1 -1
  51. package/lib/builder/webpack/providers/shared.d.ts.map +1 -1
  52. package/lib/builder/webpack/providers/shared.js +39 -5
  53. package/lib/builder/webpack/providers/shared.js.map +1 -1
  54. package/lib/builder/webpack/providers/start/shared.d.ts.map +1 -1
  55. package/lib/builder/webpack/providers/start/shared.js +6 -2
  56. package/lib/builder/webpack/providers/start/shared.js.map +1 -1
  57. package/lib/builder/webpack/tokens.d.ts +8 -16
  58. package/lib/builder/webpack/tokens.d.ts.map +1 -1
  59. package/lib/cli/index.d.ts.map +1 -1
  60. package/lib/cli/index.js +12 -12
  61. package/lib/cli/index.js.map +1 -1
  62. package/lib/commands/analyze/command.d.ts +1 -1
  63. package/lib/commands/analyze/command.d.ts.map +1 -1
  64. package/lib/commands/benchmark/benchmark.d.ts +3 -1
  65. package/lib/commands/benchmark/benchmark.d.ts.map +1 -1
  66. package/lib/commands/benchmark/benchmark.js +130 -31
  67. package/lib/commands/benchmark/benchmark.js.map +1 -1
  68. package/lib/commands/benchmark/command.d.ts +9 -0
  69. package/lib/commands/benchmark/command.d.ts.map +1 -1
  70. package/lib/commands/benchmark/command.js +12 -0
  71. package/lib/commands/benchmark/command.js.map +1 -1
  72. package/lib/commands/build/command.d.ts.map +1 -1
  73. package/lib/commands/build/command.js +5 -0
  74. package/lib/commands/build/command.js.map +1 -1
  75. package/lib/commands/new/steps/installDependencies.js +1 -1
  76. package/lib/commands/new/steps/installDependencies.js.map +1 -1
  77. package/lib/commands/start/command.d.ts.map +1 -1
  78. package/lib/commands/start/command.js +5 -0
  79. package/lib/commands/start/command.js.map +1 -1
  80. package/lib/config/configManager.d.ts +2 -0
  81. package/lib/config/configManager.d.ts.map +1 -1
  82. package/lib/config/configManager.js +2 -0
  83. package/lib/config/configManager.js.map +1 -1
  84. package/lib/di/tokens/config.d.ts +4 -8
  85. package/lib/di/tokens/config.d.ts.map +1 -1
  86. package/lib/library/webpack/blocks/js.d.ts.map +1 -1
  87. package/lib/library/webpack/blocks/js.js +57 -11
  88. package/lib/library/webpack/blocks/js.js.map +1 -1
  89. package/lib/library/webpack/common/main.d.ts.map +1 -1
  90. package/lib/library/webpack/common/main.js +7 -0
  91. package/lib/library/webpack/common/main.js.map +1 -1
  92. package/lib/library/webpack/utils/rsdoctor.d.ts +2 -0
  93. package/lib/library/webpack/utils/rsdoctor.d.ts.map +1 -0
  94. package/lib/library/webpack/utils/rsdoctor.js +27 -0
  95. package/lib/library/webpack/utils/rsdoctor.js.map +1 -0
  96. package/lib/library/webpack/utils/threadLoader.d.ts.map +1 -1
  97. package/lib/library/webpack/utils/threadLoader.js +3 -3
  98. package/lib/library/webpack/utils/threadLoader.js.map +1 -1
  99. package/lib/schema/autogeneratedSchema.json +228 -120
  100. package/lib/typings/build/Builder.d.ts +6 -2
  101. package/lib/typings/build/Builder.d.ts.map +1 -1
  102. package/lib/typings/configEntry/cli.d.ts +5 -0
  103. package/lib/typings/configEntry/cli.d.ts.map +1 -1
  104. package/package.json +16 -17
  105. package/schema.json +228 -120
  106. package/src/api/analyze/index.ts +3 -16
  107. package/src/api/benchmark/__integration__/start.test.ts +10 -12
  108. package/src/api/benchmark/build.ts +75 -30
  109. package/src/api/benchmark/const.ts +1 -0
  110. package/src/api/benchmark/index.ts +4 -6
  111. package/src/api/benchmark/start.ts +69 -65
  112. package/src/api/benchmark/types.ts +82 -14
  113. package/src/api/benchmark/utils/compilationUtils.ts +213 -0
  114. package/src/api/benchmark/utils/stats.ts +45 -28
  115. package/src/api/build/index.ts +1 -0
  116. package/src/api/index.ts +1 -1
  117. package/src/api/start/index.ts +1 -0
  118. package/src/builder/webpack/analyzePlugins/rsdoctor.ts +11 -14
  119. package/src/builder/webpack/index.ts +16 -21
  120. package/src/builder/webpack/providers/build/client.ts +7 -2
  121. package/src/builder/webpack/providers/build/server.ts +7 -2
  122. package/src/builder/webpack/providers/shared.ts +53 -5
  123. package/src/builder/webpack/providers/start/shared.ts +7 -2
  124. package/src/cli/index.ts +3 -2
  125. package/src/commands/analyze/command.ts +1 -1
  126. package/src/commands/benchmark/benchmark.ts +168 -33
  127. package/src/commands/benchmark/command.ts +12 -0
  128. package/src/commands/build/command.ts +6 -0
  129. package/src/commands/new/steps/installDependencies.ts +1 -1
  130. package/src/commands/new/templates/shared/_prettierrc.js.hbs +1 -1
  131. package/src/commands/new/templates/shared/package.json.hbs +1 -1
  132. package/src/commands/start/command.ts +6 -0
  133. package/src/config/configManager.ts +4 -0
  134. package/src/library/webpack/blocks/js.ts +61 -12
  135. package/src/library/webpack/common/main.ts +8 -0
  136. package/src/library/webpack/utils/rsdoctor.ts +26 -0
  137. package/src/library/webpack/utils/threadLoader.ts +1 -0
  138. package/src/models/config.spec.ts +4 -0
  139. package/src/schema/autogeneratedSchema.json +228 -120
  140. package/src/schema/tramvai.spec.ts +2 -0
  141. package/src/typings/build/Builder.ts +7 -2
  142. package/src/typings/configEntry/cli.ts +6 -0
  143. package/lib/api/analyze/providers/shared.d.ts +0 -3
  144. package/lib/api/analyze/providers/shared.d.ts.map +0 -1
  145. package/lib/api/analyze/providers/shared.js +0 -23
  146. package/lib/api/analyze/providers/shared.js.map +0 -1
  147. package/lib/builder/webpack/providers/analyze/shared.d.ts +0 -3
  148. package/lib/builder/webpack/providers/analyze/shared.d.ts.map +0 -1
  149. package/lib/builder/webpack/providers/analyze/shared.js +0 -141
  150. package/lib/builder/webpack/providers/analyze/shared.js.map +0 -1
  151. package/src/api/analyze/providers/shared.ts +0 -26
  152. package/src/api/benchmark/utils/stats.spec.ts +0 -36
  153. package/src/builder/webpack/providers/analyze/shared.ts +0 -160
@@ -1,59 +1,194 @@
1
- import mdtable from 'mdtable';
2
- import prettyBytes from 'pretty-bytes';
1
+ import { table, TableUserConfig } from 'table';
2
+ import isEmpty from '@tinkoff/utils/is/empty';
3
+
3
4
  import type { Context } from '../../models/context';
4
5
  import type { CommandResult } from '../../models/command';
5
6
  import type { Result } from '../../api/benchmark';
7
+ import type { CompilationStats } from '../../api/benchmark/types';
8
+ import { DEFAULT_TIMES } from '../../api/benchmark/const';
6
9
 
7
10
  import { app } from '../index';
8
11
 
9
- const roundStats = (n: number) => Math.round(100 * n) / 100;
12
+ export function toFixedDigits(num: number, digits = 2): number {
13
+ if (digits === 0) {
14
+ return Math.floor(num);
15
+ }
16
+ return +num.toFixed(digits);
17
+ }
18
+
19
+ const getUnit = (num: number) => (num > 1 ? 'mins' : 'min');
20
+
21
+ export function formatCosts(costs: number): string {
22
+ // more than 1s
23
+ if (costs >= 1000) {
24
+ const sec = costs / 1000;
25
+ // more than 1min
26
+ if (sec >= 60) {
27
+ let mins = sec / 60;
28
+
29
+ mins = toFixedDigits(mins, 0);
30
+ const mUnit = getUnit(mins);
31
+ const restSec = toFixedDigits(sec % 60, 0);
32
+
33
+ if (restSec > 0) {
34
+ return `${mins}${mUnit} ${restSec}s`;
35
+ }
36
+ return `${mins}${mUnit}`;
37
+ }
38
+
39
+ return `${toFixedDigits(sec, 1)}s`;
40
+ }
41
+
42
+ if (costs >= 10) {
43
+ return `${+toFixedDigits(costs, 0)}ms`;
44
+ }
45
+
46
+ if (costs >= 1) {
47
+ return `${+toFixedDigits(costs, 1)}ms`;
48
+ }
49
+
50
+ let r = +toFixedDigits(costs, 2);
51
+
52
+ if (r === 0) {
53
+ r = +toFixedDigits(costs, 3);
54
+ }
55
+
56
+ return `${r}ms`;
57
+ }
58
+
59
+ const formatValues = (measures: Record<string, number>) => {
60
+ const result: [string, string][] = [];
61
+
62
+ for (const measureName in measures) {
63
+ const measureValue = measures[measureName];
64
+ result.push([measureName, formatCosts(measureValue)]);
65
+ }
66
+
67
+ return result;
68
+ };
69
+
70
+ const filterStats = (measures: Record<string, number>) => {
71
+ const entries = Object.entries(measures);
72
+ entries.sort((a, b) => b[1] - a[1]);
10
73
 
11
- const formatTimeStats = (stats: Result[string]['client']) => {
12
- return `${roundStats(stats.mean)}ms ± ${roundStats(stats.variance)}%`;
74
+ return entries.slice(0, 5).reduce((acc, [key, value]) => {
75
+ acc[key] = value;
76
+ return acc;
77
+ }, {});
13
78
  };
14
79
 
15
- const formatMemoryStats = (stats: Result[string]['client']) => {
16
- const value = prettyBytes(stats.mean, {
17
- maximumFractionDigits: 2,
18
- });
80
+ const getInfo = (compilationStats: CompilationStats) => {
81
+ const { totalBuildCosts, loaderBuildCosts, pluginBuildCosts } = compilationStats;
82
+
83
+ const totalBuildInfo = formatValues(totalBuildCosts);
84
+ const loaderInfo = formatValues(filterStats(loaderBuildCosts));
85
+ const pluginInfo = formatValues(filterStats(pluginBuildCosts));
19
86
 
20
- return `${value} ± ${roundStats(stats.variance)}%`;
87
+ return { totalBuildInfo, loaderInfo, pluginInfo };
21
88
  };
22
89
 
23
- const formatStatsTable = (stats: Result) => {
24
- const header = [''] as string[];
25
- const alignment = ['C'] as string[];
26
- const rows = [['time'], ['mem']] as string[][];
90
+ const mergeTotalInfo = (
91
+ server?: [string, string][] | undefined,
92
+ client?: [string, string][] | undefined
93
+ ) => {
94
+ const result = [];
27
95
 
28
- for (const key in stats) {
29
- header.push(key);
30
- alignment.push('C');
96
+ for (let i = 0; i < (server?.length ?? client?.length); i++) {
97
+ result.push([
98
+ server?.[i][0] ?? client?.[i][0] ?? '-',
99
+ server?.[i][1] ?? '0',
100
+ client?.[i][1] ?? '0',
101
+ ]);
102
+ }
103
+
104
+ return result;
105
+ };
31
106
 
32
- const { client, server, maxMemoryRss } = stats[key];
107
+ const mergeAdditionalInfo = (
108
+ server?: [string, string][] | undefined,
109
+ client?: [string, string][] | undefined
110
+ ) => {
111
+ const result = [];
33
112
 
34
- rows[0].push(`${formatTimeStats(client)} / ${formatTimeStats(server)}`);
35
- rows[1].push(formatMemoryStats(maxMemoryRss));
113
+ for (let i = 0; i < (server?.length ?? client?.length); i++) {
114
+ result.push([
115
+ server?.[i][0] ?? '-',
116
+ server?.[i][1] ?? '0',
117
+ client?.[i][0] ?? '-',
118
+ client?.[i][1] ?? 0,
119
+ ]);
36
120
  }
37
121
 
38
- return mdtable(
39
- {
40
- header,
41
- alignment,
42
- rows,
43
- },
44
- {
45
- borders: true,
46
- padding: 1,
47
- }
48
- );
122
+ return result;
123
+ };
124
+
125
+ const formatBuildTime = (totalBuildTime) =>
126
+ totalBuildTime ? `${(totalBuildTime / 1000).toFixed(2)}s` : '-';
127
+
128
+ const formatMemoryRss = (memoryRss) => (memoryRss ? `${(memoryRss / 1000000).toFixed(2)}mb` : '-');
129
+
130
+ const formatStatsTables = (stats: Result, times: number | undefined = DEFAULT_TIMES) => {
131
+ const {
132
+ clientBuildTime,
133
+ clientCompilationStats,
134
+ serverBuildTime,
135
+ serverCompilationStats,
136
+ maxMemoryRss,
137
+ clientMaxMemoryRss,
138
+ serverMaxMemoryRss,
139
+ } = stats;
140
+ const serverInfo = !isEmpty(serverCompilationStats) && getInfo(serverCompilationStats);
141
+ const clientInfo = !isEmpty(clientCompilationStats) && getInfo(clientCompilationStats);
142
+
143
+ const totalBuildData = [
144
+ [`Mean durations (${times} times)`, 'server', 'client'],
145
+ ['Total build time', formatBuildTime(serverBuildTime), formatBuildTime(clientBuildTime)],
146
+ maxMemoryRss
147
+ ? ['Total memory', formatMemoryRss(maxMemoryRss), '']
148
+ : ['Total memory', formatMemoryRss(serverMaxMemoryRss), formatMemoryRss(clientMaxMemoryRss)],
149
+ ...mergeTotalInfo(serverInfo.totalBuildInfo, clientInfo.totalBuildInfo),
150
+ ].filter(Boolean);
151
+
152
+ const totalBuildTableConfig: TableUserConfig = {
153
+ columns: [{ alignment: 'left' }, { alignment: 'center' }, { alignment: 'center' }],
154
+ };
155
+
156
+ if (maxMemoryRss) {
157
+ // @ts-expect-error
158
+ totalBuildTableConfig.spanningCells = [{ col: 1, row: 2, colSpan: 2, alignment: 'center' }];
159
+ }
160
+
161
+ const mergedLoadersInfo = mergeAdditionalInfo(serverInfo.loaderInfo, clientInfo.loaderInfo);
162
+ const mergedPluginsInfo = mergeAdditionalInfo(serverInfo.pluginInfo, clientInfo.pluginInfo);
163
+ const additionalBuildData = [
164
+ ['server', '', 'client', ''],
165
+ ['Loaders', '', '', ''],
166
+ ...mergedLoadersInfo,
167
+ ['Plugins', '', '', ''],
168
+ ...mergedPluginsInfo,
169
+ ];
170
+
171
+ const additionalBuildTableConfig: TableUserConfig = {
172
+ spanningCells: [
173
+ { col: 0, row: 0, colSpan: 2, alignment: 'center' },
174
+ { col: 2, row: 0, colSpan: 2, alignment: 'center' },
175
+ { col: 0, row: 1, colSpan: 4, alignment: 'center' },
176
+ { col: 0, row: mergedLoadersInfo.length + 2, colSpan: 4, alignment: 'center' },
177
+ ],
178
+ };
179
+
180
+ return [
181
+ table(totalBuildData, totalBuildTableConfig),
182
+ table(additionalBuildData, additionalBuildTableConfig),
183
+ ];
49
184
  };
50
185
 
51
- export default async (context: Context, parameters): Promise<CommandResult | any> => {
186
+ export default async (_context: Context, parameters): Promise<CommandResult | any> => {
52
187
  const { command, times, ...commandOptions } = parameters;
53
188
 
54
189
  const stats = await app.run('benchmark', { command, times, commandOptions });
55
190
 
56
- console.log(formatStatsTable(stats));
191
+ formatStatsTables(stats, times).forEach((buildTable) => console.log(buildTable));
57
192
 
58
193
  return Promise.resolve({
59
194
  status: 'ok',
@@ -36,6 +36,18 @@ export class BenchmarkCommand extends CLICommand<Params> {
36
36
  description:
37
37
  'Specify the names of the bundles that need to be collected, other bundles will not be collected and their request will fail with an error',
38
38
  },
39
+ {
40
+ name: '--fileCache',
41
+ value: '[fileCache]',
42
+ transformer: (value: string) => value !== 'false',
43
+ description: 'Enable/disable persistent file cache for used cli builder',
44
+ },
45
+ {
46
+ name: '-t, --buildType',
47
+ value: '[type]',
48
+ description: 'Build type <client|server>',
49
+ defaultValue: 'client',
50
+ },
39
51
  {
40
52
  name: '--times',
41
53
  value: '[times]',
@@ -54,6 +54,12 @@ class BuildCommand extends CLICommand<Params> {
54
54
  value: '[forPublish]',
55
55
  description: '<package> Prepare library package.json for publication',
56
56
  },
57
+ {
58
+ name: '--analyze',
59
+ value: '[analyze]',
60
+ description:
61
+ 'Run build with analyze, supported plugins: <bundle|whybundled|statoscope|rsdoctor>',
62
+ },
57
63
  {
58
64
  name: '--fileCache',
59
65
  value: '[fileCache]',
@@ -62,7 +62,7 @@ const devDependencies = [
62
62
  'postcss-nested',
63
63
  'husky@^4',
64
64
  'lint-staged',
65
- 'prettier-config-tinkoff',
65
+ '@tramvai/prettier-config',
66
66
  'typescript',
67
67
  ];
68
68
 
@@ -1 +1 @@
1
- module.exports = require('prettier-config-tinkoff');
1
+ module.exports = require('@tramvai/prettier-config');
@@ -9,7 +9,7 @@
9
9
  "start": "tramvai start {{configEntry.name}}",
10
10
  "build": "tramvai build {{configEntry.name}}",
11
11
  "preview": "tramvai start-prod {{configEntry.name}}",
12
- "analyze": "tramvai analyze {{configEntry.name}}",
12
+ "analyze": "tramvai {{configEntry.name}} --analyze=statoscope",
13
13
  "lint": "eslint --ext .ts,.tsx --ignore-path .gitignore ."{{#if isJest}},
14
14
  "test": "jest --passWithNoTests",
15
15
  "test:watch": "jest --watch",
@@ -95,6 +95,12 @@ export class StartCommand extends CLICommand<Params> {
95
95
  value: '[showConfig]',
96
96
  description: 'Show config with which cli was launched',
97
97
  },
98
+ {
99
+ name: '--analyze',
100
+ value: '[analyze]',
101
+ description:
102
+ 'Run build with analyze, supported plugins: <bundle|whybundled|statoscope|rsdoctor>',
103
+ },
98
104
  {
99
105
  name: '--onlyBundles',
100
106
  value: '[onlyBundles]',
@@ -37,9 +37,11 @@ export interface Settings<E extends Env> {
37
37
  profile?: boolean;
38
38
  noServerRebuild?: boolean;
39
39
  noClientRebuild?: boolean;
40
+ benchmark?: boolean;
40
41
  resolveSymlinks?: boolean;
41
42
  showConfig?: boolean;
42
43
  onlyBundles?: string[];
44
+ analyze?: false | 'bundle' | 'whybundled' | 'statoscope' | 'rsdoctor';
43
45
  disableProdOptimization?: boolean;
44
46
  fileCache?: boolean;
45
47
  }
@@ -131,8 +133,10 @@ export const createConfigManager = <C extends ConfigEntry = ConfigEntry, E exten
131
133
  profile: false,
132
134
  noClientRebuild: false,
133
135
  noServerRebuild: false,
136
+ benchmark: false,
134
137
  resolveSymlinks: true,
135
138
  disableProdOptimization: false,
139
+ analyze: false,
136
140
  onlyBundles: [],
137
141
  // according to measures fileCache in webpack doesn't affect
138
142
  // performance much so enable it by default as it always was before
@@ -1,3 +1,4 @@
1
+ import path from 'node:path';
1
2
  import type Config from 'webpack-chain';
2
3
  import { modernLibsFilter } from '@tinkoff/is-modern-lib';
3
4
  import { applyThreadLoader } from '../utils/threadLoader';
@@ -5,25 +6,22 @@ import type { ConfigManager } from '../../../config/configManager';
5
6
  import { getTranspilerConfig, addTranspilerLoader } from '../utils/transpiler';
6
7
  import type { CliConfigEntry } from '../../../typings/configEntry/cli';
7
8
 
8
- // eslint-disable-next-line import/no-default-export
9
- export default (configManager: ConfigManager<CliConfigEntry>) => (config: Config) => {
10
- const { transpileOnlyModernLibs } = configManager;
11
-
12
- const rule = config.module
13
- .rule('js')
14
- .test(/\.[cm]?js[x]?$/)
15
- .batch(applyThreadLoader(configManager));
9
+ const projectRulesName = 'project';
10
+ const nodeModuleRulesName = 'node_module';
16
11
 
12
+ const applyProjectRules = (rule, configManager) => {
17
13
  rule
18
- .oneOf('project')
14
+ .oneOf(projectRulesName)
19
15
  .exclude.add(/node_modules/)
20
16
  .end()
21
17
  .use('transpiler')
22
- .batch(addTranspilerLoader(configManager, getTranspilerConfig(configManager)));
18
+ .batch(addTranspilerLoader(configManager, getTranspilerConfig(configManager)))
19
+ .end();
20
+ };
23
21
 
22
+ const applyNodeModulesRules = (rule, configManager) => {
24
23
  rule
25
- .oneOf('node_module')
26
- .when(transpileOnlyModernLibs, (cfg) => cfg.include.add(modernLibsFilter))
24
+ .oneOf(nodeModuleRulesName)
27
25
  .merge({
28
26
  // true value forces to use file extensions for importing mjs modules
29
27
  // but we want to use mjs if it exists anyway
@@ -32,3 +30,54 @@ export default (configManager: ConfigManager<CliConfigEntry>) => (config: Config
32
30
  .use('transpiler')
33
31
  .batch(addTranspilerLoader(configManager, getTranspilerConfig(configManager, { hot: false })));
34
32
  };
33
+
34
+ // eslint-disable-next-line import/no-default-export
35
+ export default (configManager: ConfigManager<CliConfigEntry>) => (config: Config) => {
36
+ const { transpileOnlyModernLibs } = configManager;
37
+ const { include } = configManager.experiments.transpilation;
38
+ const shouldTranspileOnlyModern = transpileOnlyModernLibs || include === 'only-modern';
39
+
40
+ const rule = config.module
41
+ .rule('js')
42
+ .test(/\.[cm]?js[x]?$/)
43
+ .batch(applyThreadLoader(configManager));
44
+
45
+ if (configManager.env === 'production') {
46
+ applyProjectRules(rule, configManager);
47
+ applyNodeModulesRules(rule, configManager);
48
+
49
+ if (shouldTranspileOnlyModern) {
50
+ rule.oneOf(nodeModuleRulesName).include.add(modernLibsFilter);
51
+ }
52
+ } else {
53
+ const shouldSkipTranspiling = include === 'none';
54
+ const shouldSelectiveTranspile = Array.isArray(include);
55
+
56
+ if (shouldSkipTranspiling) {
57
+ rule.exclude
58
+ .add(/node_modules/)
59
+ .end()
60
+ .use('transpiler')
61
+ .batch(addTranspilerLoader(configManager, getTranspilerConfig(configManager)));
62
+ } else {
63
+ applyProjectRules(rule, configManager);
64
+ applyNodeModulesRules(rule, configManager);
65
+
66
+ if (shouldSelectiveTranspile) {
67
+ const includeForTranspiling = (<string[]>include).map((includePath) =>
68
+ // require.resolve return absolute path to entrypoint of dependency
69
+ // but we need root dirname of dependency inside node_modules
70
+ path.dirname(require.resolve(`${includePath}/package.json`))
71
+ );
72
+
73
+ includeForTranspiling.forEach((includePath) => {
74
+ rule.oneOf(nodeModuleRulesName).include.add(includePath);
75
+ });
76
+ } else if (shouldTranspileOnlyModern) {
77
+ if (shouldTranspileOnlyModern) {
78
+ rule.oneOf(nodeModuleRulesName).include.add(modernLibsFilter);
79
+ }
80
+ }
81
+ }
82
+ }
83
+ };
@@ -3,6 +3,7 @@ import type Config from 'webpack-chain';
3
3
  import path from 'path';
4
4
  import { existsSync } from 'fs-extra';
5
5
  import findCacheDir from 'find-cache-dir';
6
+ import { RsdoctorWebpackMultiplePlugin } from '@rsdoctor/webpack-plugin';
6
7
  import { ignoreWarnings } from '../utils/warningsFilter';
7
8
  import resolve from '../blocks/resolve';
8
9
  import ignoreLocales from '../blocks/ignoreLocales';
@@ -10,6 +11,7 @@ import type { ConfigManager } from '../../../config/configManager';
10
11
  import { safeRequireResolve } from '../../../utils/safeRequire';
11
12
  import type { CliConfigEntry } from '../../../typings/configEntry/cli';
12
13
  import { getPostcssConfigPath } from '../blocks/css';
14
+ import { getRsdoctorOptions } from '../utils/rsdoctor';
13
15
 
14
16
  const filterNonExisted = (filePaths: string[]) => {
15
17
  return filePaths.filter((filePath) => {
@@ -126,6 +128,12 @@ export default (configManager: ConfigManager<CliConfigEntry>) => (config: Config
126
128
  },
127
129
  ]);
128
130
 
131
+ if (configManager.benchmark) {
132
+ config
133
+ .plugin('rsdoctor-benchmark')
134
+ .use(RsdoctorWebpackMultiplePlugin, [getRsdoctorOptions(configManager.buildType)]);
135
+ }
136
+
129
137
  // TODO: remove after dropping support for node@14
130
138
  if (configManager.buildType === 'server') {
131
139
  config.plugin('node-performance').use(webpack.ProvidePlugin, [
@@ -0,0 +1,26 @@
1
+ import { RsdoctorWebpackPlugin } from '@rsdoctor/webpack-plugin';
2
+
3
+ type options = ConstructorParameters<typeof RsdoctorWebpackPlugin<[]>>[0];
4
+
5
+ export const getRsdoctorOptions = (buildType: 'client' | 'server'): options => ({
6
+ disableClientServer: true,
7
+ features: ['plugins', 'loader'],
8
+ linter: {
9
+ level: 'Ignore',
10
+ },
11
+ output: {
12
+ reportDir: './.rsdoctor',
13
+ mode: 'brief',
14
+ options: {
15
+ type: ['json'],
16
+ jsonOptions: {
17
+ fileName: `${buildType}-rsdoctor-data.json`,
18
+ sections: {
19
+ moduleGraph: false,
20
+ chunkGraph: false,
21
+ rules: false,
22
+ },
23
+ },
24
+ },
25
+ },
26
+ });
@@ -23,6 +23,7 @@ const createWorkerPoolConfig = (configManager: ConfigManager<CliConfigEntry>) =>
23
23
 
24
24
  const isApplicable = (configManager: ConfigManager<CliConfigEntry>) => {
25
25
  return (
26
+ !configManager.benchmark &&
26
27
  // thread-loader uses child_process.fork under the hood, and sometimes (50/50) work in these processes does not get into inspector.Session profile
27
28
  !process.env.TRAMVAI_CPU_PROFILE &&
28
29
  !process.env.TRAMVAI_DEBUG_BUILD &&
@@ -76,6 +76,7 @@ it('should populate defaults for config', () => {
76
76
  "runtimeChunk": false,
77
77
  "serverRunner": "thread",
78
78
  "transpilation": {
79
+ "include": "only-modern",
79
80
  "loader": "babel",
80
81
  },
81
82
  "viewTransitions": false,
@@ -152,6 +153,7 @@ it('should populate defaults for config', () => {
152
153
  "minifier": "terser",
153
154
  "reactCompiler": false,
154
155
  "transpilation": {
156
+ "include": "only-modern",
155
157
  "loader": "babel",
156
158
  },
157
159
  "webpack": {
@@ -325,6 +327,7 @@ it('should populate defaults for overridable options', () => {
325
327
  "runtimeChunk": false,
326
328
  "serverRunner": "thread",
327
329
  "transpilation": {
330
+ "include": "only-modern",
328
331
  "loader": {
329
332
  "development": "swc",
330
333
  "production": "babel",
@@ -419,6 +422,7 @@ it('should populate defaults for overridable options', () => {
419
422
  "minifier": "terser",
420
423
  "reactCompiler": false,
421
424
  "transpilation": {
425
+ "include": "only-modern",
422
426
  "loader": {
423
427
  "development": "babel",
424
428
  "production": "babel",