Ever wonder just how many unused CSS Rules you have laying around?  You can enumerate your stylesheets and CSS Rules in the browser for stylesheets that originate from the same domain, but that doesn’t help you much if you serve your static CSS files from a CDN.  As it turns out, you can disable the security in PhantomJS using --web-security=false.  You can then enumerate all stylesheets regardless of their domain and test to see how many elements match each selector, if any. I added a quick example to my burgeoning toolkit to create a pie chart showing each stylesheet’s rules as matched (bluish) or unmatched (redish).  The chart below was created using phantomjs --web-security=false cssCheck.js --url=http://fasterness.com.

matched and unmatched CSS selectors by stylesheet
matched and unmatched CSS selectors by stylesheet

I’ve written a few utilities lately to measure how fast a page loads over the wire.  While watching Nicholas Zakas’ presentation at Velocity, I started wondering how I would measure the load times for popups, tabs, and other dynamic content loaded via user interaction.  CasperJS has already proven extremely handy for automating some pretty complex functional tests that had previously been done manually, so I pulled that out of the tool box to see if I could add some measurements.

Unfortunately, Nicholas’ demo was so fast and consistent that the numbers didn’t look believable :-) So, like most web developers, I turned to jQuery. And, as always, jQuery had exactly what I needed. The jQuery UI Tabs Example came complete with dynamically loaded, slow, and even broken tabs.  The Gist and output are below.

var colorizer = require('colorizer').create('Colorizer');
var casper = require('casper').create();
var totalTests=3;
casper.start('http://jqueryui.com/resources/demos/tabs/ajax.html', function(){
	casper.viewport(1024, 768);
	this.test.assertHttpStatus(200, "The page has loaded.");
	this.test.assertSelectorExists('#tabs', "We got tabs.");
	this.test.assertVisible('#tabs-1', "Content 1 is visible.");
	this.capture('ui-id-1.png');
});
testTabLoad('#ui-id-2', '#ui-tabs-1', "Tab 1", "tab1.png");
testTabLoad('#ui-id-3', '#ui-tabs-2', "Tab 2", "tab2.png");
testTabLoad('#ui-id-4', '#ui-tabs-3', "Tab 3 (slow)", "tab3.png");
testTabLoad('#ui-id-5', '#ui-tabs-4', "Tab 4 (broken)", "tab4.png");
casper.run(function() {
	this.test.done(totalTests);
	this.test.renderResults(true);
});
function testTabLoad(tab, content, name, capfilename){
	totalTests+=4;
	casper.then(function() {
		if(name)casper.echo(name, "COMMENT");
		var start=Date.now();
		this.test.assertSelectorExists(tab, "Tab selector exists.");
		this.test.assertSelectorExists(content, "Content selector exists.");
		this.test.assertDoesntExist(content+'>p', "Content is not already populated.");
		this.test.assertNotVisible(content, "Content selector is not currently visible.");
		this.click(tab);
		this.waitUntilVisible(content+'>p', function(){
			casper.echo("Content became visible in " + (Date.now()-start) + " ms", "INFO_BAR");
			if(capfilename)this.captureSelector(capfilename, content);
		});
	});	
}

Selection_012

MOAR FAST!

Web development has reached escape velocity.  For me, personally, it has gone from a nuisance, to a hobby, to a job, to a passion.  There are entire industries built on and around the web now and the pace is accelerating.  There is a forest of information out there on how to build and optimize web apps, and it is tall and wide.  I’d like to share with you a few of the things I’ve learned along the way.

Thanks for stopping by,

ryan