webpack-bundle-analyzer
webpack-bundle-analyzer copied to clipboard
Feature request: calculate size by closure size
Issue description
It would be great to see the treemap grouped not by directory/file but by imported modules. The size of a block would be the sum of all import sizes.
This would mean of course that the entry points will be the top nodes, and the size would be many times more than the total size because shared dependencies would be counted many times. Perhaps the color could be used to indicate the amount of importers of a module.
It would allow determining which modules could be loaded async or should be optimized for size. A single big block with a low-count color would indicate a heavy dependency that could use optimization.
Debug info
How do you use this module? As CLI utility or as plugin?
CLI
I don't think it's possible. How it should work if module A imports something from module B and vice versa? It's a perfectly valid situation in ES modules.
First import wins, and the circular import is ignored? For the display it doesn't really matter which one wraps which one since they're conceptually one block?
I don't understand how it should work. For example, you have 100 components that import react and 10 other vendor libs. Do you want all of them to have react and all these libs as children in the treemap? Why do you need it? How will it help you?
Ah yes react. How about dividing the size of libs by their number of imports? So React would be amortized over 100 components but that one tooltip library that imports jsdom would show up as huge.
I'm hoping that such a view would quickly show lone imports that add a lot to the bundle size, since they would show up as the biggest blocks relative to their siblings.
How it should work if module A imports something from module B and vice versa? … I don't understand how it should work. For example, you have 100 components that import react and 10 other vendor libs. Do you want all of them to have react and all these libs as children in the treemap
There are topological sort algorithms, like Tarjan, that will convert a cyclic graph to an acyclic one where certain vertices represent more than one vertex from the unsorted graph (that is, each strongly connected component of the unsorted graph becomes one vertex of the sorted graph).
Here's a use case I encountered today:
I used webpack-bundle-analyzer on a project I am working on. It's not clear from the image, but over half of the space is taken up just by the "cbor" library. Bignumber, stream-browserify and the node compatibility libraries all are dependencies of cbor and only cbor. Because I was looking at my dependencies closely, I'm able to notice that all those big boxes are things that didn't exist before I imported cbor. But if I hadn't been paying so much attention I probably wouldn't have notice— and certainly, even knowing cbor must be the real culprit, it's hard for me to get an intuitive sense of "how much" space cbor is really taking up (which is, of course, the point of a graphical space viewer in the first place). In other words, cbor's pattern of "small library, large dependencies" is allowing it to slightly defeat the purpose of webpack-bundle-analyzer— it is allowing it to take up a lot of room without it being easy to notice.
I agree that if you have many packages that depend on many other packages, there's no real way to draw that in a useful way. I can think of two ways (not mutually exclusive) to handle the "multiple packages, one dependency" problem:
- Highlight packages which are specifically included in package.json (instead of being pure dependencies) with a special color. If a section of the dependency tree is exclusively included because of exactly one of the package.json packages, stick it in the same box.
- Have some way to select a specific package and say "highlight all this package's dependencies (or sort them underneath), and tell me how much space it's taking up with its dependencies".
The first approach would cause dependencies which are there "because of" a specific package to jump out, intuitively and without having to really think about it. The second approach would help in a situation where you know that your problem is dependencies, and you're going around in a systematic way trying to check each of your toplevel dependencies trying to see how much of the dependency graph they depend on. If you check two different toplevel packages, and you notice there's a single large dependency that only highlights for those two toplevel packages, that will maybe help you realize you can remove two toplevel packages and get a large space savings.
Great ideas! In fact, I'd like to see indirect dependencies in a different background color, so you can see without highlighting how much is actually used by direct imports.
And when you hover on a dependency, highlighting all its dependencies (all the way to the leaves) would indeed be great
If anyone has the willingness to create a proof of concept about some of these ideas, it would be amazing! Then we'd know how big a task such a feature would be, and decide if it fits in the scope of webpack-bundle-analyzer :relaxed:.
Note that "proof of concept" means that that code likely won't be merged in — the PR with the proof of concept should demonstrate this idea in action but would not have to be mergeable with regards to code quality etc.
How about doing this. So we have the dependency graph, with the top node being the build and the first-level nodes being the build entries. For each node, its size is as before, but its transitiveSize is the sum of all child dependencies that only occur in the node's subtree.
So, if you have 2 entries both using React, their transitiveSize wouldn't include React, but the build node's transitiveSize would.
I wonder what that would look like.