Brian-
You raise some great points and are moving into some bigger picture stuff about how one actually writes Javascript.
In general (although there are some exceptions), having one large concatenated JS file, properly GZIPed, pushed to an asset bucket (like Amazon), pulled from a CDN (like Cloundfront), is the best way to go. Yes, you can split your manifests into different sub-sections, and load only “what you need” on any given page, but for most apps – even large apps – you just get batter overall performance with one JS file.
Sometimes as a middle-ground I will create different manifests (and load them separately) for different areas of my website – like one for the user-facing and a different one for the admin-facing sections. That can be a good middle of the road approach. Or, if you have a public facing site that has one set of JS and a dashboard for only a subset of users, you could have different manifests for each.
I think that if every page and every controller loaded a different JS, you’d simply be slowing down the user’s experience by making all those files load as the user moved through the website.
Some of it has to do with scale, are we talking about a 20 KB javascript or 300+ KB of javascript? At the 25-50 KB range, I wouldn’t even worry about it. At a bloated 300+ KB of Javascript scale, splitting up stuff might make more sense.
Let me put it this way: You’re going to get so much more of a speed increase from properly gzipping and moving your assets to a CDN, that your strategy of splitting up your website into separate JS is like saying we should upgrade the gears on our bicycle when the right thing to do is replace the bicycle with a car.
For sure, but it would be a relatively small file, wouldn’t it? There’s a lot of (reasonable) concern about making multiple HTTP requests, but that’s usually when you’re evaluating the performance of a single page. As you go between pages you’d be just loading what you need.
Well no, actually, the way it is supposed to work is that only the first page loads the needed JS, and all other subsequent page loads will use the same JS file from cache, so you really are speeding up the user’s load time on all subsequent page visits after the first one.
Honestly it might require some benchmarking of various apps to compare javascript rendering performance vs HTTP request speed. Also that varies a lot from browser to browser and network to network. Maybe somebody who’s been through this before can speak up?
Also memory usage and performance due to lots of event handlers should be considered as your application’s set of javascript files grows.
Here’s where you raise a much bigger can of worms. In my opinion, lots of JS that I see is garbage. In particular, I think the Rails community has yet to really grapple with the limitations and inefficiencies of “unobtrusive style” javascript, specifically excessive use of DOM-targetted jQuery. (By “DOM-targetting jQuery,” I mean you have lots of jQuery that targets generic class names, attaching click handlers or event functions.) I see this in an old-style Rails-Javascript apps that really haven’t evolved much since 2007.
The pain you are describing is real, and you are not alone. At small scale, that style of writing Javascript works OK. For medium or large size apps, you quickly find yourself in DOM-targeted nightmare: Your page slows down because of so many attachments being made, events being fired, etc. You use classes you think are safe but some JS somewhere attaches click handlers to them producing unexpected results. You get double-attachment errors (when two attachments are made to the same object, causing the function to fire twice). You use Ajax to rerender part of your page and you drown in having to re-apply attachments.
In my mind, this style of writing Javascript is a disaster (I would even call it an antipattern), and it’s really unfortunate that more of the Rails community hasn’t seen the light and realized that outside of the Rails world most professional JS developers moved on from this kind of writing JS back in 2009-2010 timeframe.
I know there’s a lot of controversy and opinions about Backbone, Ember, Angular, etc. I have my own opinions about the quirks and strengths of these kinds of frameworks. But consider that all of them do one basic thing: They abstract a library of code away from the initialization of Javascript code in a way that means that you know that the only things attached to my Backbone view controller object are the things I define in my Backbone “events” parameter for that viewcontroller. Backbone has deficiencies, but since all JQuery attachment is cleanly scoped I’ve never had to worry about haphazard DOM-targetting creating a nightmare of bugs and issues for me.
Outside of Rails, JS developers are working in Node, or PHP(!), or lots of other back-end options. They are writing thick-client Angular apps or Ember apps that talk strictly via JSON APIs to the back-end. A lot of these languages are new, and are having growing pains, but they are evolving our understanding of how to think about a distributed client-server application and address a lot of the headaches with structural advancement.
In the big picture, I’d like to see Rails developers embrace more modern ways of writing Javascript. Personally, I don’t think this has much to do with the Rails-core itself. Rails is a back-end technology, and it’s great at being a back-end technology. It is not meeting the needs of today’s UX and Javascript-heavy world, and that’s OK. There’s lots of ways to structure your Rails app and use the Asset Pipeline to deliver the JS app cleanly an efficiently.
SO again, it sounds like your problem of “memory usage and performance due to lots of event handlers” is the result of years of crufty DOM-targetted Javascript development. Yes, it’s a problem. But no, it’s not Rails’ problem. It the fault of the developers who let it get that way, and their shortsightedness when it comes to seeing the bigger picture and failure to embrace cleaner ways of thinking about a thick-client app.
I realize this may all be a little controversial, so take it with a grain of salt. This is just my opinion having worked in this space for several years and had this specific conversation about Javascript with a lot of different devs (who themselves had different opinions and viewpoints). I think this is actually the heart of one of the challenges for the community moving into 2015.
-Jason