Tree-shaking optimizations aren't a magic bullet. I argued for about a year and a half to get Google Search to use JQuery, but it turned out to be a complete non-starter because the way the JQuery library is constructed is not amenable to compilation or static analysis. JQuery often dynamically assigns methods to the JQuery object by building a base function and then customizing it with some data-driven properties, then splitting a string to get the method names. For example, .width() and .height() are the same method, but one returns .offsetWidth while the other returns .offsetHeight; this distinction is encoded into a closure when the JQuery object is created.
It's a really cool programming technique that unfortunately kills the possibility of statically analyzing the library.
The other interesting thing is that this technique actually makes the JQuery codebase significantly smaller than defining separate methods for each function that appears in the API. So it optimizes for byte-size of apps that use all JQuery functionality, at the cost of apps that use only a little bit of JQuery functionality. And I think this trade-off is why people continue to like no-framework approaches: it is possible for the application author to know what functionality from a library they will need and write code accordingly, but it is not possible for a library author to know what functionality a particular application will need and optimize for that. When you make your library more amenable to tree-shaking compilers, you increase the byte-size of it in the absence of those compilers (through reduced code-sharing or dynamism in your own codebase), which makes you look worse in head-to-head comparisons. When you build your library to be small and clever but assume it'll all be used as one unit, you impose a tax on people who just want some of the functionality and not all of it. And when you use no library at all, then you often end up reinventing parts of the functionality of a JS library poorly, in a less optimized form, and as your app grows it becomes both slower and less productive than if you'd just used one of the leading frameworks.
It's a really cool programming technique that unfortunately kills the possibility of statically analyzing the library.
The other interesting thing is that this technique actually makes the JQuery codebase significantly smaller than defining separate methods for each function that appears in the API. So it optimizes for byte-size of apps that use all JQuery functionality, at the cost of apps that use only a little bit of JQuery functionality. And I think this trade-off is why people continue to like no-framework approaches: it is possible for the application author to know what functionality from a library they will need and write code accordingly, but it is not possible for a library author to know what functionality a particular application will need and optimize for that. When you make your library more amenable to tree-shaking compilers, you increase the byte-size of it in the absence of those compilers (through reduced code-sharing or dynamism in your own codebase), which makes you look worse in head-to-head comparisons. When you build your library to be small and clever but assume it'll all be used as one unit, you impose a tax on people who just want some of the functionality and not all of it. And when you use no library at all, then you often end up reinventing parts of the functionality of a JS library poorly, in a less optimized form, and as your app grows it becomes both slower and less productive than if you'd just used one of the leading frameworks.