Developers, Please Stop Fucking With Your JavaScript Files
There have been waaaaaaayyyyyy too many posts lately on "supercharging" your JavaScript (and CSS) and creating "dynamic" JavaScript. Bad. Bad. Bad Developers. For an example of what I'm talking about take a look at this article (as posted on DZone), which got 18 up diggs and is described as "Best practices for Javascript delivery..." Ugh. I could write a "Best Practices For Taking A Dump" and it would come out smelling better then that post. Let's break it down...
Client VS Server Side
I don't mean to focus on the supercharging article (which, unfortunately, also has a CSS version), there are a bunch of others too (although most don't stretch on for 7(!) pages). Like this one, which caused me to lock myself in my office for 3 hours. What happened during that time is buried so deep in my mind I'd need years of hypnotherapy to even scratch the surface.
The supercharging post opens with:
I am an unapologetic stickler for speed when it comes to Web applications.
Then he proceeds to show a method that effectively speeds up the client side of the app by slowing down the server side. The net result: probably about the same as before.
Yslow Is To Blame
Yahoo's Yslow plugin is to blame for a lot of this. It's provides nice, pretty grades and dares you to do better. It even tells you where the problems are and how to fix them. What's the easiest way to do it? Route all your JS files through your server side language! No, no, no. Wrong. You see Yslow is only measuring front-end performance. It doesn't give a shit how long something takes to generate on the server. To test that you should be using tools like ab or Siege.
Why This Matters
Your webserver, even Apache, can serve static .js and .css files a fuck ton faster then dynamic pages. This is the point where you'll counter with: "Fine. It's true I'm wasting some server resources, but everything will be cached on the client, so FU, it doesn't really matter!" Go ahead and read this article from YUI blog. Or I'll just give you the conclusion:
Keep in mind the empty cache user experience. It might be more prevalent than you think!
How Do I Know If I'm Doing It Wrong?
1) You have something in your webserver's configuration that routes .js or .css files to your server side language, like this:
RewriteRule \.js$ lib/phpsprocket.php [QSA]
2) You direct your javascript/css includes right to your programming language in your HTML, like this:
<script src="/javascript.php"></script>
Making It Fast The Right Way
Make as Few HTTP Requests as Possible
It's a good thing to merge your static files into as few as possible (notice I didn't say one - more on the later). There are a bunch of different ways to do this. Most commonly it should be part of your build routine. This way the generated file can still be a static one and will be served up fast. Heck, you could even go crazy and deploy it to a CDN.
Another way would be to have it process automatically the first time any user hits a page, as long as the results are stored as a static file for the next user. If you use a framework there might already by a library that does this for you.
GZip Everything
Something that can and should be done by your webserver.
Minify Everything
This should be part of the whatever process you have that combines your files.
Caching on the Server
Any static files that are cached on the server should be cached as plain .js or .css in a directory that is web accessible. If you need to use any type of programming to read the cached file you are doing it wrong.
Caching on the Client
As part of the build routine, when you generate the minified and combined files, include either a timestamp or a version number (preferably) as part of the file name. If you use a version number, then your HTML page (which is generated dynamically) can have access to that same number and can include it as part of the file name when it generates the tags to include your static files.
Dynamic JavaScript
I know what your thinking: "But, I need to pipe my javascript through the server side language so that I can generate custom code based on the user."
No. No you don't. Do you think any site with more then three visitors a month does this? Digg? Amazon? Twitter? You will pry my web developer badge from my cold, dead, bullet ridden body before you convince me otherwise.
The needs of the many outweigh the needs of the few...
...or one. Take a look at this simple scenario: You have a JavaScript heavy website that uses jQuery and parts of the jQuery UI on every page. Say you minify and combine those and they become one 100k file. You also have page specific JavaScript files that are around 30k each. If you were hell bent on only including one JavaScript file per page you'd end up with something like:
Page 1: file1.js (130k)
Page 2: file2.js (130K)
What if instead you left the files separate:
Page 1: jquery.js (100k) + file1.js (30k)
Page 2: file2.js (30k)
What about jquery.js on Page 2? It would already have been loaded and cached by the browser on Page 1. And if you are using the trick of including the version as part of the file name and setting a far future expires date, the browser won't even make a request for the file.
All I'm saying here is be smart. It makes more sense to logically group your files and then include the groups you need for a particular page, rather then having one giant file that gets downloaded on every page because 25% of it is different then the other pages.
Wrapping It Up
Please developers, just leave your JavaScript and CSS files as static files. It's cool if you want to mess with them a bit, but make sure the final output is still a plain static file.
CakePHP Digest #14
Prelude
I'm back. The project that has been my taking up my daily supply of quality thoughts is done. This post will be twice as good as the last one. Unfortunately, the last one was like a 1.5 out of ten, so you're only getting a 3 here.
Let's spice this one and give it a theme: "Acceptable phrases with NSFW origins." For example: With the release of my CakePHP book I really opened up the kimono on all my accumulated knowledge. Got it? See if you can find them all. BTW, this is the last time I'll plug the book in this post. Really.
News
Yet another internationalized CakePHP site goes up: cakephp.com.br. This one is for the Brazilian users.
Saudações brasileiras Bakers! Sabia que eu escrevi um livro? Eu sei que prometi não mencioná-la novamente, mas esses idiotas falam Inglês não vai saber a diferença.
Tickets and Commits
The current list of open bugs is pretty short and over half of them have been assigned, which usually means they'll get marked invalid and disappeared soon or fixed...sometimes they get fixed. They all seem pretty obscure - 2 of them deal with email and 3 with MSSQL. Nothing like the XSS issue from last time that had Cake bent over a table.
In The Wild
Starcraft 2 Armory
Miles Johnson announced the relaunch of Starcraft 2 Armory. Starcraft 2 is the forthcoming prequel to the somewhat popular N64 game: StarCraft 64 released in 2000. Almost ten years between games can really build up a lot of expectations. Let's hope they didn't shoot their load on the first one and still have something left. Oddly, the series skips from chapter 64 to chapter 2. Not sure why they didn't just go all the way back and do chapter 1. Weird.
tutrme
The domain is tutrme.com, which is short for "tutor me." It's a site for matching tutees and tutors.
In The Blogs
Nothing really stood out to me. clown-hat-frowny-face <:(
In The Groups
What do you hate about CakePHP?
The most interesting topic was "what do you hate about CakePHP?" started by Nate. Of course, anyone whose reading this has already seen it, so I really should dig around and find some less traveled threads.
Johnny Two Times
Like this one, which cracked me up because of the topic and the second and third posts.
Yes, there's a function for that
Or this thread where I learned about Controller::disableCache. Seriously, Cake has a function for everything. Unless you're balls deep in the API there's no way you can know them all.
Code
DebugKit
Mark Story has released the latest version of the DebugKit. Also it's been over one year since Mark made his first CakePHP commit. Since then he's averaged almost 3 commits a day between the various CakePHP projects. It's almost like he gets off on it, which is awesome for us since he produces some great output. Umm...Uh...let's just move on...
Check back in a few days
I had marked this HABTM counter cache behavior for later reading, but unfortunately there was some change, so it's waiting to be approved again - what a pain in the ass.
Vimeo Datasource
I'm a sucker for datasources - here's one for the Vimeo API.
I'm Out!
Don't forget to subscribe to my feed or follow me on twitter.
As always if you think I missed something leave a comment. Or if you do something interesting and want it included in the next digest, send me an email.
Free CakePHP E-Book - Super Awesome Advanced CakePHP Tips
For those of you who just want the book
This is the download link ---> Super Awesome Advanced CakePHP Tips
Updated to V1.1, fixing a few small things.
For those that want a 1500 word blog post
I've been sitting on this thing for the last two weeks and figure it's about time I just let it out. Ahhhh....so much better. Now, about the book. What better way to introduce it then a fake interview? Off we go!
What exactly is this thing and why should I waste my precious bowl time reading it?
At the moment there is no lack of CakePHP books geared towards beginners. But, there really isn't much for anyone who has mastered the basics and wants to do more. This e-book is for you guys and gal (I'm sure there's at least one out there somewhere).
I suck at CakePHP. What's the best way to learn the basics so I can get up to speed and read your book?
Check out Chapter 2: "How to Learn CakePHP". It details two paths for learning the framework - a free one and a pay one. I'm interested in feedback here, since it's hard for me to remember what it's like learn the framework. I just remember being really frustrated at times and blacking out, only to awaken covered in blood and standing over a dead hobo. Not good times.
How much is this thing going to cost me?
Nothing. It's free.
No really.
Seriously. Free. You know how when you're watching an independent movie or playing an indy video game you cut it some extra slack and overlook a few minor flaws? Do that there too. Thanks.
When did you start working on this?
The original idea was hatched in December 2007. At the time I was planning on writing a series of Advanved CakePHP posts. After I had 12-15 or so I was going to roll them into an e-book. Naturally I fizzled out after 2 posts.
Fast Forward to Oct 08 and I'm sent a copy of CakePHP Application Development to review. I realized as I was reading it (and confirmed by one of the comments on that post) that there was a lack of upper level Cake books/documentation. I also realized that in the year since I'd given up on the advanced series I had a bunch of decent posts that, once I cleaned out all the cursing and porn references, would make a decent e-book.
It's kind of dick of you to spend all this time creating an e-book, but then hardly contribute to the Cookbook. Do you feel any remorse or are you so hell bent on personal glory that it has crushed all rational thought in your oddly shaped head?
I struggled with this - I really did. In my defense I would say most of the content of the book isn't really appropriate for the Cookbook. That still doesn't excuse why I haven't contributed more. Although the Cookbook is great there are gaps (though they're becoming harder to find). I don't know...maybe it's because I spend more time in the API or maybe I'm still bitter that tempdocs, which served me so well, was whacked without even given a chance to make a tearful deathbed speech.
What IDE did you use to create the book?
I actually went through two before settling on Open Office. I started with Google Docs, because I figured it would be cool to be able to write whenever/wherever I got inspired. By about 30 pages Google Docs started to really choke, plus the PDF generation was mediocre at best.
I moved the whole thing to Word and spent like a week re-doing all the styles. But Word just gave me other problems. Whole pages would disappear until I scrolled around a bit and then they'd randomly re-appear. Plus I tried a bunch of different PDF printers and they all sucked.
Finally, I moved to Open Office and wasted another week fixing the styles again. This time everything worked pretty well and the built in PDF generator actually did a decent job.
Is this what you've been busy with and why you haven't blogged as much and when you do blog the posts blow?
Yea, pretty much. I'm also obsessed with converting all my open source Cake code into plugins. I'm all over plugins like a meathead frat dude trying to impress his buddies as a way to cope with his feelings of inadequacy when he sees a slightly unattractive chick with self esteem issues whose had too much to drink.
What's with the Mark Story sections?
This one is going to take a bit. Way back in the pre-RC days of 1.2 if you used the console to bake model tests the resulting test cases would have to extend the model and set the database to use the test_suite. This approached sucked and there was a better way. If you used the ClassRegistry to get an instance of the model it would set the database automatically. When I was putting the book together I knew I wanted to include a section of fixing the model unit test.
I also had an inkling I wanted to do a proper view unit test section. It would have been a gaping goatse-esq hole if I had a section of M(odels) and V(iews) and not C(ontrollers). Before I could get my shit together and write it Mark's article came out. Fuck. It was good and I really hated the thought of re-writing the same thing.
So, I got the brilliant idea to get others to contribute sections. I emailed Mark and a bunch of other Cake devs to see if they were interested. Predictably, everyone was too busy raking in that phat CakePHP bank to contribute. Except for Mark who not only agreed to let me use that piece, but also his forthcoming (at the time), landmark, life altering, spiritually awakening piece on mock objects. *genuflect*
Why not charge $$$ for this thing?
Another long answer. Continuing the above section...sometime later I realized that Cake had actually fixed the core to generate better tests and my Model section was pretty much shot. But at this point I already had Mark on board, so to sell this thing I would either have to a)cut his part and lose like 1/3 of the book or b) negotiate some sort of split.
Realistically I knew this thing wasn't going to make a ton of loot. Certainly not enough add another wing to the PseudoCoder estate. Take a look at this post from John Resig. It's a little unclear how much he's made on that book, since he never reveals how much he received up front $7500. What is clear is that he isn't killing it. I mean, if the fricking creator of jQuery can't make a fuck ton of cash on a JavaScript book...really, what chance do the rest of us have? It's John Fucking Resign, writing about JavaFuckingScript! Shouldn't this be the #1 best seller of all time, crushing The Bible like an empty Miller High Life against it's forehead?
This book is so full of typos, grammar mistakes and bad code. Where should I send my bitchy emails?
Take your pick - all of these people took the time to proof read it and gave me immensely helpful feedback.
Paddy Foran (blog) - Paddy sent me about 100 pages of speling, grammer and typeos, which is amazing since the book is only 64 pages. I dare you to find a mistake that he missed and then harass him endlessly about it. I DARE YOU.
Shawn Poulson (blog, friendfeed, twitter) - Shawn helped fix my atrocious PERL regular expression skills as well as suggesting using the Heredoc syntax when including JavaScript in views.
Jonathan Langevin (site, cakephp forum) - Jonathan sent me a bunch of spelling errors, which I probably could have figured out on my own if I those damn squiggly red lines under the words weren't distracting me so much.
Heath and Sohaib - both challenged me on the "Getting the Logged In User from Anywhere" section.
Felix Geisendörfer (site) - Felix is a superstar and provided some great pointers.
I'm sure I'm missing someone. If you're that someone, know that as angry as you are for not being mentioned, I feel 1/8 as bad for missing you.
What as the most significant thing you learned while writing this?
I feel like a moron for not knowing this. Apparently the correct slang is friggin'. But for years I've been using "friggen" - which has a completely different meaning. It's no wonder that my friends would act strange when I'd ask "anyone want to hang at my place and play video games and other friggen stuff?" Then they'd show up five minutes later and always seem disappointed at 3AM when I said I was going to bed...like they were expecting more...
This brings up an important issue. Has there ever been cursing in a programming book before?
Not that I've ever seen, but I'd be interested in hearing about it. My goal is to have the first NSFW programming book. Set your dreams high, kids.
I have question/comment about the book. How should I contact you?
Send me an email. Hit me up on twitter. Leave a comment on this post.
What's next?
Not much for the book. I'll probably fix it up and add new sections from time to time. I've already received a few good suggestions. I have a couple good blog posts ready, including "How To Program While Shitfaced Drunk" and "Stop Fucking With Your JavaScript". They just need a few more drunken tangents and they'll be ready to go. Keep an eye out next week.
CakePHP Digest #13
Prelude
This digest kind of sucks. As we'd say in high school: My B G (which translates to "My Bad, Gangsta," for those who aren't from dorky middle class America). I have something kind of cool that I hope to get out this week that should make up for it.
News
CakePHP 1.2.3.8166
There is a new bug fix release for the 1.2 branch. The biggest issue this fixes is described below in the Tickets and Commits section.
CakeFest Talks
It looks like all the slots have been assigned for talks at CakeFest.
First 1.3 Site In The Wild?
TheChaw is now running on CakePHP 1.3. I would guess this is the first real CakePHP 1.3 site out there. Although I made a joke a couple digests ago about how everyone should move to 1.3 immediately. Some people didn't realize it was a joke, so for all I know there could be a bunch of sites updated to 1.3 already.
CakePHP Meetup in Dallas
@britg setup a CakePHP meetup for the Dallas area bakers.
Tickets and Commits
I can't even get this post out and it's already fixed.
A low danger XSS vulnerability is currently open closed. The trick allows you to inject HTML into some CakePHP apps. For example here's one of my sites. This doesn't work on all sites. For example the CakePHP sites seem to be immune. I'm calling this one "low danger" because I was only able to get HTML into the page, not JavaScript. Plus, it only works when you get people to visit your hacked link.
See the comment below from Ramon on how to exploit this for JavaScript
In The Wild
www.vendoo.co.za
@johannduplessis announced his latest site: www.vendoo.co.za. It's a "classifieds site and aggregator."
In The Blogs
Pagination With Custom Find Types
Mariano Iglesias has a nice post on doing pagination with custom find types.
Ajax Form Validation
JamNite posted a rather lengthy tutorial on doing Ajax validation using jQuery.
Which teknoid Posts to Highlight?
If I linked to every new teknoid post there wouldn't be room for any other blogs. I'll pick there two: "Give all of your error messages a different layout" and "More pondering about HABTM".
In The Groups
Uhhh....
Code
jQuery Ajax Helper
loadsys.com released a replacement for the default AjaxHelper that uses jQuery. How many of you use the AjaxHelper for generating JavaScript code? I'm interested to know if most people just write their own JS - this is what I do - rather then using the helpers.
Plugin Manager
@rodrigorm pointed out a project he's been working on - a plugin manager.
My Stuff
I updated a few of my projects last week. Since I'm completely obsessed with plugins I'm converting all my code. So far I've done the LazyLoader, Custom Find Types and jQuery Validation. I plan on doing the rest as I get time.
I'm Out!
And on that note don't forget to subscribe to my feed or follow me on twitter.
As always if you think I missed something leave a comment. Or if you do something interesting and want it included in the next digest, send me an email.
GitHub Updates
Multiple Repos
I wasn't very smart about this whole Git fad when I first started my GitHub account and just dumped all my CakePHP code into one repo. Turns out this isn't the way to do it, since you have to clone the whole repo, even if you just want one piece of code. My bad. Everything has now been split into it's own repo to make it easier for you guys to fix my shitty code. You're welcome.
jQuery Validation Updated
My jQuery Validation helper has now been pluginized. Actually, it's now a plugin within a plugin. Both the CakePHP helper and the jQuery code are plugins. It's not a straight drop-in for the old version, so make sure you read the directions. Basically it does all the same stuff as before - converts your Cake validation rules from the model to work in JavaScript, where it can. The cool thing about making the JavaScript into a proper jQuery plugin is that you can now add custom handling without changing the original source.
Callbacks
At the moment there are three callbacks: beforeFilter, setError and afterFilter.
beforeFilter - called before validation is started. No params.
afterFilter - called after validation is done. Passed an array of errors.
setError - called anytime a validation error is found. Passed the field and the error message.
So if you wanted some alternate handling for errors you could do something like this:
$.fn.validate.setError = function(field, message) {
//don't ever do this or I will come for you
alert(message);
}
Custom Rules
The old version would skip right over the custom validation rules, since it didn't know how to handle them. This new version includes the rules and if a function with the same name exists it uses that to validate. It's up to you to write the custom function and you're free to use Ajax here. For example if you had a custom validation rule "myRule" you would define the function like this:
$.fn.validate.myRule= function(val, params) {
//do some validation here and return either true or false.
}
params is the same as they are defined in the model's validation.
Model Lazy Loading
My first attempt at this was moderately successful, but some flaws were pointed out in the comments. A commenter also pointed out some code in the CakePHP bin that was attempting to accomplish the same thing. The oldest instance I could find was this one. The were some things I liked about this version, namely it didn't remove the defined associations. But I also didn't like the was it took over the __constructLinkedModel method. After going around and around with this I've come to the conclusion that it's the only way.
I've updated my version to use the same principles as jose_zap's CakePHP bin version. Here's the differences:
- DRYier
- Runs as a plugin
- catch
resetAssociations- This is called after afindoperation and inadvertently builds all the models, completely defeating the purpose of this code. Basically I'm just removing the functionality, which only matters if you usedbindModel. If you're using this code block there really isn't any reason to be usingbindModel, so I figure there's no harm here.
This update should fix the issues with counterCache and HABTM inputs.
Coming Up
I plan on rolling pretty much all my code into plugins. It's just so much easier to distribute and keeps everything contained. Keep an eye on my repo if you're interested - I won't be bothering with blog posts for every update.
