rollup-plugin-visualizer
Advanced tools
Comparing version 5.3.0 to 5.3.1
# Changelog | ||
## 5.3.1 | ||
* Fix issue that network nodes could override hierarhy data | ||
* Tried to implement groups in network chart, still some work to do | ||
* In rollup >= 2.44 use code for byte size estimation instead of renderedLength prop | ||
## 5.3.0 | ||
* Merge hierarchy nodes with single child togather, reducing visual noise by less deep structure | ||
* Merge hierarchy nodes with single child together, reducing visual noise by less deep structure | ||
@@ -7,0 +13,0 @@ ## 5.2.1 |
@@ -53,2 +53,3 @@ #!/usr/bin/env node | ||
const nodes = {}; | ||
const nodeParts = {}; | ||
let links = []; | ||
@@ -67,2 +68,3 @@ for (const { file, data } of fileContents) { | ||
Object.assign(nodes, data.nodes); | ||
Object.assign(nodeParts, data.nodeParts); | ||
links = links.concat(data.links); | ||
@@ -75,2 +77,3 @@ } | ||
nodes, | ||
nodeParts, | ||
env: fileContents[0].data.env, | ||
@@ -77,0 +80,0 @@ options: fileContents[0].data.options, |
import { GetModuleInfo } from "rollup"; | ||
import { ModuleLink, ModuleRenderInfo, ModuleTree, ModuleTreeLeaf } from "../types/types"; | ||
import { ModuleMapper } from "./module-mapper"; | ||
export declare const getLocalId: (projectRoot: string | RegExp, moduleId: string) => string; | ||
export declare const buildTree: (projectRoot: string | RegExp, modules: Array<ModuleRenderInfo>, mapper: ModuleMapper) => ModuleTree; | ||
export declare const buildTree: (bundleId: string, modules: Array<ModuleRenderInfo>, mapper: ModuleMapper) => ModuleTree; | ||
export declare const mergeTrees: (trees: Array<ModuleTree | ModuleTreeLeaf>) => ModuleTree; | ||
export declare const addLinks: (projectRoot: string | RegExp, startModuleId: string, getModuleInfo: GetModuleInfo, links: ModuleLink[], mapper: ModuleMapper) => void; | ||
export declare const addLinks: (bundleId: string, startModuleId: string, getModuleInfo: GetModuleInfo, links: ModuleLink[], mapper: ModuleMapper) => void; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.addLinks = exports.mergeTrees = exports.buildTree = exports.getLocalId = void 0; | ||
exports.addLinks = exports.mergeTrees = exports.buildTree = void 0; | ||
const types_1 = require("../types/types"); | ||
const addToPath = (id, tree, modulePath, node) => { | ||
const addToPath = (moduleId, tree, modulePath, node) => { | ||
if (modulePath.length === 0) { | ||
throw new Error(`Error adding node to path ${id}`); | ||
throw new Error(`Error adding node to path ${moduleId}`); | ||
} | ||
@@ -20,10 +20,6 @@ const [head, ...rest] = modulePath; | ||
} | ||
addToPath(id, newTree, rest, node); | ||
addToPath(moduleId, newTree, rest, node); | ||
return; | ||
} | ||
}; | ||
const getLocalId = (projectRoot, moduleId) => { | ||
return moduleId.replace(projectRoot, ""); | ||
}; | ||
exports.getLocalId = getLocalId; | ||
// TODO try to make it without recursion, but still typesafe | ||
@@ -58,14 +54,12 @@ const mergeSingleChildTrees = (tree) => { | ||
}; | ||
const buildTree = (projectRoot, modules, mapper) => { | ||
const buildTree = (bundleId, modules, mapper) => { | ||
const tree = { | ||
name: "root", | ||
name: bundleId, | ||
children: [], | ||
}; | ||
for (const { id, renderedLength, gzipLength, brotliLength } of modules) { | ||
const localId = exports.getLocalId(projectRoot, id); | ||
const mod = { id: localId, renderedLength, gzipLength, brotliLength }; | ||
const uid = mapper.setValueByModuleId(localId, mod); | ||
const nodeData = { uid }; | ||
const pathParts = localId.split(/\\|\//).filter((p) => p !== ""); | ||
addToPath(localId, tree, pathParts, nodeData); | ||
const bundleModuleUid = mapper.setValue(bundleId, id, { renderedLength, gzipLength, brotliLength }); | ||
const trimmedModuleId = mapper.trimProjectRootId(id); | ||
const pathParts = trimmedModuleId.split(/\\|\//).filter((p) => p !== ""); | ||
addToPath(trimmedModuleId, tree, pathParts, { uid: bundleModuleUid }); | ||
} | ||
@@ -92,3 +86,3 @@ tree.children = tree.children.map((node) => { | ||
exports.mergeTrees = mergeTrees; | ||
const addLinks = (projectRoot, startModuleId, getModuleInfo, links, mapper) => { | ||
const addLinks = (bundleId, startModuleId, getModuleInfo, links, mapper) => { | ||
const processedNodes = {}; | ||
@@ -98,12 +92,12 @@ const moduleIds = [startModuleId]; | ||
const moduleId = moduleIds.shift(); | ||
const localId = exports.getLocalId(projectRoot, moduleId); | ||
const moduleUid = mapper.getUid(localId); | ||
if (processedNodes[moduleUid]) { | ||
if (processedNodes[moduleId]) { | ||
continue; | ||
} | ||
else { | ||
processedNodes[moduleUid] = true; | ||
processedNodes[moduleId] = true; | ||
} | ||
const mod = mapper.getValue(moduleUid, { id: localId, renderedLength: 0 }); | ||
const moduleInfo = getModuleInfo(moduleId); | ||
if (!mapper.hasValue(bundleId, moduleId)) { | ||
mapper.setValue(bundleId, moduleId, { renderedLength: 0 }); | ||
} | ||
if (!moduleInfo) { | ||
@@ -113,10 +107,10 @@ return; | ||
if (moduleInfo.isEntry) { | ||
mod.isEntry = true; | ||
mapper.appendValue(bundleId, moduleId, { isEntry: true }); | ||
} | ||
if (moduleInfo.isExternal) { | ||
mod.isExternal = true; | ||
mapper.appendValue(bundleId, moduleId, { isExternal: true }); | ||
} | ||
const moduleUid = mapper.getModuleUid(moduleId); | ||
for (const importedId of moduleInfo.importedIds) { | ||
const localId = exports.getLocalId(projectRoot, importedId); | ||
const importedUid = mapper.getUid(localId); | ||
const importedUid = mapper.getModuleUid(importedId); | ||
links.push({ source: moduleUid, target: importedUid }); | ||
@@ -126,4 +120,3 @@ moduleIds.push(importedId); | ||
for (const importedId of moduleInfo.dynamicallyImportedIds) { | ||
const localId = exports.getLocalId(projectRoot, importedId); | ||
const importedUid = mapper.getUid(localId); | ||
const importedUid = mapper.getModuleUid(importedId); | ||
links.push({ source: moduleUid, target: importedUid, dynamic: true }); | ||
@@ -130,0 +123,0 @@ moduleIds.push(importedId); |
@@ -46,7 +46,13 @@ "use strict"; | ||
}; | ||
const renderedModuleToInfo = async (id, mod) => ({ | ||
id, | ||
...mod, | ||
...(await getAdditionalFilesInfo(mod.code)), | ||
}); | ||
const renderedModuleToInfo = async (id, mod) => { | ||
const result = { | ||
id, | ||
...mod, | ||
...(await getAdditionalFilesInfo(mod.code)), | ||
}; | ||
if (mod.code != null) { | ||
result.renderedLength = Buffer.byteLength(mod.code, "utf-8"); | ||
} | ||
return result; | ||
}; | ||
return { | ||
@@ -60,3 +66,3 @@ name: "visualizer", | ||
const roots = []; | ||
const mapper = new module_mapper_1.ModuleMapper(); | ||
const mapper = new module_mapper_1.ModuleMapper(projectRoot); | ||
const links = []; | ||
@@ -78,16 +84,16 @@ // collect trees | ||
})); | ||
tree = data_1.buildTree(projectRoot, moduleRenderInfo, mapper); | ||
tree = data_1.buildTree(bundleId, moduleRenderInfo, mapper); | ||
} | ||
else { | ||
const modules = await Promise.all(Object.entries(bundle.modules).map(([id, mod]) => renderedModuleToInfo(id, mod))); | ||
tree = data_1.buildTree(projectRoot, modules, mapper); | ||
tree = data_1.buildTree(bundleId, modules, mapper); | ||
} | ||
tree.name = bundleId; | ||
if (tree.children.length === 0) { | ||
const bundleInfo = await getAdditionalFilesInfo(bundle.code); | ||
const bundleSizes = { ...bundleInfo, renderedLength: bundle.code.length }; | ||
const facadeModuleId = (_c = bundle.facadeModuleId) !== null && _c !== void 0 ? _c : "unknown"; | ||
const moduleId = bundle.isEntry ? `entry-${facadeModuleId}` : facadeModuleId; | ||
const localId = data_1.getLocalId(projectRoot, moduleId); | ||
const bundleUid = mapper.setValueByModuleId(localId, { isEntry: true, ...bundleSizes, id: localId }); | ||
const facadeModuleId = (_c = bundle.facadeModuleId) !== null && _c !== void 0 ? _c : `${bundleId}-unknown`; | ||
const bundleUid = mapper.setValue(bundleId, facadeModuleId, { | ||
isEntry: true, | ||
...bundleSizes, | ||
}); | ||
const leaf = { name: bundleId, uid: bundleUid }; | ||
@@ -101,28 +107,16 @@ roots.push(leaf); | ||
// after trees we process links (this is mostly for uids) | ||
for (const bundle of Object.values(outputBundle)) { | ||
for (const [bundleId, bundle] of Object.entries(outputBundle)) { | ||
if (bundle.type !== "chunk" || bundle.facadeModuleId == null) | ||
continue; //only chunks | ||
data_1.addLinks(projectRoot, bundle.facadeModuleId, this.getModuleInfo.bind(this), links, mapper); | ||
data_1.addLinks(bundleId, bundle.facadeModuleId, this.getModuleInfo.bind(this), links, mapper); | ||
} | ||
const { nodes, nodeIds } = mapper; | ||
for (const [id, uid] of Object.entries(nodeIds)) { | ||
if (nodes[uid]) { | ||
nodes[uid].id = id; | ||
} | ||
else { | ||
this.warn(`Could not find mapping for node ${id} ${uid}`); | ||
} | ||
} | ||
const tree = data_1.mergeTrees(roots); | ||
const pkgStr = await fs_1.promises.readFile(path_1.default.join(__dirname, "..", "..", "package.json"), { encoding: "utf-8" }); | ||
const pkg = JSON.parse(pkgStr); | ||
const data = { | ||
version: version_1.version, | ||
tree, | ||
nodes, | ||
nodes: mapper.getNodes(), | ||
nodeParts: mapper.getNodeParts(), | ||
links, | ||
env: { | ||
rollup: this.meta.rollupVersion, | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access | ||
[pkg.name]: pkg.version, | ||
}, | ||
@@ -129,0 +123,0 @@ options: { |
import { ModuleRenderInfo, ModuleUID } from "../types/types"; | ||
export declare class ModuleMapper { | ||
id: number; | ||
prefix: string; | ||
nodes: Record<ModuleUID, ModuleRenderInfo>; | ||
nodeIds: Record<string, ModuleUID>; | ||
getUid(moduleId: string): string; | ||
setValueByModuleId(moduleId: string, value: ModuleRenderInfo): ModuleUID; | ||
getValue(uid: ModuleUID, defaultValue: ModuleRenderInfo): ModuleRenderInfo; | ||
private projectRoot; | ||
private nodes; | ||
private nodeIds; | ||
constructor(projectRoot: string | RegExp); | ||
trimProjectRootId(moduleId: string): string; | ||
getModuleUid(moduleId: string): ModuleUID; | ||
getBundleModuleUid(bundleId: string, moduleId: string): ModuleUID; | ||
setValue(bundleId: string, moduleId: string, value: Omit<ModuleRenderInfo, "id">): ModuleUID; | ||
appendValue(bundleId: string, moduleId: string, value: Partial<Omit<ModuleRenderInfo, "id">>): ModuleUID; | ||
hasValue(bundleId: string, moduleId: string): boolean; | ||
getNodes(): ModuleMapper["nodes"]; | ||
getNodeParts(): Record<ModuleUID, Record<string, ModuleUID>>; | ||
} |
@@ -5,34 +5,59 @@ "use strict"; | ||
const non_secure_1 = require("nanoid/non-secure"); | ||
const warn_1 = require("./warn"); | ||
const nanoid = non_secure_1.customAlphabet("1234567890abcdef", 4); | ||
const UNIQUE_PREFIX = nanoid(); | ||
let COUNTER = 0; | ||
const uniqueId = () => `${UNIQUE_PREFIX}-${COUNTER++}`; | ||
class ModuleMapper { | ||
constructor() { | ||
this.id = 0; | ||
this.prefix = nanoid(); | ||
constructor(projectRoot) { | ||
this.projectRoot = projectRoot; | ||
this.nodes = {}; | ||
this.nodeIds = {}; | ||
} | ||
getUid(moduleId) { | ||
trimProjectRootId(moduleId) { | ||
return moduleId.replace(this.projectRoot, ""); | ||
} | ||
getModuleUid(moduleId) { | ||
if (!(moduleId in this.nodeIds)) { | ||
const id = this.id; | ||
this.nodeIds[moduleId] = `${this.prefix}-${id}`; | ||
this.id += 1; | ||
this.nodeIds[moduleId] = { bundles: {}, uid: uniqueId() }; | ||
} | ||
return this.nodeIds[moduleId]; | ||
return this.nodeIds[moduleId].uid; | ||
} | ||
setValueByModuleId(moduleId, value) { | ||
const uid = this.getUid(moduleId); | ||
getBundleModuleUid(bundleId, moduleId) { | ||
if (!(moduleId in this.nodeIds)) { | ||
this.nodeIds[moduleId] = { bundles: {}, uid: uniqueId() }; | ||
} | ||
if (!(bundleId in this.nodeIds[moduleId].bundles)) { | ||
this.nodeIds[moduleId].bundles[bundleId] = uniqueId(); | ||
} | ||
return this.nodeIds[moduleId].bundles[bundleId]; | ||
} | ||
setValue(bundleId, moduleId, value) { | ||
const uid = this.getBundleModuleUid(bundleId, moduleId); | ||
if (uid in this.nodes) { | ||
warn_1.warn("Override (probably this is a bug)", moduleId, uid, value, this.nodes[uid]); | ||
throw new Error(`Override module: bundle id ${bundleId}, module id ${moduleId}, value ${JSON.stringify(value)}, existing value: ${JSON.stringify(this.nodes[uid])}`); | ||
} | ||
this.nodes[uid] = value; | ||
const id = this.trimProjectRootId(moduleId); | ||
this.nodes[uid] = { ...value, id }; | ||
return uid; | ||
} | ||
getValue(uid, defaultValue) { | ||
appendValue(bundleId, moduleId, value) { | ||
const uid = this.getBundleModuleUid(bundleId, moduleId); | ||
if (!(uid in this.nodes)) { | ||
this.nodes[uid] = defaultValue; | ||
throw new Error(`Missing module: bundle id ${bundleId}, module id ${moduleId}, value ${JSON.stringify(value)}`); | ||
} | ||
return this.nodes[uid]; | ||
const id = this.trimProjectRootId(moduleId); | ||
this.nodes[uid] = { ...this.nodes[uid], ...value, id }; | ||
return uid; | ||
} | ||
hasValue(bundleId, moduleId) { | ||
var _a, _b, _c; | ||
return !!((_c = (_b = (_a = this.nodeIds) === null || _a === void 0 ? void 0 : _a[moduleId]) === null || _b === void 0 ? void 0 : _b.bundles) === null || _c === void 0 ? void 0 : _c[bundleId]); | ||
} | ||
getNodes() { | ||
return this.nodes; | ||
} | ||
getNodeParts() { | ||
return Object.fromEntries(Object.values(this.nodeIds).map((val) => [val.uid, val.bundles])); | ||
} | ||
} | ||
exports.ModuleMapper = ModuleMapper; |
@@ -1,1 +0,1 @@ | ||
export declare const version = 1; | ||
export declare const version = 2; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.version = void 0; | ||
exports.version = 1; | ||
exports.version = 2; |
@@ -31,2 +31,3 @@ export declare type SizeKey = "renderedLength" | "gzipLength" | "brotliLength"; | ||
nodes: Record<ModuleUID, ModuleRenderInfo>; | ||
nodeParts: Record<ModuleUID, Record<string, ModuleUID>>; | ||
links: ModuleLink[]; | ||
@@ -33,0 +34,0 @@ env: { |
{ | ||
"name": "rollup-plugin-visualizer", | ||
"version": "5.3.0", | ||
"version": "5.3.1", | ||
"main": "./dist/plugin/index.js", | ||
@@ -55,4 +55,4 @@ "author": "Denis Bardadym <bardadymchik@gmail.com>", | ||
"@types/yargs": "^16.0.1", | ||
"@typescript-eslint/eslint-plugin": "^4.20.0", | ||
"@typescript-eslint/parser": "^4.20.0", | ||
"@typescript-eslint/eslint-plugin": "^4.21.0", | ||
"@typescript-eslint/parser": "^4.21.0", | ||
"bytes": "^3.1.0", | ||
@@ -65,7 +65,7 @@ "d3-array": "^2.12.1", | ||
"del-cli": "^3.0.1", | ||
"eslint": "^7.23.0", | ||
"eslint": "^7.24.0", | ||
"eslint-config-prettier": "^8.1.0", | ||
"eslint-plugin-import": "^2.22.1", | ||
"eslint-plugin-prettier": "^3.3.1", | ||
"eslint-plugin-react": "^7.23.1", | ||
"eslint-plugin-react": "^7.23.2", | ||
"eslint-plugin-react-hooks": "^4.2.0", | ||
@@ -77,7 +77,7 @@ "npm-run-all": "^4.1.5", | ||
"prettier": "^2.2.1", | ||
"rollup": "^2.44.0", | ||
"rollup": "^2.45.1", | ||
"rollup-plugin-postcss": "^4.0.0", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"sass": "^1.32.8", | ||
"typescript": "^4.2.3", | ||
"typescript": "^4.2.4", | ||
"webcola": "^3.4.0" | ||
@@ -84,0 +84,0 @@ }, |
Sorry, the diff of this file is too big to display
1990898
35
13244