The cost of small modules
nolanlawson.com
nolanlawson.com
Interestingly the performance difference between mobile and desktop on a fast connection was negligible.
Browserify and webpack are really developer friendly, so it's an easy business decision to sacrifice 15ms in overall load time and instead pre-hydrate the first page or use another trick to provide responsiveness while modules load.
I think front end dev process can still use plenty of improvement, but my primary takeaway here is to be conscious of the tools being used and the dependencies they import. It doesn't need to be a complex issue.
Most npm modules are small, so I'd expect in the average case that the majority of modules are actually your own app code.
Any standard CRUD app or BI dashboard should be nowhere near 1000, imho.
E.g. consider the m.reddit.com example - 1050 modules, yet an order of magnitude slower than the "1000 modules" example. I might need to follow up with more benchmarks to reduce the confusion. ^_^;;
Just to be sure, you're definitely counting modules using browserify-count-modules, not the number of directories in node_modules, right?
Not saying those optimizations will be easy. I'm marginally familiar with both the Browserify and Webpack codebases, and I certainly wouldn't want to be the one to implement any of this. But, assuming all the benchmarks in this post prove to be reproducible (and I'm expecting them to be), I hope that those more familiar with the tooling will be able to build a world where we get to have both the user experience and developer experience we want.
For CommonJS modules this is only true to a very limited extent as the export binding process can run arbitrary code which can't be analysed (it's Turing complete).
ES6 modules on the other hand are static and can be extensively analysed without difficulty. This makes, for example tree-shaking pretty easy. Rollup is an ES6 module builder which is doing this already. The future's bright.
Overall though there are still lots of edge cases that aren't well-covered without plugins (such as globals like process.nextTick etc.). Some details here: https://github.com/rollup/rollup/issues/552
By contrast, the Google Closure compiler's module system (also for JavaScript) does not suffer from this problem, but in tradeoff, disallows many types of runtime metaprogramming, such as merging modules with Object.assign or similar.
Which makes me wonder how one decides where and when to get off the treadmill. Sadly I think it's a factor of age as much as technical merit. I hit the point where I felt that we'd reached perfection with Postgres to do relational plus the ability to go schemaless when it made sense, a nice MVC framework in a sane language such as Django or Rails, a smattering of client side magic where required using good old jQuery and finally something like PJAX or Turbolinks to give you that satisfying 'no page reload' feeling.
Get off my lawn...
Spaghetti code -> MVC -> DI -> advanced framework
Personally, I embrace the suck and get off the roundabout at 'spaghetti code'. Define things as straight forward as I can as a sequence of instructions and abstract as little and as usefully as possible. Things that get repeated go into a function. Whole systems that get used more than once go into their own module. If I find myself copying and pasting between projects, it becomes its own library. If a library I'm using doesn't exactly fit my use case, I put it away and write a new one from scratch.That last one was especially hard for me. It's so tempting to spend hours or even days on google searching for just the right library somebody else wrote that will fit your use case. Don't do it. Write it yourself. It'll be quicker and you'll learn more.
That’s a common argument when you have a build-or-import decision, but that doesn’t necessarily make it correct.
If you’re talking about importing a well-established library that has substantial functionality and a large user base with a lot of collective experience then yes, if the functionality is a good fit for your project then it could be a big time-saver. Likewise if you’re talking about importing libraries from a carefully curated repository with good review, testing and maintenance practices.
However, in the modern JS world, many of the libraries that get pulled from GitHub/NPM and incorporated into projects are neither large and well-established in their own right nor part of a well-curated repository. In fact, many of them are written and (maybe) maintained primarily by a single developer, and in turn depend on other libraries also written and (maybe) maintained primarily by single developers.
In that case, it seems optimistic to assume that everything you’re bringing in will necessarily have higher quality than anything you’d write yourself. Certainly it might, but on the other hand, you could just be trading debugging someone else’s code for your own, and with someone else’s code you’re working with one hand tied behind your back. It might still be a good trade, depending on how much functionality the imported code offers and how much time it will save you, and depending on how much overhead you’ll incur finding and importing that code and adapting and maintaining your own code to match. Or it might not.