Skip to content

Commit ecc4d3f

Browse files
committed
NR-685 Research esbuild as a replacement for webpack
- Gather stats on webpack build times to a local stats.json file
1 parent 63c4c85 commit ecc4d3f

File tree

8 files changed

+305
-5
lines changed

8 files changed

+305
-5
lines changed

Diff for: jb/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ node_modules
1616
temp.json
1717
.gradle
1818
.DS_Store
19+
stats.json

Diff for: jb/webpack.config.js

+73
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,78 @@ const TerserPlugin = require("terser-webpack-plugin");
1010
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
1111
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
1212

13+
class CompileStatsPlugin {
14+
constructor(env) {
15+
this.enabled = !env.production;
16+
}
17+
total = 0;
18+
count = 0;
19+
since = Date.now();
20+
21+
deserialize() {
22+
if (!fs.existsSync("./stats.json")) {
23+
return;
24+
}
25+
try {
26+
const dataStr = fs.readFileSync("./stats.json", { encoding: "utf8" });
27+
const data = JSON.parse(dataStr);
28+
this.total = data.total;
29+
this.count = data.count;
30+
this.since = data.since;
31+
} catch (e) {
32+
// ignore
33+
}
34+
}
35+
36+
serialize() {
37+
fs.writeFileSync(
38+
"./stats.json",
39+
JSON.stringify({ count: this.count, total: this.total, since: this.since }, null, 2),
40+
{ encoding: "utf8" }
41+
);
42+
}
43+
44+
timeSpan(ms) {
45+
let day, hour, minute, seconds;
46+
seconds = Math.floor(ms / 1000);
47+
minute = Math.floor(seconds / 60);
48+
seconds = seconds % 60;
49+
hour = Math.floor(minute / 60);
50+
minute = minute % 60;
51+
day = Math.floor(hour / 24);
52+
hour = hour % 24;
53+
return {
54+
day,
55+
hour,
56+
minute,
57+
seconds
58+
};
59+
}
60+
61+
done(stats) {
62+
const elapsed = stats.endTime - stats.startTime;
63+
this.total += elapsed;
64+
this.count++;
65+
const { day, hour, minute, seconds } = this.timeSpan(this.total);
66+
const totalTime = `${day}d ${hour}h ${minute}m ${seconds}s`;
67+
this.serialize();
68+
const sinceStr = new Date(this.since).toLocaleString();
69+
// nextTick to make stats is last line after webpack logs
70+
process.nextTick(() =>
71+
console.info(
72+
`⌛ compileTime: ${elapsed}ms, compilCount: ${this.count}, totalCompileTime: ${totalTime}, since: ${sinceStr}`
73+
)
74+
);
75+
}
76+
77+
apply(compiler) {
78+
if (this.enabled) {
79+
this.deserialize();
80+
compiler.hooks.done.tap("done", this.done.bind(this));
81+
}
82+
}
83+
}
84+
1385
module.exports = function(env, argv) {
1486
env = env || {};
1587
env.analyzeBundle = Boolean(env.analyzeBundle);
@@ -55,6 +127,7 @@ module.exports = function(env, argv) {
55127
const context = path.resolve(__dirname, "webview");
56128

57129
const plugins = [
130+
new CompileStatsPlugin(env),
58131
new CleanWebpackPlugin({
59132
cleanOnceBeforeBuildPatterns: ["**/*"],
60133
verbose: true

Diff for: shared/agent/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ npm-debug.log
55
.idea/workspace.xml
66
.nyc_output
77
src/protocol/*.js
8+
stats.json

Diff for: shared/agent/webpack.config.js

+75-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,79 @@ const path = require("path");
44
const { CleanWebpackPlugin: CleanPlugin } = require("clean-webpack-plugin");
55
const FileManagerPlugin = require("filemanager-webpack-plugin");
66
const TerserPlugin = require("terser-webpack-plugin");
7+
const fs = require("fs");
8+
9+
class CompileStatsPlugin {
10+
constructor(env) {
11+
this.enabled = !env.production;
12+
}
13+
total = 0;
14+
count = 0;
15+
since = Date.now();
16+
17+
deserialize() {
18+
if (!fs.existsSync("./stats.json")) {
19+
return;
20+
}
21+
try {
22+
const dataStr = fs.readFileSync("./stats.json", { encoding: "utf8" });
23+
const data = JSON.parse(dataStr);
24+
this.total = data.total;
25+
this.count = data.count;
26+
this.since = data.since;
27+
} catch (e) {
28+
// ignore
29+
}
30+
}
31+
32+
serialize() {
33+
fs.writeFileSync(
34+
"./stats.json",
35+
JSON.stringify({ count: this.count, total: this.total, since: this.since }, null, 2),
36+
{ encoding: "utf8" }
37+
);
38+
}
39+
40+
timeSpan(ms) {
41+
let day, hour, minute, seconds;
42+
seconds = Math.floor(ms / 1000);
43+
minute = Math.floor(seconds / 60);
44+
seconds = seconds % 60;
45+
hour = Math.floor(minute / 60);
46+
minute = minute % 60;
47+
day = Math.floor(hour / 24);
48+
hour = hour % 24;
49+
return {
50+
day,
51+
hour,
52+
minute,
53+
seconds
54+
};
55+
}
56+
57+
done(stats) {
58+
const elapsed = stats.endTime - stats.startTime;
59+
this.total += elapsed;
60+
this.count++;
61+
const { day, hour, minute, seconds } = this.timeSpan(this.total);
62+
const totalTime = `${day}d ${hour}h ${minute}m ${seconds}s`;
63+
this.serialize();
64+
const sinceStr = new Date(this.since).toLocaleString();
65+
// nextTick to make stats is last line after webpack logs
66+
process.nextTick(() =>
67+
console.info(
68+
`⌛ compileTime: ${elapsed}ms, compilCount: ${this.count}, totalCompileTime: ${totalTime}, since: ${sinceStr}`
69+
)
70+
);
71+
}
72+
73+
apply(compiler) {
74+
if (this.enabled) {
75+
this.deserialize();
76+
compiler.hooks.done.tap("done", this.done.bind(this));
77+
}
78+
}
79+
}
780

881
module.exports = function(env, argv) {
982
env = env || {};
@@ -64,7 +137,8 @@ module.exports = function(env, argv) {
64137
// Added because of https://github.com/felixge/node-formidable/issues/337
65138
new webpack.DefinePlugin({ "global.GENTLY": false }),
66139
// Ignores optional worker_threads require by the write-file-atomic package
67-
new webpack.IgnorePlugin({ resourceRegExp: /^worker_threads$/ })
140+
new webpack.IgnorePlugin({ resourceRegExp: /^worker_threads$/ }),
141+
new CompileStatsPlugin(env)
68142
];
69143

70144
return {

Diff for: vs/.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -344,4 +344,5 @@ licenses/Debug/teamdev.licenses
344344
licenses/Release/teamdev.licenses
345345
src/CodeStream.VisualStudio/teamdev.licenses
346346
src/protocols/
347-
src/CodeStream.VisualStudio/Internal/CodeStream.VisualStudio.Shell.*.dll
347+
src/CodeStream.VisualStudio/Internal/CodeStream.VisualStudio.Shell.*.dll
348+
stats.json

Diff for: vs/webpack.config.js

+74-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,78 @@ const TerserPlugin = require("terser-webpack-plugin");
1010
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
1111
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
1212

13+
class CompileStatsPlugin {
14+
constructor(env) {
15+
this.enabled = !env.production;
16+
}
17+
total = 0;
18+
count = 0;
19+
since = Date.now();
20+
21+
deserialize() {
22+
if (!fs.existsSync("./stats.json")) {
23+
return;
24+
}
25+
try {
26+
const dataStr = fs.readFileSync("./stats.json", { encoding: "utf8" });
27+
const data = JSON.parse(dataStr);
28+
this.total = data.total;
29+
this.count = data.count;
30+
this.since = data.since;
31+
} catch (e) {
32+
// ignore
33+
}
34+
}
35+
36+
serialize() {
37+
fs.writeFileSync(
38+
"./stats.json",
39+
JSON.stringify({ count: this.count, total: this.total, since: this.since }, null, 2),
40+
{ encoding: "utf8" }
41+
);
42+
}
43+
44+
timeSpan(ms) {
45+
let day, hour, minute, seconds;
46+
seconds = Math.floor(ms / 1000);
47+
minute = Math.floor(seconds / 60);
48+
seconds = seconds % 60;
49+
hour = Math.floor(minute / 60);
50+
minute = minute % 60;
51+
day = Math.floor(hour / 24);
52+
hour = hour % 24;
53+
return {
54+
day,
55+
hour,
56+
minute,
57+
seconds
58+
};
59+
}
60+
61+
done(stats) {
62+
const elapsed = stats.endTime - stats.startTime;
63+
this.total += elapsed;
64+
this.count++;
65+
const { day, hour, minute, seconds } = this.timeSpan(this.total);
66+
const totalTime = `${day}d ${hour}h ${minute}m ${seconds}s`;
67+
this.serialize();
68+
const sinceStr = new Date(this.since).toLocaleString();
69+
// nextTick to make stats is last line after webpack logs
70+
process.nextTick(() =>
71+
console.info(
72+
`⌛ compileTime: ${elapsed}ms, compilCount: ${this.count}, totalCompileTime: ${totalTime}, since: ${sinceStr}`
73+
)
74+
);
75+
}
76+
77+
apply(compiler) {
78+
if (this.enabled) {
79+
this.deserialize();
80+
compiler.hooks.done.tap("done", this.done.bind(this));
81+
}
82+
}
83+
}
84+
1385
module.exports = function(env, argv) {
1486
env = env || {};
1587
env.analyzeBundle = Boolean(env.analyzeBundle);
@@ -89,7 +161,8 @@ module.exports = function(env, argv) {
89161
}),
90162
new ForkTsCheckerPlugin({
91163
async: false
92-
})
164+
}),
165+
new CompileStatsPlugin(env)
93166
];
94167

95168
if (env.analyzeBundle) {

Diff for: vscode/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ codestream-*.info
1212
.AppleDouble
1313
.LSOverride
1414
*~
15+
./stats*.json

Diff for: vscode/webpack.config.js

+78-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,80 @@ const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPl
1414
const HtmlWebpackInlineSourcePlugin = require("@effortlessmotion/html-webpack-inline-source-plugin");
1515
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
1616

17+
class CompileStatsPlugin {
18+
constructor(name, env) {
19+
this.name = name
20+
this.enabled = !env.production;
21+
this.filename = `./stats-webpack-${this.name}`
22+
}
23+
total = 0;
24+
count = 0;
25+
since = Date.now();
26+
27+
deserialize() {
28+
if (!fs.existsSync(this.filename)) {
29+
return;
30+
}
31+
try {
32+
const dataStr = fs.readFileSync(this.filename, { encoding: "utf8" });
33+
const data = JSON.parse(dataStr);
34+
this.total = data.total;
35+
this.count = data.count;
36+
this.since = data.since;
37+
} catch (e) {
38+
// ignore
39+
}
40+
}
41+
42+
serialize() {
43+
fs.writeFileSync(
44+
this.filename,
45+
JSON.stringify({ count: this.count, total: this.total, since: this.since }, null, 2),
46+
{ encoding: "utf8" }
47+
);
48+
}
49+
50+
timeSpan(ms) {
51+
let day, hour, minute, seconds;
52+
seconds = Math.floor(ms / 1000);
53+
minute = Math.floor(seconds / 60);
54+
seconds = seconds % 60;
55+
hour = Math.floor(minute / 60);
56+
minute = minute % 60;
57+
day = Math.floor(hour / 24);
58+
hour = hour % 24;
59+
return {
60+
day,
61+
hour,
62+
minute,
63+
seconds
64+
};
65+
}
66+
67+
done(stats) {
68+
const elapsed = stats.endTime - stats.startTime;
69+
this.total += elapsed;
70+
this.count++;
71+
const { day, hour, minute, seconds } = this.timeSpan(this.total);
72+
const totalTime = `${day}d ${hour}h ${minute}m ${seconds}s`;
73+
this.serialize();
74+
const sinceStr = new Date(this.since).toLocaleString();
75+
// nextTick to make stats is last line after webpack logs
76+
process.nextTick(() =>
77+
console.info(
78+
`⌛ ${this.name} compileTime: ${elapsed}ms, compilCount: ${this.count}, totalCompileTime: ${totalTime}, since: ${sinceStr}`
79+
)
80+
);
81+
}
82+
83+
apply(compiler) {
84+
if (this.enabled) {
85+
this.deserialize();
86+
compiler.hooks.done.tap("done", this.done.bind(this));
87+
}
88+
}
89+
}
90+
1791
module.exports = function(env, argv) {
1892
env = env || {};
1993
env.analyzeBundle = Boolean(env.analyzeBundle);
@@ -87,7 +161,8 @@ function getExtensionConfig(mode, env) {
87161
}
88162
]
89163
}
90-
})
164+
}),
165+
new CompileStatsPlugin("extensions", env)
91166
];
92167

93168
if (env.analyzeDeps) {
@@ -223,7 +298,8 @@ function getWebviewConfig(mode, env) {
223298
new HtmlWebpackInlineSourcePlugin(),
224299
new ForkTsCheckerPlugin({
225300
async: false
226-
})
301+
}),
302+
new CompileStatsPlugin("webview", env)
227303
];
228304

229305
if (env.analyzeBundleWebview) {

0 commit comments

Comments
 (0)