-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.js
More file actions
159 lines (137 loc) · 6.1 KB
/
build.js
File metadata and controls
159 lines (137 loc) · 6.1 KB
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
const fs = require('fs-extra');
const path = require('path');
const terser = require('terser');
const CleanCSS = require('clean-css');
const htmlmin = require('html-minifier').minify;
const archiver = require('archiver');
const config = {
releaseDir: 'release',
zipName: 'release.zip',
ignoreList: [
'node_modules',
'dist',
'.git',
'.gitignore',
'build.js',
'README.md',
'main.js',
'preload.js',
'float.html',
'updater.html',
'main.js',
'package.json',
'package-lock.json'
]
};
function getReadableFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
async function processDirectory(sourceDir, destDir) {
let totalOriginalSize = 0;
let totalMinifiedSize = 0;
const entries = await fs.readdir(sourceDir);
for (const entryName of entries) {
if (config.ignoreList.includes(entryName) || entryName === config.releaseDir) {
continue;
}
const sourcePath = path.join(sourceDir, entryName);
const destPath = path.join(destDir, entryName);
const stats = await fs.stat(sourcePath);
if (stats.isDirectory()) {
await fs.ensureDir(destPath);
const subDirSizes = await processDirectory(sourcePath, destPath);
totalOriginalSize += subDirSizes.originalSize;
totalMinifiedSize += subDirSizes.minifiedSize;
} else if (stats.isFile()) {
const originalSize = stats.size;
totalOriginalSize += originalSize;
let minifiedSize = originalSize;
let outputContent;
const ext = path.extname(entryName).toLowerCase();
const relativePath = path.relative(__dirname, sourcePath);
try {
if (ext === '.js') {
const code = await fs.readFile(sourcePath, 'utf8');
const result = await terser.minify(code, { toplevel: true });
if (result.error) throw result.error;
outputContent = result.code;
} else if (ext === '.css') {
const code = await fs.readFile(sourcePath, 'utf8');
const result = new CleanCSS({ level: 2 }).minify(code);
if (result.errors.length > 0) throw new Error(result.errors.join(', '));
outputContent = result.styles;
} else if (ext === '.html') {
const code = await fs.readFile(sourcePath, 'utf8');
outputContent = htmlmin(code, {
collapseWhitespace: true,
removeComments: true,
minifyJS: true,
minifyCSS: true,
removeEmptyAttributes: true
});
} else if (ext === '.json') {
const code = await fs.readFile(sourcePath, 'utf8');
outputContent = JSON.stringify(JSON.parse(code));
} else {
await fs.copy(sourcePath, destPath);
totalMinifiedSize += originalSize;
console.log(`已复制: ${relativePath}`);
continue;
}
minifiedSize = Buffer.byteLength(outputContent, 'utf8');
totalMinifiedSize += minifiedSize;
await fs.writeFile(destPath, outputContent, 'utf8');
const reduction = (((originalSize - minifiedSize) / originalSize) * 100).toFixed(2);
console.log(`已压缩: ${relativePath} | ${getReadableFileSize(originalSize)} -> ${getReadableFileSize(minifiedSize)} (节省 ${reduction}%)`);
} catch (error) {
console.error(`处理文件 ${relativePath} 时出错:`, error.message);
await fs.copy(sourcePath, destPath);
totalMinifiedSize += originalSize;
}
}
}
return { originalSize: totalOriginalSize, minifiedSize: totalMinifiedSize };
}
async function build() {
console.time('构建总耗时');
const releasePath = path.join(__dirname, config.releaseDir);
try {
console.log(`[1/4] 正在清空目标文件夹: ${config.releaseDir}/`);
await fs.emptyDir(releasePath);
console.log('[2/4] 正在处理所有文件...');
const { originalSize: totalOriginalSize, minifiedSize: totalMinifiedSize } = await processDirectory(__dirname, releasePath);
console.log('\n[3/4] 正在创建 ZIP 压缩包...');
const zipPath = path.join(releasePath, config.zipName);
const output = fs.createWriteStream(zipPath);
const archive = archiver('zip', { zlib: { level: 9 } });
archive.pipe(output);
archive.directory(releasePath, false, (entry) => {
return entry.name !== config.zipName ? entry : false;
});
await new Promise((resolve, reject) => {
output.on('close', resolve);
archive.on('error', reject);
archive.finalize();
});
console.log(`ZIP 压缩包已创建: ${path.join(config.releaseDir, config.zipName)}`);
console.log('\n[4/4] 构建完成!');
console.log('--- 构建摘要 ---');
console.log(`所有文件原始总大小: ${getReadableFileSize(totalOriginalSize)}`);
console.log(`压缩后文件总大小: ${getReadableFileSize(totalMinifiedSize)}`);
if (totalOriginalSize > 0) {
const reductionPercentage = ((totalOriginalSize - totalMinifiedSize) / totalOriginalSize * 100).toFixed(2);
console.log(`总空间节省百分比: ${reductionPercentage}%`);
}
console.log('----------------');
console.timeEnd('构建总耗时');
} catch (error) {
console.error('\n构建过程中发生严重错误:', error);
console.timeEnd('构建总耗时');
process.exit(1);
}
}
build();