Files
cocos/tools/package-optimize.js
刘宇飞 d393302388 Complete Cocos Creator port with level bundles, themes, and tooling.
Adds level prefabs, theme assets, audio, extensions, and deployment scripts for the Unity WebGL migration.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 15:30:58 +08:00

107 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 打包优化关卡库压缩、settings 预加载策略、体积报告。
* 供 package-for-project.js / package-for-cdn.js 共用。
*/
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');
function formatBytes(n) {
if (n >= 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
if (n >= 1024) return `${(n / 1024).toFixed(1)} KB`;
return `${n} B`;
}
function dirSize(root) {
if (!fs.existsSync(root)) return 0;
let total = 0;
for (const ent of fs.readdirSync(root, { withFileTypes: true })) {
const p = path.join(root, ent.name);
if (ent.isDirectory()) total += dirSize(p);
else total += fs.statSync(p).size;
}
return total;
}
function fileSize(p) {
return fs.existsSync(p) ? fs.statSync(p).size : 0;
}
/** 压缩关卡库 JSON去掉空白不改变语义 */
function minifyLevelsDatabase(srcPath, dstPath) {
const raw = fs.readFileSync(srcPath, 'utf8');
const data = JSON.parse(raw);
const compact = JSON.stringify(data);
fs.writeFileSync(dstPath, compact, 'utf8');
return { before: Buffer.byteLength(raw, 'utf8'), after: Buffer.byteLength(compact, 'utf8') };
}
/** 可选:生成 .br 供静态服务器直接返回 */
function brotliCompressFile(srcPath, dstPath, quality = 9) {
const input = fs.readFileSync(srcPath);
const out = zlib.brotliCompressSync(input, {
params: { [zlib.constants.BROTLI_PARAM_QUALITY]: quality },
});
fs.writeFileSync(dstPath, out);
return { raw: input.length, br: out.length };
}
/**
* 调整预加载 bundle默认只预加载 mainresources / level-prefabs 按需加载。
* @param {object} opts
* @param {boolean} [opts.preloadResources=false]
* @param {boolean} [opts.preloadLevelPrefabs=false]
*/
function patchPreloadSettings(settingsObj, opts = {}) {
const preloadResources = opts.preloadResources === true;
const preloadLevelPrefabs = opts.preloadLevelPrefabs === true;
const bundles = settingsObj.assets?.projectBundles || [];
const preload = [{ bundle: 'main' }];
if (preloadResources && bundles.includes('resources')) {
preload.push({ bundle: 'resources' });
}
if (preloadLevelPrefabs && bundles.includes('level-prefabs')) {
preload.push({ bundle: 'level-prefabs' });
}
settingsObj.assets = settingsObj.assets || {};
settingsObj.assets.preloadBundles = preload;
return settingsObj;
}
function printPackageReport(outDir, opts = {}) {
const lines = ['\n>>> 包体积报告:'];
const entries = [
['cocos-js', path.join(outDir, 'cocos-js')],
['src', path.join(outDir, 'src')],
['assets/main', path.join(outDir, 'assets', 'main')],
['assets/resources', path.join(outDir, 'assets', 'resources')],
['assets/level-prefabs', path.join(outDir, 'assets', 'level-prefabs')],
['assets/internal', path.join(outDir, 'assets', 'internal')],
['levels-database.json', path.join(outDir, 'levels-database.json')],
['levels-database.json.br', path.join(outDir, 'levels-database.json.br')],
['Build', path.join(outDir, 'Build')],
];
let total = 0;
for (const [label, p] of entries) {
if (!fs.existsSync(p)) continue;
const sz = fs.statSync(p).isDirectory() ? dirSize(p) : fileSize(p);
if (sz <= 0) continue;
total += sz;
lines.push(` ${label.padEnd(28)} ${formatBytes(sz)}`);
}
const grand = dirSize(outDir);
lines.push(` ${'合计(顶层目录)'.padEnd(28)} ${formatBytes(grand)}`);
if (opts.preloadNote) lines.push(` 预加载: ${opts.preloadNote}`);
console.log(lines.join('\n'));
}
module.exports = {
formatBytes,
dirSize,
fileSize,
minifyLevelsDatabase,
brotliCompressFile,
patchPreloadSettings,
printPackageReport,
};