Skip to content

Commit

Permalink
text vis
Browse files Browse the repository at this point in the history
  • Loading branch information
exoego committed May 6, 2024
1 parent d9cb45f commit 3af72d7
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 11 deletions.
143 changes: 132 additions & 11 deletions src/compare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,39 @@ import fs from "node:fs";
import path from "node:path";
import { filesize as originalFilesize } from "filesize";
import type { CompareResult, Options, Report } from "./types";
import { loadAnalysisJson } from "./utils";
import { loadAnalysisJson, loadMetaFile } from "./utils";

function buildTree(input: Record<string, { bytesInOutput: number }>): TreeMapNode {
const root: TreeMapNode = { name: "", path: "", value: 0, children: [] };
for (const [filePath, { bytesInOutput }] of Object.entries(input)) {
const directories = filePath.split("/");
buildNode(root, directories, bytesInOutput);
}
return root;
}

function buildNode(
node: TreeMapNode,
directories: Array<string>,
value: number,
): void {
const dir = directories.shift();
if (dir === undefined) {
return;
}
let child = node.children.find((child) => child.name === dir);
if (!child) {
child = {
name: dir,
path: `${node.path}/${dir}`.replace(/^\//, ""),
value: value,
children: [],
};
node.children.push(child);
}
node.value += value;
buildNode(child, directories, value);
}

export function compare(input: Options): void {
let hasAnyChange = false;
Expand All @@ -27,22 +59,44 @@ This analysis was generated by [esbuild-bundle-analyzer](https://github.com/exoe
base = {};
}

const trees = new Map<string, Array<TreeMapNode>>();
for (const metafileRelPath of input.metafiles) {
const metafile = loadMetaFile(path.join(process.cwd(), metafileRelPath));
for (const [outfile, buildMeta] of Object.entries(metafile.outputs)) {
const tree = buildTree(buildMeta.inputs);
trees.set(`${metafileRelPath} -> ${outfile}`, tree);

fs.writeFileSync(
path.join(
process.cwd(),
input.analyzerDirectory,
"tree.json",
),
JSON.stringify(tree, null, 2),
);
}
}

const allOutFiles: string[] = [
...new Set([...Object.keys(current), ...Object.keys(base)]),
].sort();

const comparison: Array<CompareResult> = allOutFiles.map((outfile) => {
const currentStats = current[outfile];
const baseStats = base[outfile];

if (!currentStats) {
hasAnyChange = true;
// deleted out file
return { ...baseStats, diff: -1, remark: "deleted" };
return { ...baseStats, diff: -1, remark: "deleted", tree: undefined };
}

const tree = trees.get(`${currentStats.metafile} -> ${currentStats.outfile}`);

if (!baseStats) {
hasAnyChange = true;
// new out file
return { ...currentStats, diff: -1, remark: "added" };
return { ...currentStats, diff: -1, remark: "added", tree };
}
const diff = currentStats.bytes - baseStats.bytes;
const increase = !!Math.sign(diff);
Expand All @@ -52,12 +106,14 @@ This analysis was generated by [esbuild-bundle-analyzer](https://github.com/exoe
return {
...currentStats,
diff,
tree,
remark: increase ? "increased" : "decreased",
};
});

if (hasAnyChange) {
output += markdownTable(comparison, input.percentExtraAttention);
output += fileSizeTable(comparison, input.percentExtraAttention);

if (input.showDetails) {
output += `\n<details>
Expand All @@ -80,14 +136,6 @@ This analysis was generated by [esbuild-bundle-analyzer](https://github.com/exoe
// consistently find the right comment to edit as more commits are pushed.
output += `<!-- __ESBUILD_BUNDLE_${input.name} -->`;

// Log mostly for testing and debugging.
// This will show up in the github actions console.
console.dir({
input,
hasAnyChange,
output,
});

// Write the output to a file which is later read in
// as comment contents by the actions workflow.
fs.mkdirSync(path.join(process.cwd(), input.analyzerDirectory), {
Expand Down Expand Up @@ -128,6 +176,79 @@ Meta File | Out File | Size (raw) | Note
${rows}`;
}

/**
* Find the first twenty largest nodes in root tree.
* Dig nodes until the depth of 3.
*/
function findLargeDirectories(
root: TreeMapNode,
) {
const nodes: TreeMapNode[] = [];
const queue: Array<{ node: TreeMapNode; depth: number }> = [{ node: root, depth: 0 }];
while (queue.length > 0) {
const { node, depth } = queue.shift()!;
if (depth === 3) {
nodes.push(node);
continue;
}
if (node.children.length === 0) {
nodes.push(node);
} else {
for (const item of node.children) {
queue.push({node: item, depth: depth + 1});
}
}
}

const largeNodes = nodes
.sort((a, b) => b.value - a.value)
.slice(0, 10);
const rest = {
value: root.value - largeNodes.reduce((acc, node) => acc + node.value, 0)
}
return { largeNodes, rest };
}

function fileSizeTable(
data: Array<CompareResult>,
redThreshold: number,
): string {
let output = "";

for (const d of data) {
output += `\n`;
output += `## ${d.metafile} -> ${d.outfile}\n`;

if (d.tree) {
const total = d.tree.value;
const { largeNodes, rest } = findLargeDirectories(d.tree);
output += `| Path | Size | Percentage | \n`;
output += `|------|------|------------|\n`;
const largestNodePercent = Math.min(Number(((largeNodes[0].value / total) * 100).toFixed(0)), 100)
const restPercent = Math.min(Number(((rest.value / total) * 100).toFixed(0)), 100);
const largestPercent = Math.max(largestNodePercent, restPercent);
for (const node of largeNodes) {
// FIXME: percentage is not accurate, sometimes it is larger than 100%
const percent = Math.min(Number(((node.value / total) * 100).toFixed(0)), 100);
output += `| ${node.path} | ${filesize(node.value)} | ${renderBar(percent, largestPercent)} |\n`;
}
if (rest.value > 0) {
output += `| (other) | ${filesize(rest.value)} | ${renderBar(restPercent, largestPercent)} |\n`;
}
} else {
output += `Deleted\n`;
}
}
return output
}

function renderBar(percent: number, largestPercent: number): string {
const barLength = 2000 / largestPercent;
const bar = "█".repeat(Math.round((percent / 100) * barLength));
// const space = " ".repeat(barLength - bar.length);
return `\${{\\color{BrickRed}{\\textsf{ ${bar} }}}}\$ ${percent}%`;
}

function renderSize(d: CompareResult): string {
return filesize(d.bytes);
}
Expand Down
9 changes: 9 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface CompareResult {
bytes: number;
diff: number;
remark: "added" | "deleted" | "increased" | "decreased";
tree: TreeMapNode | undefined;
}

export interface Options {
Expand All @@ -21,3 +22,11 @@ export interface Options {
percentExtraAttention: number;
showDetails: boolean;
}

export interface TreeMapNode {
value: number;
name: string;
color?: Array<string>;
path: string;
children: TreeMapNode[];
}

0 comments on commit 3af72d7

Please sign in to comment.