#4 This post is part of the Velocity countdown series. Stay tuned for the articles to come.
I'm working on tomorrow's kind of big thing, so will take it easy today, with a stroll down memory lane.
I was clearing up my space at home few days ago and came across this oldish notepad. In there (among the usual amount of lists of todos and ideas in the spirit of i-wanna-do-this-tool/site/experiment!) I found these early sketches of what has since become YSlow 2.0. These are all still pretty relevant, so why not take a minute to review them and get acquainted with the YSlow internals.
Back at the time Steve Souders and I had just released YSlow 0.9 and Steve had moved to Google. It was the right time to have a quick bugfix-or-two release of YSlow 1.0 and in parallel get cranking on a complete YSlow 2.0 rewrite.
The motivation behind the total rewrite was (aside from the usual "I didn't make this mess" ego-driven desire to start fresh and do a better job the second time around) was that we were getting a lot of "meh, these are Yahoo's problems/rules, not yours". For example a normal mere mortal blog with no CDN budget should still try to get an A in most other checks. Another, somewhat forward thinking, as opposed to reactive reason was that I was a big fan of letting others contribute rules and checks of their own. The idea was to make YSlow your own tool, not only Yahoo's. For example if you want to set a rule that there should be no more than 5 images on a page, you should be able to codify this into a rule. And share the rule with the rest of team or the world. (Here's an example). Another thing was also to decouple the tool from Firebug. Make it work without Firebug and even without Firefox. Go back to having a bookmarklet version (Steve's original very first version) and versions for other browsers. (Thanks to Marcel Duran this is also becoming a reality now)
So the new architecture (a big name for a bunch of objects) was conceived on these sketches while en route a red-eye flight to Bulgaria. My little kids were asleep taking over my seat as well, so here I was standing up in the aisle on the plane or sitting on the seat's handrail, scribbling these notes.
The main idea was divide and conquer. Split this monolithic piece of code into smaller components.
When you run YSlow, it starts by "peeling off" the page, extracting all possible information. Hence the Peeler
singleton.
Peeler
has methods such as getJavaScript()
and getDocuments()
(as in document
+ any frames). This can work most anywhere (bookmarklet too). Then if YSlow is running inside Firebug and has access to Net Panel (or any other browser or environment that lets you access stuff happening on the network, not only DOM crawling), it can also find things such as XHR requests or image beacons, which are not part of the DOM, using a NetMonitor
listener object of some sorts.
Whatever Peeler
finds, it sticks into a ComponentSet
which is just an array of components along with some convenience methods such as getComponentsByType('css')
.
Moving on, the ComponentSet
contains Component
objects which have all the data, like headers, type, content, URL, the whole thing.
K, now we have a bunch of components waiting and willing to be inspected. To make this inspection as lego-like as possible, there's no big-ass inspector, but there are many little Rule
objects. Each Rule
object has a bunch of properties like name
, URL
with more info, etc, but the main thing is - it needs to implement a lint()
method. The lint()
method takes a reference to the ComponentSet
and then returns a Result
object.
The Result
objects are fairly simple - they have a grade/score, message and optionally a list of offending components (e.g. images without Expires
header). A bunch of result objects make a ResultSet
which has methods to get the final total score.
A bunch of Rule
objects go into a RuleSet
. The idea is to mash those up as you wish. So a Rule
object is for example "Use CDN". (it's also configurable, e.g. how many score points to take away for each offender). Also within a RuleSet
you can define what is the relative weight of each Rule
. E.g. is F on "Expires" rule as bad as F on "CSS expressions". You can create your own RuleSet
s (e.g. "Small blog") including an configuring any of the existing rules you like and also add more custom Rules
. It's one big happy pool of Rules to pick from and configure. In fact YSlow 2.0 shipped with three rulesets - the new one with more rules, the old yslow1 and a "small site or blog"
At the end there is one central lint()
method which takes a RuleSet
, loops over the Rule
s in it, calls each Rule
's lint()
and collects the results into a ResultSet
.
From there it's a question of rendering the ResultSet
, grades, offenders, etc. Additionally there are tools that can run on the ComponentSet
(e.g. JSLint) and stats. In addition to the YSlow UI, you should be able to render these results in any way you like, including exporting a JSON or whathaveyou.
Whew!
I may have missed some details but that's about all there is to the core of YSlow 2.0
Here's also a presentation that talks about these things and offers some diagrams that hopefully clarify even further
Thanks for reading!
That was it for today, only 4 days to go to Velocity. Hope you learned something you can use and you're ready to start coding your own rules and create rulesets to customize what YSlow can do for you.
To stay connected, there's now a Facebook page for YSlow and there's always the YDN (Yahoo! Developer Network) section about YSlow