@tramvai/cli 5.53.81 → 5.53.111
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 +1 -1
- package/bin/const.js +5 -0
- package/bin/platform.js +12 -6
- package/bin/spawn.js +6 -0
- package/lib/api/analyze/index.d.ts.map +1 -1
- package/lib/api/analyze/index.js +1 -13
- package/lib/api/analyze/index.js.map +1 -1
- package/lib/api/benchmark/build.d.ts +1 -6
- package/lib/api/benchmark/build.d.ts.map +1 -1
- package/lib/api/benchmark/build.js +59 -23
- package/lib/api/benchmark/build.js.map +1 -1
- package/lib/api/benchmark/const.d.ts +2 -0
- package/lib/api/benchmark/const.d.ts.map +1 -0
- package/lib/api/benchmark/const.js +5 -0
- package/lib/api/benchmark/const.js.map +1 -0
- package/lib/api/benchmark/index.d.ts +4 -6
- package/lib/api/benchmark/index.d.ts.map +1 -1
- package/lib/api/benchmark/index.js.map +1 -1
- package/lib/api/benchmark/start.d.ts +1 -7
- package/lib/api/benchmark/start.d.ts.map +1 -1
- package/lib/api/benchmark/start.js +56 -49
- package/lib/api/benchmark/start.js.map +1 -1
- package/lib/api/benchmark/types.d.ts +76 -12
- package/lib/api/benchmark/types.d.ts.map +1 -1
- package/lib/api/benchmark/utils/compilationUtils.d.ts +4 -0
- package/lib/api/benchmark/utils/compilationUtils.d.ts.map +1 -0
- package/lib/api/benchmark/utils/compilationUtils.js +157 -0
- package/lib/api/benchmark/utils/compilationUtils.js.map +1 -0
- package/lib/api/benchmark/utils/stats.d.ts +2 -7
- package/lib/api/benchmark/utils/stats.d.ts.map +1 -1
- package/lib/api/benchmark/utils/stats.js +36 -22
- package/lib/api/benchmark/utils/stats.js.map +1 -1
- package/lib/api/build/index.d.ts +1 -0
- package/lib/api/build/index.d.ts.map +1 -1
- package/lib/api/build/index.js.map +1 -1
- package/lib/api/index.js +1 -1
- package/lib/api/index.js.map +1 -1
- package/lib/api/start/index.d.ts +1 -0
- package/lib/api/start/index.d.ts.map +1 -1
- package/lib/api/start/index.js.map +1 -1
- package/lib/builder/webpack/analyzePlugins/rsdoctor.d.ts +5 -5
- package/lib/builder/webpack/analyzePlugins/rsdoctor.d.ts.map +1 -1
- package/lib/builder/webpack/analyzePlugins/rsdoctor.js +7 -9
- package/lib/builder/webpack/analyzePlugins/rsdoctor.js.map +1 -1
- package/lib/builder/webpack/index.d.ts.map +1 -1
- package/lib/builder/webpack/index.js +14 -12
- package/lib/builder/webpack/index.js.map +1 -1
- package/lib/builder/webpack/providers/build/client.d.ts.map +1 -1
- package/lib/builder/webpack/providers/build/client.js +3 -2
- package/lib/builder/webpack/providers/build/client.js.map +1 -1
- package/lib/builder/webpack/providers/build/server.d.ts.map +1 -1
- package/lib/builder/webpack/providers/build/server.js +3 -2
- package/lib/builder/webpack/providers/build/server.js.map +1 -1
- package/lib/builder/webpack/providers/shared.d.ts.map +1 -1
- package/lib/builder/webpack/providers/shared.js +39 -5
- package/lib/builder/webpack/providers/shared.js.map +1 -1
- package/lib/builder/webpack/providers/start/shared.d.ts.map +1 -1
- package/lib/builder/webpack/providers/start/shared.js +6 -2
- package/lib/builder/webpack/providers/start/shared.js.map +1 -1
- package/lib/builder/webpack/tokens.d.ts +10 -16
- package/lib/builder/webpack/tokens.d.ts.map +1 -1
- package/lib/cli/index.d.ts.map +1 -1
- package/lib/cli/index.js +12 -12
- package/lib/cli/index.js.map +1 -1
- package/lib/commands/analyze/command.d.ts +1 -1
- package/lib/commands/analyze/command.d.ts.map +1 -1
- package/lib/commands/benchmark/benchmark.d.ts +3 -1
- package/lib/commands/benchmark/benchmark.d.ts.map +1 -1
- package/lib/commands/benchmark/benchmark.js +130 -31
- package/lib/commands/benchmark/benchmark.js.map +1 -1
- package/lib/commands/benchmark/command.d.ts +9 -0
- package/lib/commands/benchmark/command.d.ts.map +1 -1
- package/lib/commands/benchmark/command.js +12 -0
- package/lib/commands/benchmark/command.js.map +1 -1
- package/lib/commands/build/command.d.ts.map +1 -1
- package/lib/commands/build/command.js +5 -0
- package/lib/commands/build/command.js.map +1 -1
- package/lib/commands/start/command.d.ts.map +1 -1
- package/lib/commands/start/command.js +5 -0
- package/lib/commands/start/command.js.map +1 -1
- package/lib/commands/update/checkVersionValidator.d.ts +1 -1
- package/lib/commands/update/checkVersionValidator.d.ts.map +1 -1
- package/lib/commands/update/checkVersionValidator.js +3 -2
- package/lib/commands/update/checkVersionValidator.js.map +1 -1
- package/lib/commands/update/command.d.ts +1 -1
- package/lib/commands/update/dependantLibs.d.ts +1 -1
- package/lib/commands/update/dependantLibs.d.ts.map +1 -1
- package/lib/commands/update/dependantLibs.js +3 -2
- package/lib/commands/update/dependantLibs.js.map +1 -1
- package/lib/commands/update/update.d.ts.map +1 -1
- package/lib/commands/update/update.js +6 -3
- package/lib/commands/update/update.js.map +1 -1
- package/lib/commands/update/updatePackageJson.d.ts +1 -1
- package/lib/commands/update/updatePackageJson.d.ts.map +1 -1
- package/lib/commands/update/updatePackageJson.js +7 -7
- package/lib/commands/update/updatePackageJson.js.map +1 -1
- package/lib/config/configManager.d.ts +2 -0
- package/lib/config/configManager.d.ts.map +1 -1
- package/lib/config/configManager.js +2 -0
- package/lib/config/configManager.js.map +1 -1
- package/lib/di/tokens/config.d.ts +5 -8
- package/lib/di/tokens/config.d.ts.map +1 -1
- package/lib/library/webpack/blocks/css.d.ts.map +1 -1
- package/lib/library/webpack/blocks/css.js +42 -15
- package/lib/library/webpack/blocks/css.js.map +1 -1
- package/lib/library/webpack/blocks/js.d.ts.map +1 -1
- package/lib/library/webpack/blocks/js.js +57 -11
- package/lib/library/webpack/blocks/js.js.map +1 -1
- package/lib/library/webpack/common/main.d.ts.map +1 -1
- package/lib/library/webpack/common/main.js +7 -0
- package/lib/library/webpack/common/main.js.map +1 -1
- package/lib/library/webpack/utils/browserslist.d.ts +4 -0
- package/lib/library/webpack/utils/browserslist.d.ts.map +1 -0
- package/lib/library/webpack/utils/browserslist.js +27 -0
- package/lib/library/webpack/utils/browserslist.js.map +1 -0
- package/lib/library/webpack/utils/rsdoctor.d.ts +2 -0
- package/lib/library/webpack/utils/rsdoctor.d.ts.map +1 -0
- package/lib/library/webpack/utils/rsdoctor.js +27 -0
- package/lib/library/webpack/utils/rsdoctor.js.map +1 -0
- package/lib/library/webpack/utils/threadLoader.d.ts.map +1 -1
- package/lib/library/webpack/utils/threadLoader.js +3 -3
- package/lib/library/webpack/utils/threadLoader.js.map +1 -1
- package/lib/library/webpack/utils/transpiler.d.ts.map +1 -1
- package/lib/library/webpack/utils/transpiler.js +3 -16
- package/lib/library/webpack/utils/transpiler.js.map +1 -1
- package/lib/schema/autogeneratedSchema.json +240 -120
- package/lib/typings/build/Builder.d.ts +6 -2
- package/lib/typings/build/Builder.d.ts.map +1 -1
- package/lib/typings/configEntry/cli.d.ts +9 -0
- package/lib/typings/configEntry/cli.d.ts.map +1 -1
- package/lib/utils/commands/dependencies/getLatestPackageVersion.d.ts +1 -1
- package/lib/utils/commands/dependencies/getLatestPackageVersion.d.ts.map +1 -1
- package/lib/utils/commands/dependencies/getLatestPackageVersion.js +4 -2
- package/lib/utils/commands/dependencies/getLatestPackageVersion.js.map +1 -1
- package/lib/utils/commands/dependencies/packageHasVersion.d.ts +1 -1
- package/lib/utils/commands/dependencies/packageHasVersion.d.ts.map +1 -1
- package/lib/utils/commands/dependencies/packageHasVersion.js +3 -2
- package/lib/utils/commands/dependencies/packageHasVersion.js.map +1 -1
- package/package.json +19 -18
- package/schema.json +240 -120
- package/src/api/analyze/index.ts +3 -16
- package/src/api/benchmark/__integration__/start.test.ts +10 -12
- package/src/api/benchmark/build.ts +75 -30
- package/src/api/benchmark/const.ts +1 -0
- package/src/api/benchmark/index.ts +4 -6
- package/src/api/benchmark/start.ts +69 -65
- package/src/api/benchmark/types.ts +82 -14
- package/src/api/benchmark/utils/compilationUtils.ts +213 -0
- package/src/api/benchmark/utils/stats.ts +45 -28
- package/src/api/build/index.ts +1 -0
- package/src/api/index.ts +1 -1
- package/src/api/start/index.ts +1 -0
- package/src/builder/webpack/analyzePlugins/rsdoctor.ts +11 -14
- package/src/builder/webpack/index.ts +16 -21
- package/src/builder/webpack/providers/build/client.ts +7 -2
- package/src/builder/webpack/providers/build/server.ts +7 -2
- package/src/builder/webpack/providers/shared.ts +53 -5
- package/src/builder/webpack/providers/start/shared.ts +7 -2
- package/src/cli/index.ts +3 -2
- package/src/commands/analyze/command.ts +1 -1
- package/src/commands/benchmark/benchmark.ts +168 -33
- package/src/commands/benchmark/command.ts +12 -0
- package/src/commands/build/command.ts +6 -0
- package/src/commands/new/templates/shared/package.json.hbs +1 -1
- package/src/commands/start/command.ts +6 -0
- package/src/commands/update/checkVersionValidator.ts +4 -2
- package/src/commands/update/dependantLibs.ts +3 -1
- package/src/commands/update/update.ts +6 -3
- package/src/commands/update/updatePackageJson.spec.ts +19 -3
- package/src/commands/update/updatePackageJson.ts +7 -2
- package/src/config/configManager.ts +4 -0
- package/src/library/webpack/blocks/css.ts +52 -16
- package/src/library/webpack/blocks/js.ts +61 -12
- package/src/library/webpack/common/main.ts +8 -0
- package/src/library/webpack/utils/browserslist.ts +29 -0
- package/src/library/webpack/utils/rsdoctor.ts +26 -0
- package/src/library/webpack/utils/threadLoader.ts +1 -0
- package/src/library/webpack/utils/transpiler.ts +3 -18
- package/src/models/config.spec.ts +4 -0
- package/src/schema/autogeneratedSchema.json +240 -120
- package/src/schema/tramvai.spec.ts +2 -0
- package/src/typings/build/Builder.ts +7 -2
- package/src/typings/configEntry/cli.ts +11 -0
- package/src/utils/commands/dependencies/getLatestPackageVersion.ts +4 -1
- package/src/utils/commands/dependencies/packageHasVersion.ts +7 -2
- package/lib/api/analyze/providers/shared.d.ts +0 -3
- package/lib/api/analyze/providers/shared.d.ts.map +0 -1
- package/lib/api/analyze/providers/shared.js +0 -23
- package/lib/api/analyze/providers/shared.js.map +0 -1
- package/lib/builder/webpack/providers/analyze/shared.d.ts +0 -3
- package/lib/builder/webpack/providers/analyze/shared.d.ts.map +0 -1
- package/lib/builder/webpack/providers/analyze/shared.js +0 -141
- package/lib/builder/webpack/providers/analyze/shared.js.map +0 -1
- package/src/api/analyze/providers/shared.ts +0 -26
- package/src/api/benchmark/utils/stats.spec.ts +0 -36
- package/src/builder/webpack/providers/analyze/shared.ts +0 -160
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
|
|
3
|
+
import { CompilationStats, LoaderTransformData, MinimalLoaderData, PluginData } from '../types';
|
|
4
|
+
|
|
5
|
+
export async function getServerCompilationTimings(
|
|
6
|
+
benchmarkStartTime: string,
|
|
7
|
+
attemptStartTime: number,
|
|
8
|
+
attempt: number
|
|
9
|
+
) {
|
|
10
|
+
return getCompilationTimings(benchmarkStartTime, attemptStartTime, attempt, 'server');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function getClientCompilationTimings(
|
|
14
|
+
benchmarkStartTime: string,
|
|
15
|
+
attemptStartTime: number,
|
|
16
|
+
attempt: number
|
|
17
|
+
) {
|
|
18
|
+
return getCompilationTimings(benchmarkStartTime, attemptStartTime, attempt, 'client');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function getCompilationTimings(
|
|
22
|
+
benchmarkStartTime: string,
|
|
23
|
+
attemptStartTime: number,
|
|
24
|
+
attempt: number,
|
|
25
|
+
type: 'client' | 'server'
|
|
26
|
+
): Promise<CompilationStats> {
|
|
27
|
+
try {
|
|
28
|
+
const rsdoctorData = await getReportData(
|
|
29
|
+
await processReport(benchmarkStartTime, attempt, type)
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const { summary, loader, plugin } = rsdoctorData;
|
|
33
|
+
|
|
34
|
+
const totalBuildCosts = calculateTotalCosts(summary, attemptStartTime);
|
|
35
|
+
const loaderBuildCosts = calculateLoadersCosts(loader);
|
|
36
|
+
const pluginBuildCosts = calculatePluginsCosts(plugin);
|
|
37
|
+
|
|
38
|
+
return { totalBuildCosts, loaderBuildCosts, pluginBuildCosts };
|
|
39
|
+
} catch (err) {
|
|
40
|
+
throw new Error(`Failed to get rsdoctor report!\n${err}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function getReportData(reportPath: string) {
|
|
45
|
+
const rsdoctorRawStats = await fs.readFile(reportPath, 'utf-8');
|
|
46
|
+
const rsdoctorStats = JSON.parse(rsdoctorRawStats);
|
|
47
|
+
|
|
48
|
+
return rsdoctorStats.data;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function processReport(
|
|
52
|
+
benchmarkStartTime: string,
|
|
53
|
+
attempt: number,
|
|
54
|
+
type: 'client' | 'server'
|
|
55
|
+
) {
|
|
56
|
+
const reportBasePath = `./.rsdoctor/${benchmarkStartTime}`;
|
|
57
|
+
const reportPath = `${reportBasePath}/${type}-rsdoctor-data-${attempt + 1}.json`;
|
|
58
|
+
|
|
59
|
+
await fs.mkdir(reportBasePath, { recursive: true });
|
|
60
|
+
await fs.rename(`./.rsdoctor/${type}-rsdoctor-data.json`, reportPath);
|
|
61
|
+
|
|
62
|
+
return reportPath;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function mergeIntervals(intervals: [number, number][]) {
|
|
66
|
+
// Sort from small to large
|
|
67
|
+
intervals.sort((a, b) => a[0] - b[0]);
|
|
68
|
+
// The previous interval, the next interval, store the result
|
|
69
|
+
let previous;
|
|
70
|
+
let current;
|
|
71
|
+
const result: [number, number][] = [];
|
|
72
|
+
|
|
73
|
+
for (let i = 0; i < intervals.length; i++) {
|
|
74
|
+
current = intervals[i];
|
|
75
|
+
// If the first interval or the current interval does not overlap with the previous interval, add the current interval to the result
|
|
76
|
+
if (!previous || current[0] > previous[1]) {
|
|
77
|
+
// Assign the current interval to the previous interval
|
|
78
|
+
previous = current;
|
|
79
|
+
result.push(current);
|
|
80
|
+
} else {
|
|
81
|
+
// Otherwise, the two intervals overlap
|
|
82
|
+
// Update the end time of the previous interval
|
|
83
|
+
previous[1] = Math.max(previous[1], current[1]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function getLoadersCosts(
|
|
91
|
+
filter: (loader: MinimalLoaderData) => boolean,
|
|
92
|
+
loaders: MinimalLoaderData[]
|
|
93
|
+
) {
|
|
94
|
+
const match: { [pid: number | string]: [start: number, end: number][] } = {};
|
|
95
|
+
const others: { [pid: number | string]: [start: number, end: number][] } = {};
|
|
96
|
+
|
|
97
|
+
loaders.forEach((e) => {
|
|
98
|
+
if (filter(e)) {
|
|
99
|
+
if (!match[e.pid]) match[e.pid] = [];
|
|
100
|
+
match[e.pid].push([e.startAt, e.endAt]);
|
|
101
|
+
} else {
|
|
102
|
+
if (!others[e.pid]) others[e.pid] = [];
|
|
103
|
+
others[e.pid].push([e.startAt, e.endAt]);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
let costs = 0;
|
|
108
|
+
|
|
109
|
+
const pids = Object.keys(match);
|
|
110
|
+
|
|
111
|
+
for (let i = 0; i < pids.length; i++) {
|
|
112
|
+
const pid = pids[i];
|
|
113
|
+
const _match = mergeIntervals(match[pid]);
|
|
114
|
+
// between in loader.startAt and loader.endAt
|
|
115
|
+
const _others = mergeIntervals(others[pid] || []).filter(([s, e]) =>
|
|
116
|
+
_match.some((el) => s >= el[0] && e <= el[1])
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// eslint-disable-next-line no-param-reassign
|
|
120
|
+
const matchSum = _match.length ? _match.reduce((t, c) => (t += c[1] - c[0]), 0) : 0;
|
|
121
|
+
// eslint-disable-next-line no-param-reassign
|
|
122
|
+
const othersSum = _others.length ? _others.reduce((t, c) => (t += c[1] - c[0]), 0) : 0;
|
|
123
|
+
|
|
124
|
+
costs += matchSum - othersSum;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return costs;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function calculateTotalCosts(
|
|
131
|
+
summary: { costs: { name: string; cost: string }[] },
|
|
132
|
+
attemptStartTime: number
|
|
133
|
+
) {
|
|
134
|
+
const { costs: buildCosts } = summary;
|
|
135
|
+
const buildCostsMap = buildCosts.reduce((acc, cost) => {
|
|
136
|
+
acc[cost.name] = cost;
|
|
137
|
+
return acc;
|
|
138
|
+
}, {});
|
|
139
|
+
|
|
140
|
+
const result: Record<string, number> = {};
|
|
141
|
+
|
|
142
|
+
for (const buildCostName in buildCostsMap) {
|
|
143
|
+
if (buildCostName === 'bootstrap->beforeCompile') {
|
|
144
|
+
// start of bootstrap is start of first build, so use attemptStarTime instead
|
|
145
|
+
result[buildCostName] =
|
|
146
|
+
buildCostsMap['beforeCompile->afterCompile'].startAt - attemptStartTime;
|
|
147
|
+
} else {
|
|
148
|
+
result[buildCostName] = buildCostsMap[buildCostName].costs;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function calculateLoadersCosts(loaders: { loaders: LoaderTransformData[] }[]) {
|
|
156
|
+
const filteredLoaders: MinimalLoaderData[] = [];
|
|
157
|
+
const uniqueLoaders = new Map<
|
|
158
|
+
string,
|
|
159
|
+
{
|
|
160
|
+
files: number;
|
|
161
|
+
path: string;
|
|
162
|
+
}
|
|
163
|
+
>();
|
|
164
|
+
|
|
165
|
+
loaders.forEach((data) => {
|
|
166
|
+
data.loaders.forEach((fl) => {
|
|
167
|
+
const uniqueLoader = uniqueLoaders.get(fl.loader);
|
|
168
|
+
if (uniqueLoader) {
|
|
169
|
+
uniqueLoaders.set(fl.loader, {
|
|
170
|
+
files: uniqueLoader.files + 1,
|
|
171
|
+
path: fl.path,
|
|
172
|
+
});
|
|
173
|
+
} else {
|
|
174
|
+
uniqueLoaders.set(fl.loader, { files: 1, path: fl.path });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return filteredLoaders.push({
|
|
178
|
+
loader: fl.loader,
|
|
179
|
+
startAt: fl.startAt,
|
|
180
|
+
endAt: fl.endAt,
|
|
181
|
+
pid: fl.pid,
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const costs: Record<string, number> = {};
|
|
187
|
+
uniqueLoaders.forEach((_, loaderName: string) => {
|
|
188
|
+
costs[loaderName] = getLoadersCosts((item) => item.loader === loaderName, filteredLoaders);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
return costs;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function calculatePluginsCosts(plugins: PluginData) {
|
|
195
|
+
const pluginCosts: Record<string, number> = {};
|
|
196
|
+
|
|
197
|
+
for (const hookName in plugins) {
|
|
198
|
+
const hookCalls = plugins[hookName];
|
|
199
|
+
|
|
200
|
+
hookCalls.forEach((plugin) => {
|
|
201
|
+
const pluginName = plugin.tapName;
|
|
202
|
+
const pluginCost = plugin.costs;
|
|
203
|
+
|
|
204
|
+
if (pluginCosts[pluginName]) {
|
|
205
|
+
pluginCosts[pluginName] += pluginCost;
|
|
206
|
+
} else {
|
|
207
|
+
pluginCosts[pluginName] = pluginCost;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return pluginCosts;
|
|
213
|
+
}
|
|
@@ -1,45 +1,62 @@
|
|
|
1
|
-
import type { RunStats,
|
|
1
|
+
import type { RunStats, Samples, CompilationStats } from '../types';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
function getMeanValue(samples: number[]) {
|
|
4
|
+
if (samples.length === 0) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
5
7
|
|
|
6
8
|
let sum = 0;
|
|
7
9
|
|
|
8
|
-
for (let i = 0; i <
|
|
10
|
+
for (let i = 0; i < samples.length; i++) {
|
|
9
11
|
sum += samples[i];
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
return sum / samples.length;
|
|
15
|
+
}
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
function getCompilationMeanStats(allStats) {
|
|
18
|
+
const result = {} as CompilationStats;
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
sum += (samples[i] - mean) * (samples[i] - mean);
|
|
18
|
-
}
|
|
20
|
+
const stats: CompilationStats = allStats[0];
|
|
19
21
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
+
for (const section in stats) {
|
|
23
|
+
for (const metricName in stats[section]) {
|
|
24
|
+
const samples = allStats.reduce((acc, item) => {
|
|
25
|
+
acc.push(item[section][metricName]);
|
|
26
|
+
return acc;
|
|
27
|
+
}, []);
|
|
22
28
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
if (!result[section]) {
|
|
30
|
+
result[section] = {};
|
|
31
|
+
}
|
|
32
|
+
const meanValue = getMeanValue(samples);
|
|
33
|
+
|
|
34
|
+
// ignore values less than 10ms
|
|
35
|
+
if (meanValue > 10) {
|
|
36
|
+
result[section][metricName] = meanValue;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
30
43
|
|
|
31
44
|
export const getResultStats = ({
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
clientBuildTimeSamples,
|
|
46
|
+
clientCompilationTimings,
|
|
47
|
+
clientMaxMemoryRssSamples,
|
|
48
|
+
serverBuildTimeSamples,
|
|
49
|
+
serverCompilationTimings,
|
|
50
|
+
serverMaxMemoryRssSamples,
|
|
34
51
|
maxMemoryRssSamples,
|
|
35
|
-
}: {
|
|
36
|
-
clientSamples: number[];
|
|
37
|
-
serverSamples: number[];
|
|
38
|
-
maxMemoryRssSamples: number[];
|
|
39
|
-
}): RunStats => {
|
|
52
|
+
}: Samples): RunStats => {
|
|
40
53
|
return {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
54
|
+
serverBuildTime: getMeanValue(serverBuildTimeSamples),
|
|
55
|
+
serverCompilationStats: getCompilationMeanStats(serverCompilationTimings),
|
|
56
|
+
clientBuildTime: getMeanValue(clientBuildTimeSamples),
|
|
57
|
+
clientCompilationStats: getCompilationMeanStats(clientCompilationTimings),
|
|
58
|
+
maxMemoryRss: getMeanValue(maxMemoryRssSamples),
|
|
59
|
+
clientMaxMemoryRss: getMeanValue(clientMaxMemoryRssSamples),
|
|
60
|
+
serverMaxMemoryRss: getMeanValue(serverMaxMemoryRssSamples),
|
|
44
61
|
};
|
|
45
62
|
};
|
package/src/api/build/index.ts
CHANGED
package/src/api/index.ts
CHANGED
|
@@ -33,8 +33,8 @@ const app = createApp({
|
|
|
33
33
|
commands: {
|
|
34
34
|
start: () => import('./start'),
|
|
35
35
|
build: () => import('./build'),
|
|
36
|
-
benchmark: () => import('./benchmark'),
|
|
37
36
|
analyze: () => import('./analyze'),
|
|
37
|
+
benchmark: () => import('./benchmark'),
|
|
38
38
|
'start-prod': () => import('./start-prod'),
|
|
39
39
|
},
|
|
40
40
|
providers: [
|
package/src/api/start/index.ts
CHANGED
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { RsdoctorWebpackPlugin } from '@rsdoctor/webpack-plugin';
|
|
1
|
+
import type { RsdoctorWebpackPlugin } from '@rsdoctor/webpack-plugin';
|
|
3
2
|
import { AnalyzePlugin } from '../types';
|
|
4
3
|
|
|
4
|
+
type options = ConstructorParameters<typeof RsdoctorWebpackPlugin<[]>>;
|
|
5
5
|
export class RsdoctorAnalyzePlugin extends AnalyzePlugin {
|
|
6
6
|
requireDeps = [];
|
|
7
7
|
|
|
8
|
-
options:
|
|
8
|
+
options: options = [
|
|
9
9
|
{
|
|
10
|
-
|
|
10
|
+
linter: {
|
|
11
|
+
level: 'Ignore',
|
|
12
|
+
},
|
|
11
13
|
},
|
|
12
14
|
];
|
|
13
15
|
|
|
14
|
-
plugin = RsdoctorWebpackPlugin;
|
|
15
|
-
|
|
16
|
-
patchConfig = (config: Config): Config => {
|
|
17
|
-
super.patchConfigInternal(config);
|
|
18
|
-
// https://github.com/web-infra-dev/rsdoctor/issues/717
|
|
19
|
-
config.set('experiments', { backCompat: true });
|
|
20
|
-
|
|
21
|
-
return config;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
16
|
// rsdoctor поднимает dev server
|
|
25
17
|
afterBuild = () => new Promise(() => null);
|
|
18
|
+
|
|
19
|
+
get plugin() {
|
|
20
|
+
// eslint-disable-next-line import/no-unresolved
|
|
21
|
+
return require('@rsdoctor/webpack-plugin').RsdoctorWebpackMultiplePlugin;
|
|
22
|
+
}
|
|
26
23
|
}
|
|
@@ -27,7 +27,6 @@ import { buildClientProviders } from './providers/build/client';
|
|
|
27
27
|
import { buildServerProviders } from './providers/build/server';
|
|
28
28
|
import { CONFIG_MANAGER_TOKEN } from '../../di/tokens';
|
|
29
29
|
import { buildApplicationServerProviders } from './providers/build/application/server';
|
|
30
|
-
import { analyzeSharedProviders } from './providers/analyze/shared';
|
|
31
30
|
|
|
32
31
|
const BUILDER_NAME = 'webpack';
|
|
33
32
|
|
|
@@ -53,6 +52,14 @@ export const webpackProviders: Provider[] = [
|
|
|
53
52
|
...(shouldBuildServer ? startServerProviders : []),
|
|
54
53
|
]);
|
|
55
54
|
|
|
55
|
+
const configManager = di.get(CONFIG_MANAGER_TOKEN);
|
|
56
|
+
if (configManager.analyze) {
|
|
57
|
+
di.register({
|
|
58
|
+
provide: WEBPACK_ANALYZE_PLUGIN_NAME_TOKEN,
|
|
59
|
+
useValue: configManager.analyze,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
56
63
|
await runHandlers(di.get({ token: INIT_HANDLER_TOKEN, optional: true, multi: true }));
|
|
57
64
|
|
|
58
65
|
const getBuildStats = di.get(GET_BUILD_STATS_TOKEN);
|
|
@@ -89,9 +96,13 @@ export const webpackProviders: Provider[] = [
|
|
|
89
96
|
...(shouldBuildServer ? buildServerProviders : []),
|
|
90
97
|
]);
|
|
91
98
|
|
|
92
|
-
await runHandlers(di.get({ token: INIT_HANDLER_TOKEN, optional: true, multi: true }));
|
|
93
|
-
|
|
94
99
|
const configManager = di.get(CONFIG_MANAGER_TOKEN);
|
|
100
|
+
if (configManager.analyze) {
|
|
101
|
+
di.register({
|
|
102
|
+
provide: WEBPACK_ANALYZE_PLUGIN_NAME_TOKEN,
|
|
103
|
+
useValue: configManager.analyze,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
95
106
|
|
|
96
107
|
if (configManager.type === 'application') {
|
|
97
108
|
registerProviders(di, [
|
|
@@ -99,6 +110,8 @@ export const webpackProviders: Provider[] = [
|
|
|
99
110
|
]);
|
|
100
111
|
}
|
|
101
112
|
|
|
113
|
+
await runHandlers(di.get({ token: INIT_HANDLER_TOKEN, optional: true, multi: true }));
|
|
114
|
+
|
|
102
115
|
const getBuildStats = di.get(GET_BUILD_STATS_TOKEN);
|
|
103
116
|
|
|
104
117
|
await runHandlers(
|
|
@@ -113,24 +126,6 @@ export const webpackProviders: Provider[] = [
|
|
|
113
126
|
getBuildStats,
|
|
114
127
|
};
|
|
115
128
|
},
|
|
116
|
-
async analyze({ plugin }) {
|
|
117
|
-
di.register({
|
|
118
|
-
provide: WEBPACK_ANALYZE_PLUGIN_NAME_TOKEN,
|
|
119
|
-
useValue: plugin || 'bundle',
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
registerProviders(di, analyzeSharedProviders);
|
|
123
|
-
|
|
124
|
-
await runHandlers(di.get({ token: INIT_HANDLER_TOKEN, optional: true, multi: true }));
|
|
125
|
-
|
|
126
|
-
await runHandlers(
|
|
127
|
-
di.get({ token: PROCESS_HANDLER_TOKEN, optional: true, multi: true })
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
await runHandlers(
|
|
131
|
-
di.get({ token: CLOSE_HANDLER_TOKEN, optional: true, multi: true })
|
|
132
|
-
);
|
|
133
|
-
},
|
|
134
129
|
on(event, callback) {
|
|
135
130
|
di.get(EVENT_EMITTER_TOKEN).on(event, callback);
|
|
136
131
|
},
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
CLIENT_CONFIG_MANAGER_TOKEN,
|
|
7
7
|
CLOSE_HANDLER_TOKEN,
|
|
8
8
|
PROCESS_HANDLER_TOKEN,
|
|
9
|
+
WEBPACK_ANALYZE_PLUGIN_TOKEN,
|
|
9
10
|
WEBPACK_CLIENT_COMPILER_TOKEN,
|
|
10
11
|
WEBPACK_CLIENT_CONFIG_TOKEN,
|
|
11
12
|
} from '../../tokens';
|
|
@@ -27,12 +28,16 @@ export const buildClientProviders: Provider[] = [
|
|
|
27
28
|
}),
|
|
28
29
|
provide({
|
|
29
30
|
provide: WEBPACK_CLIENT_COMPILER_TOKEN,
|
|
30
|
-
useFactory: ({ webpackConfig, di }) => {
|
|
31
|
-
return createCompiler(
|
|
31
|
+
useFactory: ({ webpackConfig, di, analyzePlugin }) => {
|
|
32
|
+
return createCompiler(
|
|
33
|
+
toWebpackConfig(analyzePlugin ? analyzePlugin.patchConfig(webpackConfig) : webpackConfig),
|
|
34
|
+
di
|
|
35
|
+
);
|
|
32
36
|
},
|
|
33
37
|
deps: {
|
|
34
38
|
webpackConfig: WEBPACK_CLIENT_CONFIG_TOKEN,
|
|
35
39
|
di: DI_TOKEN,
|
|
40
|
+
analyzePlugin: { token: WEBPACK_ANALYZE_PLUGIN_TOKEN, optional: true },
|
|
36
41
|
},
|
|
37
42
|
}),
|
|
38
43
|
provide({
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
INIT_HANDLER_TOKEN,
|
|
9
9
|
PROCESS_HANDLER_TOKEN,
|
|
10
10
|
SERVER_CONFIG_MANAGER_TOKEN,
|
|
11
|
+
WEBPACK_ANALYZE_PLUGIN_TOKEN,
|
|
11
12
|
WEBPACK_SERVER_COMPILER_TOKEN,
|
|
12
13
|
WEBPACK_SERVER_CONFIG_TOKEN,
|
|
13
14
|
} from '../../tokens';
|
|
@@ -18,12 +19,16 @@ import { createCompiler } from '../../utils/compiler';
|
|
|
18
19
|
export const buildServerProviders: Provider[] = [
|
|
19
20
|
provide({
|
|
20
21
|
provide: WEBPACK_SERVER_COMPILER_TOKEN,
|
|
21
|
-
useFactory: ({ webpackConfig, di }) => {
|
|
22
|
-
return createCompiler(
|
|
22
|
+
useFactory: ({ webpackConfig, di, analyzePlugin }) => {
|
|
23
|
+
return createCompiler(
|
|
24
|
+
toWebpackConfig(analyzePlugin ? analyzePlugin.patchConfig(webpackConfig) : webpackConfig),
|
|
25
|
+
di
|
|
26
|
+
);
|
|
23
27
|
},
|
|
24
28
|
deps: {
|
|
25
29
|
webpackConfig: WEBPACK_SERVER_CONFIG_TOKEN,
|
|
26
30
|
di: DI_TOKEN,
|
|
31
|
+
analyzePlugin: { token: WEBPACK_ANALYZE_PLUGIN_TOKEN, optional: true },
|
|
27
32
|
},
|
|
28
33
|
}),
|
|
29
34
|
provide({
|
|
@@ -3,6 +3,8 @@ import { provide } from '@tinkoff/dippy';
|
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
4
|
import { CONFIG_MANAGER_TOKEN, WITH_BUILD_STATS_TOKEN } from '../../../di/tokens';
|
|
5
5
|
import { closeWorkerPool, warmupWorkerPool } from '../../../library/webpack/utils/threadLoader';
|
|
6
|
+
import { calculateBuildTime } from '../utils/calculateBuildTime';
|
|
7
|
+
import { maxMemoryRss } from '../utils/maxMemoryRss';
|
|
6
8
|
import {
|
|
7
9
|
CLOSE_HANDLER_TOKEN,
|
|
8
10
|
EVENT_EMITTER_TOKEN,
|
|
@@ -10,10 +12,26 @@ import {
|
|
|
10
12
|
INIT_HANDLER_TOKEN,
|
|
11
13
|
WEBPACK_CLIENT_COMPILER_TOKEN,
|
|
12
14
|
WEBPACK_SERVER_COMPILER_TOKEN,
|
|
15
|
+
WEBPACK_ANALYZE_PLUGIN_NAME_TOKEN,
|
|
16
|
+
WEBPACK_ANALYZE_PLUGIN_TOKEN,
|
|
13
17
|
} from '../tokens';
|
|
14
|
-
import { calculateBuildTime } from '../utils/calculateBuildTime';
|
|
15
18
|
import { emitWebpackEvents } from '../utils/webpackEvents';
|
|
16
|
-
import {
|
|
19
|
+
import { BundleAnalyzePlugin } from '../analyzePlugins/bundle';
|
|
20
|
+
import { StatoscopeAnalyzePlugin } from '../analyzePlugins/statoscope';
|
|
21
|
+
import { WhyBundledAnalyzePlugin } from '../analyzePlugins/whyBundled';
|
|
22
|
+
import { RsdoctorAnalyzePlugin } from '../analyzePlugins/rsdoctor';
|
|
23
|
+
import type { AnalyzePlugin } from '../types';
|
|
24
|
+
|
|
25
|
+
interface Type<T> extends Function {
|
|
26
|
+
new (...args: any[]): T;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const pluginMap: Record<string, Type<AnalyzePlugin>> = {
|
|
30
|
+
bundle: BundleAnalyzePlugin,
|
|
31
|
+
whybundled: WhyBundledAnalyzePlugin,
|
|
32
|
+
statoscope: StatoscopeAnalyzePlugin,
|
|
33
|
+
rsdoctor: RsdoctorAnalyzePlugin,
|
|
34
|
+
};
|
|
17
35
|
|
|
18
36
|
export const sharedProviders: Provider[] = [
|
|
19
37
|
provide({
|
|
@@ -31,8 +49,12 @@ export const sharedProviders: Provider[] = [
|
|
|
31
49
|
const getMaxMemoryRss = maxMemoryRss();
|
|
32
50
|
return () => {
|
|
33
51
|
return {
|
|
34
|
-
|
|
35
|
-
|
|
52
|
+
client: {
|
|
53
|
+
buildTime: getClientTime?.(),
|
|
54
|
+
},
|
|
55
|
+
server: {
|
|
56
|
+
buildTime: getServerTime?.(),
|
|
57
|
+
},
|
|
36
58
|
maxMemoryRss: getMaxMemoryRss?.(),
|
|
37
59
|
};
|
|
38
60
|
};
|
|
@@ -43,6 +65,27 @@ export const sharedProviders: Provider[] = [
|
|
|
43
65
|
serverCompiler: { token: WEBPACK_SERVER_COMPILER_TOKEN, optional: true },
|
|
44
66
|
},
|
|
45
67
|
}),
|
|
68
|
+
provide({
|
|
69
|
+
provide: WEBPACK_ANALYZE_PLUGIN_TOKEN,
|
|
70
|
+
useFactory: ({ pluginName }) => {
|
|
71
|
+
if (!pluginName) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const PluginClass = pluginMap[pluginName];
|
|
76
|
+
|
|
77
|
+
if (!PluginClass) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
'Set correct value for --analytics cli option, <bundle|whybundled|statoscope|rsdoctor>\n'
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return new PluginClass();
|
|
84
|
+
},
|
|
85
|
+
deps: {
|
|
86
|
+
pluginName: WEBPACK_ANALYZE_PLUGIN_NAME_TOKEN,
|
|
87
|
+
},
|
|
88
|
+
}),
|
|
46
89
|
provide({
|
|
47
90
|
provide: EVENT_EMITTER_TOKEN,
|
|
48
91
|
useClass: EventEmitter,
|
|
@@ -77,13 +120,18 @@ export const sharedProviders: Provider[] = [
|
|
|
77
120
|
provide({
|
|
78
121
|
provide: CLOSE_HANDLER_TOKEN,
|
|
79
122
|
multi: true,
|
|
80
|
-
useFactory: ({ configManager }) => {
|
|
123
|
+
useFactory: ({ configManager, analyzePlugin }) => {
|
|
81
124
|
return async () => {
|
|
82
125
|
await closeWorkerPool(configManager);
|
|
126
|
+
|
|
127
|
+
if (analyzePlugin) {
|
|
128
|
+
return analyzePlugin.afterBuild();
|
|
129
|
+
}
|
|
83
130
|
};
|
|
84
131
|
},
|
|
85
132
|
deps: {
|
|
86
133
|
configManager: CONFIG_MANAGER_TOKEN,
|
|
134
|
+
analyzePlugin: { token: WEBPACK_ANALYZE_PLUGIN_TOKEN, optional: true },
|
|
87
135
|
},
|
|
88
136
|
}),
|
|
89
137
|
];
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
WEBPACK_COMPILER_TOKEN,
|
|
10
10
|
WEBPACK_SERVER_COMPILER_TOKEN,
|
|
11
11
|
WEBPACK_SERVER_CONFIG_TOKEN,
|
|
12
|
+
WEBPACK_ANALYZE_PLUGIN_TOKEN,
|
|
12
13
|
} from '../../tokens';
|
|
13
14
|
import { createDevServer } from '../../devServer/setup';
|
|
14
15
|
import { CONFIG_MANAGER_TOKEN, STATIC_SERVER_TOKEN } from '../../../../di/tokens';
|
|
@@ -16,8 +17,11 @@ import { CONFIG_MANAGER_TOKEN, STATIC_SERVER_TOKEN } from '../../../../di/tokens
|
|
|
16
17
|
export const startSharedProviders: Provider[] = [
|
|
17
18
|
provide({
|
|
18
19
|
provide: WEBPACK_COMPILER_TOKEN,
|
|
19
|
-
useFactory: ({ clientConfig, serverConfig }) => {
|
|
20
|
-
const configs = [clientConfig, serverConfig]
|
|
20
|
+
useFactory: ({ clientConfig, serverConfig, analyzePlugin }) => {
|
|
21
|
+
const configs = [clientConfig, serverConfig]
|
|
22
|
+
.filter(Boolean)
|
|
23
|
+
.map((config) => (analyzePlugin ? analyzePlugin.patchConfig(config) : config))
|
|
24
|
+
.map(toWebpackConfig);
|
|
21
25
|
const multiCompiler = webpack(configs);
|
|
22
26
|
const { inputFileSystem } = multiCompiler.compilers[0];
|
|
23
27
|
|
|
@@ -51,6 +55,7 @@ export const startSharedProviders: Provider[] = [
|
|
|
51
55
|
deps: {
|
|
52
56
|
clientConfig: { token: WEBPACK_CLIENT_CONFIG_TOKEN, optional: true },
|
|
53
57
|
serverConfig: { token: WEBPACK_SERVER_CONFIG_TOKEN, optional: true },
|
|
58
|
+
analyzePlugin: { token: WEBPACK_ANALYZE_PLUGIN_TOKEN, optional: true },
|
|
54
59
|
},
|
|
55
60
|
}),
|
|
56
61
|
provide({
|
package/src/cli/index.ts
CHANGED
|
@@ -11,8 +11,8 @@ import buildCommand from '../commands/build/command';
|
|
|
11
11
|
import { StartCommand } from '../commands/start/command';
|
|
12
12
|
import lintCommand from '../commands/lint/command';
|
|
13
13
|
import taskCommand from '../commands/task/command';
|
|
14
|
-
import analyze from '../commands/analyze/command';
|
|
15
14
|
import generate from '../commands/generate/command';
|
|
15
|
+
import analyze from '../commands/analyze/command';
|
|
16
16
|
import newCommand from '../commands/new/command';
|
|
17
17
|
import updateCommand from '../commands/update/command';
|
|
18
18
|
import addCommand from '../commands/add/command';
|
|
@@ -27,15 +27,16 @@ import { getRootFile } from '../utils/getRootFile';
|
|
|
27
27
|
import { getTramvaiConfig } from '../utils/getTramvaiConfig';
|
|
28
28
|
import { syncJsonFile } from '../utils/syncJsonFile';
|
|
29
29
|
import { AnalyticsService, resolveDependenciesProperties } from '../models/analytics/analytics';
|
|
30
|
+
import AnalyzeCommand from '../commands/analyze/command';
|
|
30
31
|
|
|
31
32
|
async function loadCommands(): Promise<CommandMap> {
|
|
32
33
|
return [
|
|
33
34
|
buildCommand,
|
|
35
|
+
AnalyzeCommand,
|
|
34
36
|
StartProdCommand,
|
|
35
37
|
StartCommand,
|
|
36
38
|
lintCommand,
|
|
37
39
|
taskCommand,
|
|
38
|
-
analyze,
|
|
39
40
|
generate,
|
|
40
41
|
newCommand,
|
|
41
42
|
updateCommand,
|
|
@@ -8,7 +8,7 @@ import { checkReactCompilerDependencies } from '../../validators/commands/checkR
|
|
|
8
8
|
|
|
9
9
|
export type Params = {
|
|
10
10
|
target: string;
|
|
11
|
-
plugin?: 'bundle' | 'whybundled' | 'statoscope';
|
|
11
|
+
plugin?: 'bundle' | 'whybundled' | 'statoscope' | 'rsdoctor';
|
|
12
12
|
showConfig?: boolean;
|
|
13
13
|
};
|
|
14
14
|
|