Few of my own tips, most of which you covered.

- Load everything asyncronously. RequireJS etc... (if you don't use AMD loading, then seriously start reading up about it).

- The overhead of including Facebook Like button and Twitter, is like 150kb. It's ridiculous. We load them after the page has loaded. In their place, we load placeholder Facebook buttons. That mimic the like button. (Similar to what TechCrunch does).

- Bundle everything. We use shrinksafe for this. (Sometimes Closure... it really depends on which one is playing nicer at the time of doing the build). This allows us to create enormous JS files of all of our application. What we do is create one "kernel.js" file. This is always loaded first. And once the page has loaded we fire off using AMD loading asyncronously to the actual application.js. I've played around testing on this as to whether it's best to only include the javascript that is relevant to the current page, but in the end we settled on loading absolutely everything. This makes the JS about 280kb gzipped. The user doesn't really ever notice the hit, since we load the "kernel.js" first, which contains the bare bones minimum.

- Use a CSS preprocessor. We use LessJS. We managed to reduce our CSS overhead by an overhead of 20% in file size while using the same sheet. When you use a preprocessor (although we supply the compiled versions) you are making the file gzip heaven. The ungzipped version is larger, but the compression is great. Additionally, maintainability improved by an order of magnitutde that I can't even count. Incidentally, we also provide the entire CSS for the entire site in a single .css file. Again, tests were done with splitting the CSS, but it just makes more sense to provide everything and improve the page loading on second requests (We don't have a high bounce rate so it might make more sense on our types of sites).

- SpriteSheets. You can't really over emphasise the importance of these. HTTP requests are expensive when you are firing off multiple requests to the same domain. Depending on the browser you could hit blocking/waiting pretty quickly. It really pays off to merge your images into a sheet. Don't use a premade sprite sheet with 100 icons on it, where you only use 8. Make your own.

- Cookieless Domains. Serve all of your static assets from cookieles domains. This one isn't neccessarily a major win, since the gain you get is reduced based as you optimize more. However, before I started optimizer, a single request would fire 80 HTTP requests just to static assets. The average user on the site would have about 500bytes worth of cookie data. I set myself the target of getting the request down to 400kb for everything. So like 2% (I can't do maths) of that was being taken up just on the users /GET Request. It's not neccessary! Move everything to a CDN. We use CloudFront.

- Browser Blocking. We don't have this issue any more, but we used to load a lot of assets. As a result we would hit "blocking" really quickly. (This is where the browser stops loading assets from the same domain). This number changes depending on the browser you are using, but the normal number is 6. (Some even as low as 2!). The iPhone is the only phone which is also around 6. Most other phone devices are still at 2. This means that requests to the same domain (where you have lots) really sucks. So as a possibility you might want to consider using an asset serving library. The idea of this is that you provide multiple links to the same assets in your application, and round robin through the sources to make sure that you are rotating between hosts where the asset can be found. If you do implement somethign like this you need to make sure that the user is served the same host otherwise they wouldn't benefit from caching. The "hack" way that we implemented it was to use their HEADERS as a "seed key" which created a cache, which we would then perform some type of modulus caclulation on to serve the correct server. It isn't perfect, but it works.

- Headers. Use correct headers.. expires... cache... if you are serving up cacheable content. Say so! Some study I read recently showed that over a period of a month, rechecking the same 1000 sites daily and checking each asset. Of those that never changed, over 50% didn't make correct use of expiry headers! If you do this you are telling your users that you don't care about performance!

- Speed isn't always about waiting for that DOMContentLoaded to fire. It's also about perceived performance and loading. This means that you should always give your images a height and width attribute too.

- Use a reverse proxy cache! The stack that we use is nginx(port 80) -> varnish -> nginx. This is so that we can benefit from server side includes which are cached in varnished, and rebuilt by nginx.

- Eager Loading. I've only just started experimenting with this as a way of improving my knowledge on machine learning. As I mentioned above we have a really load bounce rate, so it might make more sense for us than it does for your site. Basically, I've started using Markov Models to build a probalistic model of the liklihood of a user navigating to another internal page and figuring out based on all other users which page that might be. I then drip feed load the assets from the other page.