t-comm
Version:
专业、稳定、纯粹的工具库
157 lines (152 loc) • 6.48 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var fs_fsUtil = require('../fs/fs-util.js');
var nodejs_child_process = require('../nodejs/child_process.js');
var nodejs_fs = require('../nodejs/fs.js');
var nodejs_os = require('../nodejs/os.js');
var nodejs_path = require('../nodejs/path.js');
require('@babel/runtime/helpers/toConsumableArray');
require('../fs/fs.js');
require('../nodejs/crypto.js');
require('../time/time.js');
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
var DEFAULT_EXCLUDE_GLOBS = ['*.map'];
function tryZipBin(options) {
var fs = nodejs_fs.getFs();
var path = nodejs_path.getPath();
var os = nodejs_os.getOs();
var _getChildProcess = nodejs_child_process.getChildProcess(),
execFileSync = _getChildProcess.execFileSync;
var tmpZip = path.join(os.tmpdir(), "t-comm-zip-size-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 8), ".zip"));
var excludeArgs = [];
var _iterator = _createForOfIteratorHelper(options.excludeGlobs),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var g = _step.value;
excludeArgs.push('-x', g);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
try {
// -r 递归 -q 静默 -X 不带额外属性 -9 最大压缩比
// cwd 设为产物目录,避免把绝对路径写入包
execFileSync(options.zipBin, ['-rqX9', tmpZip, '.'].concat(excludeArgs), {
cwd: options.outputDir,
stdio: ['ignore', 'ignore', 'ignore']
});
var _fs$statSync = fs.statSync(tmpZip),
size = _fs$statSync.size;
try {
fs.unlinkSync(tmpZip);
} catch (_) {/* ignore */}
return {
zipSize: size,
zipMethod: 'zip'
};
} catch (_) {
try {
fs.unlinkSync(tmpZip);
} catch (__) {/* ignore */}
return null;
}
}
function listAllFiles(root, excludeMap) {
var path = nodejs_path.getPath();
var result = [];
fs_fsUtil.traverseFolder(function (filePath) {
if (excludeMap && /\.map$/i.test(filePath)) return;
result.push(path.relative(root, filePath));
}, root);
return result;
}
function tryGzipSum(options) {
var _a, _b;
var fs = nodejs_fs.getFs();
var path = nodejs_path.getPath();
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
var zlib = require('zlib');
var list = (_b = (_a = options.files) === null || _a === void 0 ? void 0 : _a.map(function (f) {
return f.name;
})) !== null && _b !== void 0 ? _b : listAllFiles(options.outputDir, options.excludeMapInGzip);
var sum = 0;
var _iterator2 = _createForOfIteratorHelper(list),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var name = _step2.value;
if (options.excludeMapInGzip && /\.map$/i.test(name)) continue;
var buf = fs.readFileSync(path.join(options.outputDir, name));
// Buffer 在运行时完全兼容 InputType,但 Node 类型定义中 Buffer.buffer 可能为 SharedArrayBuffer,
// 导致类型检查失败。使用 Uint8Array.from(buf) 显式转换可消除类型错误且零运行时开销。
var input = Uint8Array.from(buf);
sum += zlib.gzipSync(input, {
level: 9
}).length;
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return {
zipSize: sum,
zipMethod: 'gzip-sum'
};
} catch (_) {
return null;
}
}
/**
* 获取构建产物目录的 zip 压缩后体积,跨平台兜底。
*
* 估算策略:
* 1) 优先调用系统 `zip` 命令打成真实 zip 包,删除后返回字节数(最准)
* 2) 不可用时,降级为 `zlib.gzipSync` 逐文件累加(估算值,比真实 zip 略大,因为没有共享字典)
* 3) 仍失败则返回 `{ zipSize: null, zipMethod: 'none' }`
*
* Windows 默认没有 `zip` 命令,会自动降级到 gzip-sum,无需额外配置。
*
* @example
* ```ts
* import { getZipSize } from 't-comm';
*
* const { zipSize, zipMethod } = getZipSize({ outputDir: '/path/to/dist' });
* console.log(zipSize, zipMethod); // 1234567 'zip'
* ```
*/
function getZipSize(options) {
var outputDir = options.outputDir,
files = options.files,
_options$excludeGlobs = options.excludeGlobs,
excludeGlobs = _options$excludeGlobs === void 0 ? DEFAULT_EXCLUDE_GLOBS : _options$excludeGlobs,
_options$excludeMapIn = options.excludeMapInGzip,
excludeMapInGzip = _options$excludeMapIn === void 0 ? true : _options$excludeMapIn,
_options$zipBin = options.zipBin,
zipBin = _options$zipBin === void 0 ? 'zip' : _options$zipBin;
// 方式一:系统 zip 命令
var fromZip = tryZipBin({
outputDir: outputDir,
excludeGlobs: excludeGlobs,
zipBin: zipBin
});
if (fromZip) return fromZip;
// 方式二:逐文件 gzip 累加
var fromGzip = tryGzipSum({
outputDir: outputDir,
excludeMapInGzip: excludeMapInGzip,
files: files
});
if (fromGzip) return fromGzip;
return {
zipSize: null,
zipMethod: 'none'
};
}
exports.getZipSize = getZipSize;