-
Notifications
You must be signed in to change notification settings - Fork 0
/
zip.js
107 lines (84 loc) · 3.12 KB
/
zip.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
"use strict";
const path = require("path");
const fs = require("fs");
const zlib = require("zlib");
const utils = require("./utils");
exports.run = async function(directory) {
let stats = {
og: { count: 0, size: 0 },
gz: { count: 0, size: 0 },
br: { count: 0, size: 0 },
};
let startTime = process.hrtime.bigint();
for (let p of utils.walkDir(directory)) {
let ext = path.extname(p);
if (![".css", ".htm", ".html", ".js", ".json", ".mjs", ".svg", ".txt", ".xml"].includes(ext)) {
continue;
}
let size = fs.statSync(p).size;
stats.og.count += 1;
stats.og.size += size;
let [gzSize, brSize] = await Promise.all([makeGzip(p, size), makeBrotli(p, size)]);
if (gzSize != null) {
stats.gz.count += 1;
stats.gz.size += gzSize;
} else {
stats.gz.size += size;
}
if (brSize != null) {
stats.br.count += 1;
stats.br.size += brSize;
} else {
stats.br.size += size;
}
}
let endTime = process.hrtime.bigint();
let duration = utils.humanDuration(endTime - startTime);
console.log(`zip: Took ${duration} to complete`);
let ogSize = utils.humanSize(stats.og.size);
console.log(` original: ${ogSize}, ${stats.og.count} text file(s)`);
for (let [name, type] of [["gzip", "gz"], ["brotli", "br"]]) {
let size = utils.humanSize(stats[type].size);
let savings = 100 - (stats.og.size === 0 ? 100 : stats[type].size/stats.og.size * 100);
let skip = stats.og.count - stats[type].count;
console.log(` ${name}: ${size} (saved ${savings.toFixed(2)}%), skipped ${skip} file(s)`);
}
}
function makeGzip(ogPath, ogSize) {
let gzPath = ogPath + ".gz";
let gzInput = fs.createReadStream(ogPath);
let gzOutput = fs.createWriteStream(gzPath);
let compressor = zlib.createGzip({ level: zlib.constants.Z_BEST_COMPRESSION });
gzInput.pipe(compressor).pipe(gzOutput);
return new Promise((resolve) => {
gzOutput.on("close", () => {
let gzSize = fs.statSync(gzPath).size;
if (gzSize > ogSize) {
fs.unlinkSync(gzPath);
resolve(null);
}
resolve(gzSize);
});
});
}
function makeBrotli(ogPath, ogSize) {
let brPath = ogPath + ".br";
let brInput = fs.createReadStream(ogPath);
let brOutput = fs.createWriteStream(brPath);
let compressor = zlib.createBrotliCompress({
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
[zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY,
[zlib.constants.BROTLI_PARAM_SIZE_HINT]: ogSize,
});
brInput.pipe(compressor).pipe(brOutput);
return new Promise((resolve) => {
brOutput.on("close", () => {
let brSize = fs.statSync(brPath).size;
if (brSize > ogSize) {
fs.unlinkSync(brPath);
resolve(null);
}
resolve(brSize);
});
});
}