Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168FQuoV7vDh5nhnSowW5cp
99 lines
3.7 KiB
JavaScript
99 lines
3.7 KiB
JavaScript
// 스프레드시트 크기 재기 — gzip 크기(바이트). `test_spreadsheet_size.py` 가 부름.
|
|
// node spreadsheet_size.mjs <저장소 뿌리> → {"engine": {js, css}, "total": {js, css}, "static": [...]}
|
|
// engine = 엔진 파일만 줄여 묶은 크기 · total = 실제 앱 빌드에서 스프레드시트를 열 때 받는 조각
|
|
// (스프레드시트 조각 + 끌어오는 공용 조각 + css · 첫 화면 `index.html` 조각은 뺌).
|
|
// static = 스프레드시트 조각을 정적으로 끌어오는 조각(비어야 함 — 늦게만 받음).
|
|
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { pathToFileURL } from "node:url";
|
|
import { gzipSync } from "node:zlib";
|
|
|
|
const root = path.resolve(process.argv[2] ?? ".");
|
|
const dir = path.join(root, "A00_Common", "spreadsheet");
|
|
const { build } = await import(
|
|
pathToFileURL(path.join(root, "config/node_modules/vite/dist/node/index.js")).href
|
|
);
|
|
|
|
const ENGINE = [
|
|
"spreadsheet_address",
|
|
"spreadsheet_parser",
|
|
"spreadsheet_eval",
|
|
"spreadsheet_graph",
|
|
"spreadsheet_refshift",
|
|
"spreadsheet_commands",
|
|
"spreadsheet_history",
|
|
"spreadsheet_recalc",
|
|
"spreadsheet_functions",
|
|
"spreadsheet_numfmt",
|
|
"spreadsheet_fill",
|
|
];
|
|
|
|
async function engineSize() {
|
|
const out = await build({
|
|
configFile: false,
|
|
logLevel: "silent",
|
|
root,
|
|
resolve: { alias: { "@ui": path.join(root, "ui_template") } },
|
|
build: {
|
|
write: false,
|
|
minify: true,
|
|
target: "es2022",
|
|
lib: { entry: ENGINE.map((name) => path.join(dir, `${name}.ts`)), formats: ["es"] },
|
|
},
|
|
});
|
|
let js = 0;
|
|
for (const o of (Array.isArray(out) ? out : [out]).flatMap((o) => o.output)) {
|
|
if (o.type === "chunk") js += gzipSync(o.code).length;
|
|
}
|
|
return { js, css: 0 };
|
|
}
|
|
|
|
async function appSize() {
|
|
const outDir = fs.mkdtempSync(path.join(os.tmpdir(), "aislo-sheet-size-"));
|
|
try {
|
|
await build({
|
|
configLoader: "runner",
|
|
configFile: path.join(root, "vite.config.ts"),
|
|
logLevel: "silent",
|
|
build: { outDir, emptyOutDir: true, manifest: true },
|
|
});
|
|
const manifest = JSON.parse(fs.readFileSync(path.join(outDir, ".vite/manifest.json"), "utf8"));
|
|
const key = Object.keys(manifest).find((k) => k.endsWith("spreadsheet/spreadsheet.ts"));
|
|
const gz = (file) => gzipSync(fs.readFileSync(path.join(outDir, file))).length;
|
|
// M02 가 이미 받은 조각은 새 몫이 아님 — 첫 화면 · M02 페이지 · M02 표(ui_template_sheet 등)
|
|
// 의 정적 import 사슬. 산출근거 카드는 집계표를 연 뒤에만 열림.
|
|
const first = new Set();
|
|
const mark = (k) => {
|
|
if (first.has(k)) return;
|
|
first.add(k);
|
|
for (const i of manifest[k].imports ?? []) mark(i);
|
|
};
|
|
const page = Object.keys(manifest).find((k) => k.endsWith("M02_MasterTemplete_UI_Page.ts"));
|
|
mark("index.html");
|
|
mark(page);
|
|
for (const d of manifest[page].dynamicImports ?? []) if (d !== key) mark(d);
|
|
const size = { js: 0, css: 0 };
|
|
const seen = new Set();
|
|
const walk = (k) => {
|
|
if (seen.has(k) || first.has(k)) return;
|
|
seen.add(k);
|
|
const e = manifest[k];
|
|
size.js += gz(e.file);
|
|
for (const c of e.css ?? []) size.css += gz(c);
|
|
for (const i of e.imports ?? []) walk(i); // 그 밖 공용 조각은 셈(넉넉히)
|
|
};
|
|
walk(key);
|
|
const statics = Object.entries(manifest)
|
|
.filter(([, v]) => (v.imports ?? []).includes(key))
|
|
.map(([k]) => k);
|
|
return { total: size, static: statics };
|
|
} finally {
|
|
fs.rmSync(outDir, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
const engine = await engineSize();
|
|
const { total, static: statics } = await appSize();
|
|
console.log(JSON.stringify({ engine, total, static: statics }));
|