<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[JP's blog]]></title>
  <link href="http://blog.jphpsf.com/atom.xml" rel="self"/>
  <link href="http://blog.jphpsf.com/"/>
  <updated>2012-10-31T08:40:05-07:00</updated>
  <id>http://blog.jphpsf.com/</id>
  <author>
    <name><![CDATA[JP]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Running Jasmine tests with Phantom.js or Webdriver]]></title>
    <link href="http://blog.jphpsf.com/2012/10/31/running-Jasmine-tests-with-Phantom-js-or-Webdriver/"/>
    <updated>2012-10-31T08:33:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/10/31/running-Jasmine-tests-with-Phantom-js-or-Webdriver</id>
    <content type="html"><![CDATA[<p><a href="http://twitter.com/ngauthier">Nick Gauthier</a> was recently sharing how
he was running his <a href="http://pivotal.github.com/jasmine/">Jasmine</a> test using
Capybara with the Capybara Webkit headless driver. You can check out his
<a href="https://github.com/ngauthier/capybara-jasmine">capybara-jasmine project on GitHub</a>.</p>

<p>In my recent <a href="http://blog.jphpsf.com/2012/09/30/OMG-test-driven-development-actually-works/">blog post on TDD</a>
I mentioned that I had just put together a Javascript test suite using Jasmine.
In my case, I&#8217;ve used <a href="http://phantomjs.org/">Phantom.js</a> for headless fast tests
as well as <a href="https://code.google.com/p/selenium/">Selenium Webdriver</a> for real
browser testing (I usually use headless during development to get quick feedback
and use the real browsers as a safety check before commit). Nick Gauthier&#8217;s project
inspired me to share my setup.</p>

<h1>Test suite</h1>

<p>For this blog post, I can not share the code I already built as it belongs to my employer.
Instead, I will start from scratch using the <a href="https://github.com/pivotal/jasmine/downloads">Jasmine 1.2.0 standalone release</a>. It includes a sample test suite which will be a perfect
fit for this example. It includes the main test runner (an HTML page called <code>SpecRunner.html</code>)
and the Jasmine distribution (under the <code>lib/</code> directory). It also includes example code
under <code>spec</code> and <code>src</code>. If you unzip the file and load <code>SpecRunner.html</code> in your browser,
you should see the test suite pass without errors.</p>

<h1>Phantom.js</h1>

<p>To run the test suite using Phantom.js, I&#8217;ve used <a href="https://github.com/jcarver989/phantom-jasmine">Joshua Carver&#8217;s Jasmine runner for Phantom.js</a>. I copied
the <code>lib</code> directory from the project under <code>lib/phantom-jasmine</code> in my source tree.</p>

<p>Next I changed the <code>SpecRunner.html</code> to add an additional reporter called
<code>ConsoleReporter</code> - which is part of Joshua&#8217;s project.</p>

<figure class='code'><figcaption><span>Add script tag for ConsoleReporter  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;script </span><span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span> <span class="na">src=</span><span class="s">&quot;lib/phantom-jasmine/console-runner.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span>Add ConsoleReporter to Jasmine environment  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>window.consoleReporter = new jasmine.ConsoleReporter();
</span><span class='line'>jasmineEnv.addReporter(consoleReporter);
</span></code></pre></td></tr></table></div></figure>


<p>Third step: patch Jasmine to get a stack trace on test failure. The
current version of Jasmine (1.2.0) does not show stack traces when
executed throught Phantom.js. Thanks to a <a href="http://stackoverflow.com/questions/11245016/stack-trace-for-jasmine-test-with-the-resharper-7-test-runner">tip found on Stackoverflow</a> I was able to fix that
with a very simple patch and submitted a <a href="https://github.com/pivotal/jasmine/pull/291">pull request</a>.</p>

<figure class='code'><figcaption><span>Jasmine patch for stack traces  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='diff'><span class='line'><span class="gu">@@ -106,7 +106,9 @@ jasmine.ExpectationResult = function(params) {</span>
</span><span class='line'>   this.actual = params.actual;
</span><span class='line'>   this.message = this.passed_ ? &#39;Passed.&#39; : params.message;
</span><span class='line'>
</span><span class='line'><span class="gd">-  var trace = (params.trace || new Error(this.message));</span>
</span><span class='line'><span class="gi">+  var err;</span>
</span><span class='line'><span class="gi">+  try { throw new Error(this.message); } catch(e) { err = e };</span>
</span><span class='line'><span class="gi">+  var trace = (params.trace || err);</span>
</span><span class='line'>   this.trace = this.passed_ ? &#39;&#39; : trace;
</span><span class='line'> };
</span></code></pre></td></tr></table></div></figure>


<p>Assuming that Phantom.js is installed and available in the <code>$PATH</code>,
the test suite can be executed using the following command:</p>

<figure class='code'><figcaption><span>Running the Jasmine test with Phantom.js  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>phantomjs lib/phantom-jasmine/run_jasmine_test.coffee SpecRunner.html
</span></code></pre></td></tr></table></div></figure>


<p>Finally, I wrapped the above command in a Rake task so that I can
just type <code>rake phantomjs</code> to run the test suite:</p>

<figure class='code'><figcaption><span>Rake task for Phantom.js  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">desc</span> <span class="s2">&quot;Run Jasmine tests with Phantomjs&quot;</span>
</span><span class='line'><span class="n">task</span> <span class="ss">:phantomjs</span> <span class="k">do</span>
</span><span class='line'>  <span class="c1"># Note: we are assuming phantomjs is installed and available in $PATH</span>
</span><span class='line'>  <span class="n">sh</span> <span class="sx">%{phantomjs lib/phantom-jasmine/run_jasmine_test.coffee SpecRunner.html}</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is what the output looks like:</p>

<p><img src="http://blog.jphpsf.com/images/blog/2012-10-27-jasmine-phantom.png" title="Jasmine Phantom.js output" ></p>

<h1>Webdriver</h1>

<p>In order to execute the Jasmine test suite in real browsers, I am using Selenium
Webdriver. I am using the <code>selenium-webdriver</code> gem to interact with it.
In just a minute, I will show how I have added an additional task to my <code>Rakefile</code>
to run the tests.</p>

<p>Also note that a webserver is required to serve the <code>SpecRunner.html</code> file and
its dependencies. One could setup a webserver such as Apache but I think it is
too much work and creates an external unnecessary dependency for the test runner
(every environment where the tests are executed would need to configure an
instance of Apache). Instead, I prefer to use the <code>service_manager</code> gem to spin
up a simple web server on demand using the <code>python -m SimpleHTTPServer</code> command.
With Service Manager, you define services that will be automatically started when
the tests begin and stopped at the end. Because Python is widely available, no extra
dependencies should be required. For more information, see <a href="https://github.com/leadtune/service_manager">service_manager documentation on GitHub</a>.</p>

<p>The <code>Rakefile</code> in the end is fairly straightforward:</p>

<ul>
<li>Require <code>bundler</code> and some gems</li>
<li>Start <code>ServiceManager</code> which will spawn the webserver process</li>
<li>Detect the browser passed as a command line argument</li>
<li>Instantiate Webdriver and load the <code>SpecRunner.html</code> file</li>
<li>Capture the output of the <code>ConsoleReporter</code> and display it</li>
<li>Finally, check the status for success or failure</li>
</ul>


<p>The complete <code>Rakefile</code> looks like this:</p>

<figure class='code'><figcaption><span>Rakefile including task for Webdriver  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;bundler/setup&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;selenium-webdriver&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;service_manager&#39;</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="n">desc</span> <span class="s1">&#39;Run Jasmine tests with Phantomjs&#39;</span>
</span><span class='line'><span class="n">task</span> <span class="ss">:phantomjs</span> <span class="k">do</span>
</span><span class='line'>  <span class="c1"># Note: we are assuming phantomjs is installed and available in $PATH</span>
</span><span class='line'>  <span class="n">sh</span> <span class="sx">%{phantomjs lib/phantom-jasmine/run_jasmine_test.coffee SpecRunner.html}</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="n">desc</span> <span class="s1">&#39;Run Jasmine tests with Webdriver&#39;</span>
</span><span class='line'><span class="n">task</span> <span class="ss">:webdriver</span> <span class="k">do</span>
</span><span class='line'>  <span class="c1"># Use service_manager to start a simple web server</span>
</span><span class='line'>  <span class="no">ServiceManager</span><span class="o">.</span><span class="n">start</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># Detect which browser we want to run</span>
</span><span class='line'>  <span class="k">case</span> <span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;browser&#39;</span><span class="o">]</span>
</span><span class='line'>  <span class="k">when</span> <span class="s1">&#39;chromium&#39;</span>
</span><span class='line'>    <span class="c1"># TODO: detect chromium path? I use Linux, this is the path on my machine</span>
</span><span class='line'>    <span class="no">Selenium</span><span class="o">::</span><span class="no">WebDriver</span><span class="o">::</span><span class="no">Chrome</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="s1">&#39;/usr/lib/chromium-browser/chromium-browser&#39;</span>
</span><span class='line'>    <span class="n">driver</span> <span class="o">=</span> <span class="no">Selenium</span><span class="o">::</span><span class="no">WebDriver</span><span class="o">.</span><span class="n">for</span> <span class="ss">:chrome</span>
</span><span class='line'>  <span class="k">when</span> <span class="s1">&#39;firefox&#39;</span>
</span><span class='line'>    <span class="n">driver</span> <span class="o">=</span> <span class="no">Selenium</span><span class="o">::</span><span class="no">WebDriver</span><span class="o">.</span><span class="n">for</span> <span class="ss">:firefox</span>
</span><span class='line'>  <span class="k">else</span>
</span><span class='line'>    <span class="k">raise</span> <span class="no">ArgumentError</span><span class="p">,</span> <span class="s1">&#39;Unknown browser requested&#39;</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># Finally, we load the spec runner HTML page with WebDriver</span>
</span><span class='line'>  <span class="n">driver</span><span class="o">.</span><span class="n">navigate</span><span class="o">.</span><span class="n">to</span> <span class="s1">&#39;http://localhost:8000/SpecRunner.html&#39;</span>
</span><span class='line'>  <span class="n">status</span> <span class="o">=</span> <span class="n">driver</span><span class="o">.</span><span class="n">execute_script</span><span class="p">(</span><span class="s1">&#39;return consoleReporter.status;&#39;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">output</span> <span class="o">=</span> <span class="n">driver</span><span class="o">.</span><span class="n">execute_script</span><span class="p">(</span><span class="s1">&#39;return consoleReporter.getLogsAsString();&#39;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">driver</span><span class="o">.</span><span class="n">quit</span>
</span><span class='line'>
</span><span class='line'>  <span class="nb">print</span> <span class="n">output</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># Make sure to exit with code &gt; 0 if there is a test failure</span>
</span><span class='line'>  <span class="k">raise</span> <span class="no">RuntimeError</span><span class="p">,</span> <span class="s1">&#39;Failure&#39;</span> <span class="k">unless</span> <span class="n">status</span> <span class="o">===</span> <span class="s1">&#39;success&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>To run the <code>webdriver</code> task, just execute <code>rake webdriver browser=firefox</code>. You should
see Firefox start and go through the tests. This is what the output looks like:</p>

<p><img src="http://blog.jphpsf.com/images/blog/2012-10-27-jasmine-webdriver.png" title="Jasmine Webdriver output" ></p>

<p>A remaining step is that I will need to add support for browsers other than Firefox
or Chromium, as well as support for remote Webdriver instances (such as Internet
Explorer running in a virtual machine).</p>

<h1>Breaking stuff</h1>

<p>Before wrapping up, I&#8217;d like to show a failure example. Let&#8217;s break some code
by commenting out line 17 of <code>src/Player.js</code>. Running <code>rake phantomjs</code> fails
as expected. Notice how I can see the full stack trace which points me to line
33 of <code>spec/PlayerSpec.js</code>.</p>

<p><img src="http://blog.jphpsf.com/images/blog/2012-10-27-jasmine-failure.png" title="Jasmine Phantom.js failure" ></p>

<h1>Wrap up</h1>

<p>Phantom.js, Webdriver and Jasmine are a really powerful combo to test drive code.
Not only that, they are also really easy to set up. Kudos to the various Open
Source contributors behind these projects for providing a great developer experience!</p>

<p>The next step of this adventure is continuous integration. I need to integrate
the tests with our Jenkins instance. Hopefully, that should be trivial since
I have my tests runner command ready to go.</p>

<p>If you want to see the code, it&#8217;s available on <a href="https://github.com/jphpsf/jasmine-phantomjs">GitHub</a>.</p>

<p>What do you think? Do you find this technique useful? What other tips
do you use for running your Javascript tests? If you have feedback on this post,
feel free to comment below or to contact me via Twitter (<a href="http://twitter.com/jphpsf">@jphpsf</a>).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[OMG, Test Driven Development actually works!]]></title>
    <link href="http://blog.jphpsf.com/2012/09/30/OMG-test-driven-development-actually-works/"/>
    <updated>2012-09-30T13:15:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/09/30/OMG-test-driven-development-actually-works</id>
    <content type="html"><![CDATA[<p>You often hear people advocate that writing tests (unit, functional, etc.) when
building software leads to less bugs in production. How can one verify this
statement? Usually, those people are already using TDD or BDD and might be working
for companies that have a strong testing culture from day one. Then, how can
one measure the impact of <em>NOT</em> writing tests? How can we verify that practicing
TDD is actually producing less bugs? Can we stop writing tests for a period of
time and look at the consequences it has on the defect count? That doesn&#8217;t
seem very realistic.</p>

<p>In this post, I am trying to answer the question by analyzing real numbers
from my current job. No tests were written originally and once tests were
included, I became a strong advocate of the TDD methodology.</p>

<!-- more -->


<h1>Background</h1>

<p>I&#8217;ve been a web developer for over 10 years and in 2009 I started to hear a
lot about test driven development (TDD). It was then I decided to learn more
about it. At that time I had been working for my current employer for about 2
years. Fast forward to today (2012). I&#8217;ve now been with my company for 5 years
and have spent the last 3 years applying TDD principles.</p>

<p>This is very interesting because today I can look at our bug tracker and gather
statistics about the number of defects found over time and see the impact TDD
has had on our code base.</p>

<p>A quick word about the software stack: I build a UI based on PHP and
Javascript. I am the lead UI engineer, which means if there is a UI bug, I am
likely to be the one responsible. The UI interacts with backend C++ services
which are leveraging PLSQL code running on Oracle.</p>

<p>The PHP code of the UI is the only area where TDD was applied. Our Javascript
code does not have tests (yet). Sadly, no other engineers in the company are
practicing TDD. All the other layers of the code base are not unit or
functionally tested (the testing is handled by a dedicated QA team post
development).</p>

<p>This actually makes it really easy to look at statistics. I can look over time
at the number of defects in the UI vs the entire product. That should allow me
to answer the initial question, which in context can be rephrased as: does TDD
adoption lead to less defects in the UI that I am responsible for?</p>

<h1>So does TDD actually work?</h1>

<p>The following graph is generated from our bug tracker. It is showing the ratio
of bugs in the UI compared to the whole product.</p>

<p><img src="http://blog.jphpsf.com/images/blog/2012-09-30-defect-ratio.png" title="Defect Ratio" ></p>

<p>There are a few interesting things to notice:</p>

<ul>
<li><p>First and foremost, we can answer the question: the amount of bugs found in
the UI (in green above) has been reduced by about 50% (the UI accounted for
roughly 35% of the bugs in the product and today it&#8217;s down to hovering around 15%).</p></li>
<li><p>Applying TDD on a legacy code base does not magically change things
overnight. I started applying TDD in Q3 of 2009. You can see the number of bugs
starting to decline around Q3 of 2010 with a bigger drop in Q3 of 2011. It took
nearly 2 years to achieve the 50% drop.</p></li>
<li><p>The graph shows a couple of bumps (e.g. slight increase in bug count) in Q2
of 2010 and Q2 of 2011. Looking at our releases, this corresponds to a time where
we added features based on 3rd party maps API that heavily relied on Javascript.
As I mentioned previously, we did not have Javascript tests at the time. This also
confirms that not writing tests leads to more bugs.</p></li>
</ul>


<h1>What&#8217;s next?</h1>

<p>As I said earlier, I started applying TDD to the PHP side of my code. Looking at
the bugs I get nowadays, I noticed they usually fall in one of two categories:</p>

<ul>
<li><p>Bugs in our Javascript code (which again is not automatically tested)</p></li>
<li><p>Integration bugs (for instance where independent PHP components are passing
unit tests, but are not working together properly)</p></li>
</ul>


<p>This leads me to the next obvious step of my testing adventure: I need to add
a Javascript test suite as well as a end to end integration testing suite.</p>

<p>This is what I&#8217;ve been working on over the summer. For Javascript, I&#8217;ve setup a
test suite based on the <a href="http://pivotal.github.com/jasmine/">Jasmine BDD</a>
framework. For end to end testing, I&#8217;ve setup <a href="http://cukes.info/">Cucumber</a>.
In both cases, I can run the tests using real browsers with <a href="http://seleniumhq.org/">Selenium Web Driver</a>
or headless using the awesome <a href="http://phantomjs.org/">Phantom.js</a>.</p>

<p>We are about to start our next development cycle and I am looking forward
to leveraging this new setup to build higher quality software. I am also looking
forward to looking at this topic next year and seeing what impact these tools will
have. It will hopefully help to reduce our bug count further.</p>

<p>Also, sharing those numbers with my teammates helped convince some engineers of
the benefits of TDD. Engineers working on other services of our product have shown
interest and are willing to investigate how they can apply TDD to their codebases.
It&#8217;ll be interesting to see what kind of benefits they get out of the exercise.</p>

<h1>Wrap up</h1>

<p>What about you? How did TDD or BDD affect your code base? Do you have similar
statistics to share? Feel free to comment below.</p>

<p>As usual, if you have feedback on this post, feel free to leave a note or
to contact me via Twitter (<a href="http://twitter.com/jphpsf">@jphpsf</a>).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[DRYing up your JavaScript Jasmine tests with the data provider pattern]]></title>
    <link href="http://blog.jphpsf.com/2012/08/30/drying-up-your-javascript-jasmine-tests/"/>
    <updated>2012-08-30T08:15:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/08/30/drying-up-your-javascript-jasmine-tests</id>
    <content type="html"><![CDATA[<p>Lately, I&#8217;ve been using <a href="http://pivotal.github.com/jasmine/">Jasmine</a> to unit
test my JavaScript code. Jasmine is a great BDD framework. It has a very clean
and easy syntax. It has a lot of useful features such as matchers/expectations
and mock objects (spies).</p>

<p>However, one feature I have been missing is a data provider mechanism. I learned
about that feature while using <a href="http://phpunit.de">PHPUnit</a> for PHP unit testing.
The basic premise of a data provider is to feed a test with multiple test values
to avoid repeating your test code over and over.</p>

<p>In this post, I will show you how you can leverage that data provider pattern
with Jasmine.</p>

<!-- more -->


<h2>The problem</h2>

<p>First, let me explain the problem I am trying to solve. Imagine you have some
validation code that must verify a username. A correct username matches the
following requirement:</p>

<ul>
<li>Must be alphanumeric or underscore</li>
<li>Minimum of 3 characters</li>
<li>No more than 12 characters</li>
</ul>


<p>Positive and negative test cases could look like this:</p>

<figure class='code'><figcaption><span>Username validation with Jasmine  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">describe</span><span class="p">(</span><span class="s2">&quot;username validation&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">it</span><span class="p">(</span><span class="s2">&quot;should return true for valid usernames&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">expect</span><span class="p">(</span><span class="nx">validateUserName</span><span class="p">(</span><span class="s2">&quot;abc&quot;</span><span class="p">)).</span><span class="nx">toBeTruthy</span><span class="p">();</span>
</span><span class='line'>    <span class="nx">expect</span><span class="p">(</span><span class="nx">validateUserName</span><span class="p">(</span><span class="s2">&quot;longusername&quot;</span><span class="p">)).</span><span class="nx">toBeTruthy</span><span class="p">();</span>
</span><span class='line'>    <span class="nx">expect</span><span class="p">(</span><span class="nx">validateUserName</span><span class="p">(</span><span class="s2">&quot;john_doe&quot;</span><span class="p">)).</span><span class="nx">toBeTruthy</span><span class="p">();</span>
</span><span class='line'>  <span class="p">})</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">it</span><span class="p">(</span><span class="s2">&quot;should return false for invalid usernames&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">expect</span><span class="p">(</span><span class="nx">validateUserName</span><span class="p">(</span><span class="s2">&quot;ab&quot;</span><span class="p">)).</span><span class="nx">toBeFalsy</span><span class="p">();</span>
</span><span class='line'>    <span class="nx">expect</span><span class="p">(</span><span class="nx">validateUserName</span><span class="p">(</span><span class="s2">&quot;name_too_long&quot;</span><span class="p">)).</span><span class="nx">toBeFalsy</span><span class="p">();</span>
</span><span class='line'>    <span class="nx">expect</span><span class="p">(</span><span class="nx">validateUserName</span><span class="p">(</span><span class="s2">&quot;no spaces&quot;</span><span class="p">)).</span><span class="nx">toBeFalsy</span><span class="p">();</span>
</span><span class='line'>    <span class="nx">expect</span><span class="p">(</span><span class="nx">validateUserName</span><span class="p">(</span><span class="s2">&quot;inv*alid&quot;</span><span class="p">)).</span><span class="nx">toBeFalsy</span><span class="p">();</span>
</span><span class='line'>  <span class="p">})</span>
</span><span class='line'><span class="p">})</span>
</span></code></pre></td></tr></table></div></figure>


<p>The above test is pretty straightforward: we are testing a method called
<code>validateUserName</code> and we are making sure that it returns <code>true</code> for valid
values and <code>false</code> for invalid ones.</p>

<p>The problem I have with the above code is the repetition of the same
expectation in each of the two <code>it</code> blocks.</p>

<h2>DRYing it up</h2>

<p>Let&#8217;s look at the same 2 tests using the data provider pattern. I came up
with the following syntax:</p>

<figure class='code'><figcaption><span>Same validation without repetition  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">describe</span><span class="p">(</span><span class="s2">&quot;username validation&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">using</span><span class="p">(</span><span class="s2">&quot;valid values&quot;</span><span class="p">,</span> <span class="p">[</span><span class="s2">&quot;abc&quot;</span><span class="p">,</span> <span class="s2">&quot;longusername&quot;</span><span class="p">,</span> <span class="s2">&quot;john_doe&quot;</span><span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">){</span>
</span><span class='line'>    <span class="nx">it</span><span class="p">(</span><span class="s2">&quot;should return true for valid usernames&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">expect</span><span class="p">(</span><span class="nx">validateUserName</span><span class="p">(</span><span class="nx">value</span><span class="p">)).</span><span class="nx">toBeTruthy</span><span class="p">();</span>
</span><span class='line'>    <span class="p">})</span>
</span><span class='line'>  <span class="p">})</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">using</span><span class="p">(</span><span class="s2">&quot;invalid values&quot;</span><span class="p">,</span> <span class="p">[</span><span class="s2">&quot;ab&quot;</span><span class="p">,</span> <span class="s2">&quot;name_too_long&quot;</span><span class="p">,</span> <span class="s2">&quot;no spaces&quot;</span><span class="p">,</span> <span class="s2">&quot;inv*alid&quot;</span><span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">){</span>
</span><span class='line'>    <span class="nx">it</span><span class="p">(</span><span class="s2">&quot;should return false for invalid usernames&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">expect</span><span class="p">(</span><span class="nx">validateUserName</span><span class="p">(</span><span class="nx">value</span><span class="p">)).</span><span class="nx">toBeFalsy</span><span class="p">();</span>
</span><span class='line'>    <span class="p">})</span>
</span><span class='line'>  <span class="p">})</span>
</span><span class='line'><span class="p">})</span>
</span></code></pre></td></tr></table></div></figure>


<p>Basically, I wrap each <code>it</code> block with a <code>using</code> block. The <code>using</code> block
specifies what values to pass to the <code>it</code> test.</p>

<p>The <code>using</code> function is really easy to implement:</p>

<figure class='code'><figcaption><span>Data provider code for Jasmine  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">function</span> <span class="nx">using</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">values</span><span class="p">,</span> <span class="nx">func</span><span class="p">){</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">count</span> <span class="o">=</span> <span class="nx">values</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">count</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">values</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span> <span class="o">!==</span> <span class="s1">&#39;[object Array]&#39;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nx">values</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">values</span><span class="p">[</span><span class="nx">i</span><span class="p">]];</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="nx">func</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">values</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
</span><span class='line'>    <span class="nx">jasmine</span><span class="p">.</span><span class="nx">currentEnv_</span><span class="p">.</span><span class="nx">currentSpec</span><span class="p">.</span><span class="nx">description</span> <span class="o">+=</span> <span class="s1">&#39; (with &quot;&#39;</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="s1">&#39;&quot; using &#39;</span> <span class="o">+</span> <span class="nx">values</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;, &#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;)&#39;</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>using</code> function takes 3 arguments:</p>

<ul>
<li><code>name</code>: that is the name describing the set of values</li>
<li><code>values</code>: array of values to use for the tests (note that each element in the
array can be a simple value or an array of multiple values)</li>
<li><code>func</code>: function wrapping the <code>it</code> block</li>
</ul>


<p>The last line enhances the test description with the name associated
with the values (first argument of the using block). It also adds which
value has been used for a given test. This will make troubleshooting
easier in case of a test failure.</p>

<h2>Demo</h2>

<p>A demo is usually better for understanding than a long explanation with
code samples so I pushed a demo to my GitHub account:</p>

<ul>
<li><a href="http://jphpsf.github.com/jasmine-data-provider/">see the demo</a></li>
<li><a href="https://github.com/jphpsf/jasmine-data-provider">see the code</a></li>
</ul>


<p>Here is a screenshot of the Jasmine output:</p>

<p><img src="http://blog.jphpsf.com/images/blog/2012-08-30-jasmine-data-provider.png" title="Jasmine data provider" ></p>

<h2>Wrap up</h2>

<p>I did some research prior to setting this up and I could not find
an existing solution. The data provider functionality is standalone and
can easily be added to the spec helper file in your project.</p>

<p>What do you think? Do you find this technique useful? What other tips
do you use for DRYing up your tests? If you have feedback on this post,
feel free to comment below or to contact me via Twitter (<a href="http://twitter.com/jphpsf">@jphpsf</a>).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Share the #webperf love]]></title>
    <link href="http://blog.jphpsf.com/2012/08/28/share-the-webperf-love/"/>
    <updated>2012-08-28T09:15:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/08/28/share-the-webperf-love</id>
    <content type="html"><![CDATA[<p><em>August is Speed Awareness Month! This blog post was originally published
<a href="http://www.speedawarenessmonth.com/share-the-webperf-love/">yesterday</a>
 on the <a href="http://www.speedawarenessmonth.com/">Speed Awareness Month blog</a>.
Check it out to learn tips and tools for speeding up your website.</em></p>

<p>If you care about web performance, you are likely to know and use tools
such as WebPagetest, HTTP Archive, YSlow, Boomerang, etc. Whether your level
is novice or expert with these tools, using them is only one side of the
coin. What about contributing back to them? Those tools are open source
which means you - whether you are a novice or an expert - can help out.</p>

<p>Open source represents one aspect of the web performance community.
User group (meetups) focused on web performance are another.</p>

<p>In this post, I will explain how you can get started and get involved
in our continuously growing community.</p>

<!-- more -->


<h2>Open Source Contributions</h2>

<p>There are many ways one can contribute to performance open source projects.
The first common step is usually to find the source repository. This
information is typically found on the project&#8217;s official website. Look for
links such as <em>&#8220;Contribute&#8221;</em>, <em>&#8220;Source Code&#8221;</em> or <em>&#8220;Fork me on GitHub&#8221;</em>. For
instance, see the <a href="http://yslow.org/">YSlow website</a>, which includes a link
to the <em>&#8220;Source&#8221;</em> in the top navigation as well as a <em>&#8220;Fork me on GitHub&#8221;</em>
banner in the top left corner:</p>

<p><img src="http://blog.jphpsf.com/images/blog/2012-08-09-yslow-banner.png" title="YSlow example" ></p>

<p>Most open source projects nowadays are hosted on GitHub or Google Code. Here
are the repositories for some of the most popular web performance related ones:</p>

<ul>
<li><a href="https://code.google.com/p/webpagetest">WebPagetest</a></li>
<li><a href="https://code.google.com/p/httparchive">HTTP Archive</a></li>
<li><a href="https://github.com/lognormal/boomerang">Boomerang</a></li>
<li><a href="https://github.com/marcelduran/yslow">YSlow</a></li>
<li><a href="https://github.com/sergeychernyshev/showslow">ShowSlow</a></li>
</ul>


<h3>1. Contribute code:</h3>

<p>Now that you&#8217;ve located the repository, it&#8217;s time to contribute! Do you have
an idea for a new feature? Did you find a bug or see an issue in the bug tracker
that you can resolve? Implement the new functionality or create a fix and send
a patch back to the author (or submit a pull request if the project is on GitHub).</p>

<h3>2. Testing and bug reports:</h3>

<p>Not a developer or don&#8217;t think you have the coding chops? Not a problem. There
are other ways to contribute. If you encounter a bug as you use the software, make
sure to report the issue in the bug tracker. Chances are that if you encounter a
problem, others might as well, but make sure to search the bug tracker first. In
addition to bugs, you can submit feature requests or enhancement suggestions.
As an example, this is the <a href="https://code.google.com/p/httparchive/issues/list">bug tracker for the HTTP archive project</a>.</p>

<h3>3. Help with user support:</h3>

<p>Users might encounter issues and in turn will have some questions. A first place to
look is the issue tracker. If you see an issue for which you know the solution,
feel free to give an answer to the original poster. Other places to look at are
mailings lists or IRC channels. Here is <a href="https://showslow.uservoice.com/">some user feedback for the ShowSlow project</a>.</p>

<h3>4. Contribute to the documentation or website:</h3>

<p>As you read the documentation, report any error you might find. If you have writing
skills, maybe you can help? Do you see any mistakes or missing information? Do you
have suggestions for new howtos or guides? Write them! Often projects are using wikis
which make it easy to add or edit content. If the documentation is not available in
your native language, consider translating it. The same can be done for the
project&#8217;s website: you can help maintain it with new content, corrections,
translations, etc. For instance, this is the <a href="https://github.com/marcelduran/yslow/wiki">YSlow user documentation wiki</a>.</p>

<h3>5. Give financial support:</h3>

<p>Open source projects are often run by individuals on their spare time and personal money.
If you want to support the project, donate some money (look for a <em>&#8220;Donate&#8221;</em> link) or
have your company offer to sponsor the project.</p>

<h3>6. Live instances:</h3>

<p>What about providing hosting? Do you have bandwidth and/or hardware available? Tools like
WebPagetest or ShowSlow provide live instances hosted all over the world. Do you have a
hosting location to offer? Get in touch! You&#8217;ll find the contact information on the project&#8217;s
website. The following page for instance, gives <a href="https://sites.google.com/a/webpagetest.org/docs/other-resources/hosting-a-test-location">details about hosting a WebPagetest instance</a>.</p>

<h3>7. Thank yous:</h3>

<p>A very simple gesture, yet really appreciated by open source developers: express your
appreciation and thank them. It&#8217;s as simple as a @mention on Twitter, but why not send
a nice email or a post card?</p>

<p>These are a few ideas to get started with open source. Still not sure where to start?
Just ask where you can help! I am sure the project owners will be happy to indicate
where help is needed.</p>

<h2>Meetups</h2>

<p>Open source projects are an important element of the performance community. Meetups
are another great way to participate. There are <a href="http://web-performance.meetup.com/">quite a few performance meetup groups</a>
already. Check them out!</p>

<p>Don&#8217;t see one close to you? You could start one. I&#8217;ve seen three different formats
so far. First, the classic tech talk with Q&amp;A: a speaker gives a presentation on performance
followed by a Q&amp;A session. Second, the <em>Meet 4 Speed</em>: an open format where attendees
can show their work on performance or bring a problem and get help from others.
Finally, the drink up: meet over a performance enhancing pint (I shamelessly stole that
line from my good friend Aaron) and talk shop with performance people.</p>

<p>Are you or your company working on really cool performance projects? Do you have
some results or metrics to share? I love when companies are sharing their success
stories (&#8220;We implemented the following web performance tweaks and we increased our sales by
X%&#8221;!). Propose a talk to your local meetup. As an organizer myself, I am
always looking for people that have interesting things to share on web performance.</p>

<h2>Other suggestions</h2>

<p>There are a couple of other suggestions that I think are worth mentioning.</p>

<p>The first is blogging: you can share your knowledge with others on your own blog or
as a guest blogger (see the <a href="http://calendar.perfplanet.com/">Performance Calendar</a> for
instance).</p>

<p>And let&#8217;s not forget forums: one example is the <a href="http://www.webpagetest.org/forums/">forum hosted by the WebPagetest project</a>
. This is a good place to find some help on performance or help others.</p>

<h2>Wrap up</h2>

<p>This is what the <a href="http://www.speedawarenessmonth.com/"><em>Speed Awareness Month</em></a> is
about. Share the #webperf love: evangelize performance best practices, raise
awereness and help improve the invaluable tools from our web performance toolbox.</p>

<p>Do you have feedback on this post? Feel free to comment below or to contact me via Twitter
(<a href="http://twitter.com/jphpsf">@jphpsf</a>).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Squeezing Octopress for faster load times]]></title>
    <link href="http://blog.jphpsf.com/2012/06/12/squeezing-octopress-for-faster-load-times/"/>
    <updated>2012-06-12T21:15:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/06/12/squeezing-octopress-for-faster-load-times</id>
    <content type="html"><![CDATA[<p>This blog runs an out of the box <a href="http://octopress.org/">Octopress</a> setup. I love Octopress. It&#8217;s a great framework. It&#8217;s trivial to setup, gets out of your way and it just works.</p>

<p>Being passionate about web performance optimization, I decided to <em>&#8220;eat my own dog food&#8221;</em> and look at how I could improve the load time of my blog.</p>

<!-- more -->


<h2>Baseline</h2>

<p>I&#8217;ve measured the homepage of the blog with my usual weapon of choice, <a href="http://www.webpagetest.org/">WebPagetest</a>. Using Firefox and Chrome roughly yielded the same results:</p>

<ul>
<li>DOM ready fires at about 1.2 seconds.</li>
<li>The page is fully loaded between 2.8 and 3 seconds.</li>
<li>There are 21 HTTP requests for a total of 244KB.</li>
</ul>


<h2>Optimizing Javascript</h2>

<p>The first obvious improvment is with javascript. The default Octopress installation will load 4 javascript files as shown in the screenshot below:</p>

<p><img src="http://blog.jphpsf.com/images/blog/2012-06-10-4-script-tags.png" title="Javascript script tags" ></p>

<p>This is bad because browsers usually have a limit in the number of concurrent downloads they can perform at the same time. While this limit has been increased in the recent years, it is still a good practice to concatenate all the Javascript resources into one file. I created a file under <code>source/javascripts/all.js</code> in which I combined all 4 files. While I was at it, I minified <code>all.js</code> to make it smaller and moved the file from the head to the bottom of the page.</p>

<p>Then I removed the 3 script tags from <code>source/_includes/head.html</code>:</p>

<figure class='code'><figcaption><span>Remove script tags  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/modernizr-2.0.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/ender.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/octopress.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>And I added the following to <code>source/_includes/custom/after_footer.html</code>:</p>

<figure class='code'><figcaption><span>Loading combined all.js  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/all.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span> <span class="nt">/&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>The load time did not change: still around 2.8 seconds. However something broke: the sidebar fails to load my recent tweets because that code depends on some that were moved to the bottom of the page (as explained above). I fixed the dependency and merged all the twitter JS code into all.js. The twitter JS code can be found in <code>source/_includes/asides/twitter.html</code>:</p>

<figure class='code'><figcaption><span>Removing Twitter code  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;script </span><span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nx">$</span><span class="p">.</span><span class="nx">domReady</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>    <span class="nx">getTwitterFeed</span><span class="p">(</span><span class="s2">&quot;jphpsf&quot;</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'><span class="nt">&lt;/script&gt;</span>
</span><span class='line'><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;{ { root_url } }/javascripts/twitter.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;</span> <span class="nt">&lt;/script&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p><em>Disclaimer: this last change might need to be applied to other plugins or sidebar modules. Twitter is the only one I used and after this last change, my recent tweets were back.</em></p>

<p>Trying to improve the load time further, I decided to load the all.js file asynchronously. The blog content does not depend on any javascript, so it is ok to defer the load to later. I used the same pattern as the Google Analytics snippets, eg. in <code>source/_includes/custom/after_footer.html</code> I now have:</p>

<figure class='code'><figcaption><span>Loading all.js asynchronously  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;script </span><span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">all</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;script&#39;</span><span class="p">);</span> <span class="nx">all</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="s1">&#39;text/javascript&#39;</span><span class="p">;</span> <span class="nx">all</span><span class="p">.</span><span class="nx">async</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
</span><span class='line'>  <span class="nx">all</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="s1">&#39;{ { root_url } }/javascripts/all.js&#39;</span><span class="p">;</span>
</span><span class='line'>  <span class="nx">s</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">&#39;script&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span> <span class="nx">s</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">all</span><span class="p">,</span> <span class="nx">s</span><span class="p">);</span>
</span><span class='line'><span class="p">})();</span>
</span><span class='line'><span class="nt">&lt;/script&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>This last change brings the DOM ready event to now fires at 0.8 seconds.</p>

<p>Brandon Mathis (the creator of Octopress) mentioned on Twitter his plans to integrate a JS preprocessor (in the same way than Octopress uses compass for CSS preprocessing). I would hope this could include the optimizations mentioned above.</p>

<p>After this change:</p>

<ul>
<li>DOM ready fires at about 0.8 seconds (improved by 0.4 seconds).</li>
<li>The page is fully loaded between 2.8 and 3 seconds (no changes).</li>
<li>There are 17 HTTP requests for a total of 237KB (saved 4 requests and 7KB).</li>
</ul>


<h2>Optimizing @font-face</h2>

<p>Octopress includes the PT Sans font as a default and is including it on the page using <code>@font-face</code>. I noticed a flash of invisible content (see screenshot below). The issue is even more noticeable on mobile devices, which tends to be slower. This is something I noticed on other websites using <code>@font-face</code> as well (Octopress blogs or not).</p>

<p><img src="http://blog.jphpsf.com/images/blog/2012-06-10-invisible-content.png" title="Invisible content" ></p>

<p>Paul Irish explains the problem in <a href="http://paulirish.com/2009/fighting-the-font-face-fout/">this 2009 blog post</a>. The flash of invisible content is actually here to avoid a flash of unstyled content (at least for WebKit browsers). When using <code>@font-face</code>, the browser needs to download the font file. If the file arrives late during the page load, then the browser first shows the content without the font applied and switches to using the font as soon as it arrives. This is called a flash of unstyled content (FOUC for short). To work around this issue, WebKit engineers make the content text invisible until the font is loaded. This is better than the unstyled flash, but it is still an issue. To minimize it, the key is to load the font as fast as possible. Removing the <code>@font-face</code> all together is a solution (the fastest font is the one you don&#8217;t have to load) but for now I wanted to keep using a custom font, so I started digging.</p>

<p>The first thing I discovered was that I was actually loading 2 fonts (Ubuntu Condensed for the headers and PT Sans for everything else). That&#8217;s 25KB and 59KB. One was loaded from my domain the other from Google&#8217;s webfont CDN. I removed the Ubuntu font as PT Sans was looking just fine for the headers. Also, PT Sans leverages Google&#8217;s webfont CDN. The load time dropped to 2.2 seconds. The DOM ready event fires now at 0.6 seconds. Great! Can we make it even faster?</p>

<p>Looking at my waterfall revealed that the font was loaded late after the DOM ready event. The font download finished at around 1.6 seconds. I am assuming that means the content is invisible until then (more on that later).</p>

<p>Paul Irish&#8217;s blog post mentioned another technique: inline the font in the CSS file using data URI. This is a good idea because it removes 2 extra requests (Google&#8217;s webfont CDN loads one CSS file and then the font file). Also, a CSS file can be gzipped which can lead to additional savings.</p>

<p>I removed the font face include tags from the <code>source/_includes/custom/head.html</code> and added the following to the <code>sass/custom/_styles.scss</code> file (note: I did not include the actual base 64 content of the font).</p>

<figure class='code'><figcaption><span>Optimized @font-face syntax  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'><span class="k">@font-face</span> <span class="p">{</span>
</span><span class='line'>  <span class="nt">font-family</span><span class="o">:</span> <span class="s1">&#39;PT Sans&#39;</span><span class="o">;</span>
</span><span class='line'>  <span class="nt">font-style</span><span class="o">:</span> <span class="nt">normal</span><span class="o">;</span>
</span><span class='line'>  <span class="nt">font-weight</span><span class="o">:</span> <span class="nt">normal</span><span class="o">;</span>
</span><span class='line'>  <span class="nt">src</span><span class="o">:</span> <span class="nt">local</span><span class="o">(</span><span class="s1">&#39;PT Sans&#39;</span><span class="o">),</span> <span class="nt">local</span><span class="o">(</span><span class="s1">&#39;PTSans-Regular&#39;</span><span class="o">),</span>
</span><span class='line'>    <span class="nt">url</span><span class="o">(</span><span class="s1">&#39;data:application/x-font-woff;base64,[BASE64 FONT CONTENT GOES HERE]&#39;</span><span class="o">)</span> <span class="nt">format</span><span class="o">(</span><span class="s1">&#39;woff&#39;</span><span class="o">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>DOM ready happens slightly later at 0.8 sec but at this point the font is downloaded. Previously the font was ready at 1.6 seconds. This should improve the flash of invisible content problem.</p>

<p>Are we done with <code>@font-face</code>? No. I noticed an issue in Internet Explorer where the font seems to never load. It turned out to be a great hint for the next step. Data URI length is limited to 32KB in IE8 (according to <a href="http://caniuse.com/#search=uri">caniuse.com</a>). Could I find a smaller font? A quick search for PT Sans lead me to <a href="http://www.fontsquirrel.com/fonts/PT-Sans">Font Squirrel</a> which had the same font as Google webfont. However, it was smaller: 18K instead of 59K. I am not sure where that difference came from. The only difference I could see was visually: while very similar, the Google&#8217;s webfont seemed to be more condensed than the Font Squirrel equivalent. In the end, I think the font is fine so I went ahead and added it to the CSS file.</p>

<p>To verify the impact of these optimizations we can use the comparison feature of WebPagetest which includes a film strip view as well as a video comparison service. The film strip screenshot below shows that the optimized version at the bottom, as expected, loads about 1 second faster:</p>

<p><img src="http://blog.jphpsf.com/images/blog/2012-06-10-filmstrip.png" title="Film strip view" ></p>

<p>You can view WebPagetest video comparison by following <a href="http://www.webpagetest.org/video/view.php?id=120613_c753edf2bda3cad5429e8711667fb758721e164f">this link</a>.</p>

<p>After this change:</p>

<ul>
<li>DOM ready fires at about 0.7 seconds (improved by 0.1 seconds).</li>
<li>The page is fully loaded in about 2 seconds (improved by 1 second).</li>
<li>There are 15 HTTP requests for a total of 172KB (saved 2 more requests and 65KB).</li>
</ul>


<h2>Optimizing with Cloudflare</h2>

<p>Another thing I wanted to investigate was <a href="https://cloudflare.com/">CloudFlare</a>. I am running this blog behind CloudFlare&#8217;s security and performance proxy and was wondering about how the various settings could affect the load time and if CloudFlare was helping my blog to load faster.</p>

<p>I&#8217;ve enabled the performance proxy of CloudFlare since day one, so this blog should already benefit from CloudFlare optimizations. To determine the gains, I decided to disable the performance proxy and measure the page speed. I lost about 0.5 seconds on my load time doing so. The main difference appeared to be the size of downloaded content. It grew from 172KB to 248KB. The difference comes from gzipping/minifying assets such as CSS or Javascript. When bypassing the performance proxy, I hit Heroku&#8217;s server directly and because I haven&#8217;t configured Heroku to gzip or minify assets, it serves unoptimized content. CloudFlare&#8217;s performance proxy shaves 0.5 seconds off of the load time, that&#8217;s not bad.</p>

<p>WebPagetest pointed out that I was not setting the far expire header properly for my assets. CloudFlare actually takes care of that. The default value is pretty low, it is set to 4 hours. I tweaked it to use the recommended 30 days which improved my caching score on WebPagetest.</p>

<p>Another benefit is the CDN: the assets of my blog are deployed on CloudFlare&#8217;s CDN. This is totally transparent to me (I did not have to make any changes to my blog&#8217;s code) and is great for performance. The CDN stores content closer to the user hence allowing faster delivery. I am running out of time here, but I guess the impact could be verified with Webpagetest. One can pick various test locations and compare the performance with and without CDN.</p>

<p>The last feature I played with is <a href="http://blog.cloudflare.com/56590463">Rocket Loader</a>. It&#8217;s a pretty clever Javascript loader. From what I&#8217;ve seen it speeds up a website in two ways. First it makes any javascript files load asynchronously. Second it caches them in the browser&#8217;s local storage. Unfortunatelly, when I activated the feature, the comments powered by Disqus stopped working. Rocket Loader is currently under beta, so I guess there are a few things still left to iron out. In the end, I&#8217;ve already done some optimization to my blog&#8217;s Javascript (previously explained) so I disabled Rocket Loader.</p>

<h2>Conclusion</h2>

<p>I started with 21 HTTP requests for a total of 244KB and a page loading in about 3 seconds. After optimizations, the page is down to 15 requests for a total of 172KB. The page now fully loads in about 2 seconds.</p>

<p>This experiment was very interesting. The big take away was learning more about <code>@font-face</code> performance implications. I think barebone Octopress out of the box performance is not bad at all: the load time of my blog prior to the changes was decent. Yet, I was able to squeeze a little more speed with a few simple changes. I will contact Brandon Mathis (the creator of Octopress) to see if he would be interested by some of these tweaks. With Octopress being open source, patches are as easy as a pull request ;)</p>

<p>Now it&#8217;s your turn! Do you have an Octopress blog? How is your load time? If you try the above tips, do you see any improvements? Do you have any other tips that I might have missed? Contact me via the comment form below, <a href="https://twitter.com/jphpsf">Twitter</a> or the <a href="http://news.ycombinator.com/item?id=4104356,">Hacker News thread</a> I&#8217;d love to hear from you :)</p>

<h2>Update September 2012</h2>

<p>After weighting the pros and cons about the usage of @font-face, I&#8217;ve decided to remove the custom font I was using. In
the end, I value speed more than fancy typography. A basic font like Helvetica is perfectly fine for this blog :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Backing up your Twitter account with &quot;t&quot;]]></title>
    <link href="http://blog.jphpsf.com/2012/05/07/backing-up-your-twitter-account-with-t/"/>
    <updated>2012-05-07T08:32:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/05/07/backing-up-your-twitter-account-with-t</id>
    <content type="html"><![CDATA[<p>Are you backing up your data regularly? You probably are and if not you should :) What about your social media accounts, is that important to backup? For instance, Twitter: have you ever wanted to backup your tweets, direct messages, favorites&#8230;?</p>

<p>There are <a href="http://tweetake.com/">pleny</a> <a href="http://pongsocket.com/tweetnest/">of</a> <a href="https://www.backupify.com/social-media-backup">backup</a> <a href="http://tweetbackup.com/">solutions</a> for Twitter. However, it seems that most of them are 3rd party websites and I am not sure if you can automate them easily (to integrate them with a backup script for instance). Wouldn&#8217;t it be cool if you could drive this task using only the command line?</p>

<p>Recently, I came accross the <a href="http://sferik.github.com/t/">Twitter CLI</a> gem. It&#8217;s a very powerful tool to query Twitter from the command line. In this post, I will show you how to leverage it to backup your Twitter data.</p>

<!-- more -->


<h2>The t gem</h2>

<p>The <a href="http://sferik.github.com/t/">Twitter CLI</a> gem (also known as the <a href="https://github.com/sferik/t">t gem</a>) is an open source ruby gem that you install and use to query Twitter from the command line. It&#8217;s a Ruby gem. Gross, right? You have to install Ruby. That&#8217;s OK, installing Ruby is actually quite easy: checkout <a href="https://rvm.io/rvm/install/">rvm</a> or if you are running Ubuntu, checkout <a href="http://blog.brightbox.co.uk/posts/next-generation-ruby-packages-for-ubuntu">the new Ruby packages from Brightbox</a>.</p>

<p>Once you have your ruby environment up and running, the installation is trivial:</p>

<figure class='code'><figcaption><span>Installing the gem  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>gem install t
</span></code></pre></td></tr></table></div></figure>


<p>Once that&#8217;s done, if you type t in your shell, you should see the t help screen which lists all the available commands. Configuration will be the next step. You need to authorize t to use your Twitter account. Everything is explained on <a href="http://sferik.github.com/t/#configuration">t&#8217;s website</a>, so I will not repeat it here.</p>

<p>You should now be ready to use t. If you want to see some usage examples, jump back to <a href="http://sferik.github.com/t/#usage">t&#8217;s website</a>. It contains some good examples.</p>

<h2>Backing up your Twitter account</h2>

<p>I want to backup my tweets (timeline), my retweets, my favorites, my direct messages and the list of people I am following.</p>

<p>Using the timeline subcommand I can retrieve all of my tweets. The following command will retrieve the 3000 most recent tweets for my username and save them as CSV in tweets.csv. You have to specify a number as the default behavior is to retrieve only the first 20.</p>

<figure class='code'><figcaption><span>Backing up tweets  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>t timeline @jphpsf --csv --number 3000 &gt; tweets.csv
</span></code></pre></td></tr></table></div></figure>


<p>The retweets do not seem to be included in the timeline. Here is the command to fetch them. It&#8217;s very similar to the previous command. Note that in this case, it does not require you to specify the username</p>

<figure class='code'><figcaption><span>Backing up retweets  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>t retweets --csv --number 3000 &gt; retweets.csv
</span></code></pre></td></tr></table></div></figure>


<p>The favorites command:</p>

<figure class='code'><figcaption><span>Backing up favorites  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>t favorites --csv --number 3000 &gt; favorites.csv
</span></code></pre></td></tr></table></div></figure>


<p>For the direct messages, there are actually two separate commands: one for received messages and one for sent.</p>

<figure class='code'><figcaption><span>Backing up direct messages  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>t direct_messages --csv --number 3000 &gt; dm_received.csv
</span><span class='line'>t direct_messages_sent --csv --number 3000 &gt; dm_sent.csv
</span></code></pre></td></tr></table></div></figure>


<p>Finally, for the list of people I follow:</p>

<figure class='code'><figcaption><span>Backing up followings  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>t followings --csv &gt; followings.csv
</span></code></pre></td></tr></table></div></figure>


<h2>Putting it all together</h2>

<p>Now that we have the basic commands needed for the backup task, we can put them all together in a shell script.</p>

<figure class='code'><figcaption><span>Simple Twitter backup script  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="c">#!/bin/sh</span>
</span><span class='line'><span class="c"># Simple Twitter backup script</span>
</span><span class='line'>
</span><span class='line'><span class="nb">export </span><span class="nv">DAY</span><span class="o">=</span><span class="sb">`</span>date +<span class="s1">&#39;%Y-%m-%d&#39;</span><span class="sb">`</span>
</span><span class='line'>
</span><span class='line'><span class="nb">echo</span> <span class="s2">&quot;Backing up tweets...&quot;</span>
</span><span class='line'>t timeline @jphpsf --csv --number 3000 &gt; tweets-<span class="nv">$DAY</span>.csv
</span><span class='line'><span class="nb">echo</span> <span class="s2">&quot;Backing up retweets...&quot;</span>
</span><span class='line'>t retweets --csv --number 3000 &gt; retweets-<span class="nv">$DAY</span>.csv
</span><span class='line'><span class="nb">echo</span> <span class="s2">&quot;Backing up favorites...&quot;</span>
</span><span class='line'>t favorites --csv --number 3000 &gt; favorites-<span class="nv">$DAY</span>.csv
</span><span class='line'><span class="nb">echo</span> <span class="s2">&quot;Backing up DM received...&quot;</span>
</span><span class='line'>t direct_messages --csv --number 3000 &gt; dm_received-<span class="nv">$DAY</span>.csv
</span><span class='line'><span class="nb">echo</span> <span class="s2">&quot;Backing up DM sent...&quot;</span>
</span><span class='line'>t direct_messages_sent --csv --number 3000 &gt; dm_sent-<span class="nv">$DAY</span>.csv
</span><span class='line'><span class="nb">echo</span> <span class="s2">&quot;Backing up followings...&quot;</span>
</span><span class='line'>t followings --csv &gt; followings-<span class="nv">$DAY</span>.csv
</span><span class='line'>
</span><span class='line'><span class="nb">echo</span> -e <span class="s2">&quot;\nBacked up the following:&quot;</span>
</span><span class='line'><span class="nb">echo</span> -e <span class="s2">&quot;- &quot;</span><span class="sb">`</span>wc -l tweets-<span class="nv">$DAY</span>.csv|cut -d<span class="s2">&quot; &quot;</span> -f 1<span class="sb">`</span><span class="s2">&quot; tweets&quot;</span>
</span><span class='line'><span class="nb">echo</span> -e <span class="s2">&quot;- &quot;</span><span class="sb">`</span>wc -l retweets-<span class="nv">$DAY</span>.csv|cut -d<span class="s2">&quot; &quot;</span> -f 1<span class="sb">`</span><span class="s2">&quot; retweets&quot;</span>
</span><span class='line'><span class="nb">echo</span> -e <span class="s2">&quot;- &quot;</span><span class="sb">`</span>wc -l favorites-<span class="nv">$DAY</span>.csv|cut -d<span class="s2">&quot; &quot;</span> -f 1<span class="sb">`</span><span class="s2">&quot; favorites&quot;</span>
</span><span class='line'><span class="nb">echo</span> -e <span class="s2">&quot;- &quot;</span><span class="sb">`</span>wc -l dm_received-<span class="nv">$DAY</span>.csv|cut -d<span class="s2">&quot; &quot;</span> -f 1<span class="sb">`</span><span class="s2">&quot; DM received&quot;</span>
</span><span class='line'><span class="nb">echo</span> -e <span class="s2">&quot;- &quot;</span><span class="sb">`</span>wc -l dm_sent-<span class="nv">$DAY</span>.csv|cut -d<span class="s2">&quot; &quot;</span> -f 1<span class="sb">`</span><span class="s2">&quot; DM sent&quot;</span>
</span><span class='line'><span class="nb">echo</span> -e <span class="s2">&quot;- &quot;</span><span class="sb">`</span>wc -l followings-<span class="nv">$DAY</span>.csv|cut -d<span class="s2">&quot; &quot;</span> -f 1<span class="sb">`</span><span class="s2">&quot; followings&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="nb">echo</span> -e <span class="s2">&quot;\nDone\n&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Wrapping up</h2>

<p>We now have a very easy way to backup a Twitter account from the CLI. As I am finishing up this post I realize it would be cool to have the backup feature available as a t command. I am thinking about submitting a pull request that would allow something like:</p>

<figure class='code'><figcaption><span>Backup command  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>t backup -o /path/to/backup
</span></code></pre></td></tr></table></div></figure>


<p>What do you think?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Front End Performance Case Study: GitHub]]></title>
    <link href="http://blog.jphpsf.com/2012/04/28/front-end-performance-case-study-github/"/>
    <updated>2012-04-28T15:36:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/04/28/front-end-performance-case-study-github</id>
    <content type="html"><![CDATA[<p>A couple weeks ago, someone in my Twitter timeline retweeted the following tweets from <a href="https://twitter.com/dom_monster">DOM Monster</a>:</p>

<blockquote><p>In HTML5, quotes around attribute values are optional. Which means, omit them. Smaller, faster, less clutter.</p><footer><strong>@dom_monster</strong> <cite><a href='https://twitter.com/#!/dom_monster/status/184649270144663552'>View Original Tweet</a></cite></footer></blockquote>




<blockquote><p>Here&#8217;s an example. This page from GitHub contains about 4,517 quote characters. Most of these can be omitted.<br/>https://github.com/rails/rails/commit/3756a3fdfe8d339a53bf347487342f93fd9e1edb</p><footer><strong>@dom_monster</strong> <cite><a href='https://twitter.com/#!/dom_monster/status/184652815615004672'>View Original Tweet</a></cite></footer></blockquote>


<p>This is a very specific and interesting performance optimization suggestion. I never really thought about it much or even looked at it to see what kind of performance impact, the omission of quote characters might have on a web page. However, after reading these tweets, I started to wonder: how well is GitHub doing on front end performance?</p>

<!-- more -->


<p><img src="http://blog.jphpsf.com/images/blog/2012-04-19-github-chrome-devtools.png" title="Chrome dev tools" ></p>

<p>A quick look at the Chrome dev tools with an empty cache for the GitHub url mentioned above showed a total load time of 5.43 seconds (onload at 3.33 and DOM ready at 1.33s) and an HTTP request count of 73 for a total of 1.36MB. That seemed a little high (for reference, the <a href="http://httparchive.org/trends.php">HTTP archive trends</a> reports an average of 84 requests for a total of about 1MB). As some of you who know me from the <a href="http://www.meetup.com/SF-Web-Performance-Group/">SF web performance meetup</a>, I really like dissecting web pages and figuring out what might make a given page slower.</p>

<p><em>Disclaimer: I do not work for GitHub and I have not contacted GitHub prior to writing this blog post. They might be aware of some of the issues and might be working on the front end performance of GitHub already. In any case, I would love to learn what they think of the following analysis.</em></p>

<h2>Webpagetest</h2>

<p>One of my favorite tools in my performance toolbox is <a href="http://www.webpagetest.org/">WebPagetest</a>. WebPagetest is a front end performance analysis tool that crawls a web page and generates a performance report card. It includes a lot of performance metrics, waterfall charts for first view and repeat view, page speed/yslow type of overview scores, &#8230; Also, it runs on a variety of real browsers (you can choose between IE, Chrome, Firefox, etc).</p>

<p>I ran the previous GitHub url and you can see the results using the following links:</p>

<ul>
<li><a href="http://www.webpagetest.org/result/120417_4P_3ZS5T/">Performance report with IE8</a></li>
<li><a href="http://www.webpagetest.org/result/120417_VT_3ZRY4/">Performance report with Firefox 11</a></li>
</ul>


<p>I tried to run the test with Chrome as well but encountered some issues with SSL in WebPagetest (I haven&#8217;t looked at the problem at this time and I am not sure if the issue is with Chrome or WebPagetest).</p>

<p>Let&#8217;s dive in!</p>

<h2>Javascript blocks rendering</h2>

<p><img src="http://blog.jphpsf.com/images/blog/2012-04-19-js-blocks-rendering.png" title="Javascript blocks rendering" ></p>

<h3>The problem</h3>

<p>According to WebPagetest, the rendering starts pretty late (at around 6 seconds in Firefox and 3 seconds in IE).</p>

<p>In most browsers, a javascript <code>&lt;script&gt;</code> tag will block rendering as the browser is loading and parsing the javascript code. The reason for this is fairly simple: a javascript file might include code that could modify the HTML document via a <code>document.write()</code> for instance (<a href="http://www.stevesouders.com/blog/2012/04/10/dont-docwrite-scripts/">boooh, don&#8217;t do that</a>) or any other DOM manipulation technique. As this might affect the rendered page, browsers usually stop any rendering activity while parsing and evaluating javascript.</p>

<p>If you look at the waterfalls, the rendering start on GitHub is delayed by 2 javascript files (from the file name it seems that one is the jQuery source code and the other is the actual GitHub javascript code).</p>

<h3>Solutions</h3>

<p>The 2 <code>&lt;script&gt;</code> tags are located at the top of the HTML document in the head. A performance best practice recommends to place the javascript <code>&lt;script&gt;</code> tags at the bottom of the HTML document (right before the <code>&lt;/body&gt;</code> closing tag) in order for the browser to start parsing the file as late as possible.</p>

<p>Another approach could be to use an asynchronous script loading technique (via a script loader such as <a href="http://labjs.com/">LABjs</a> or <a href="http://stevesouders.com/controljs/">ControlJS</a>; a custom solution as described <a href="http://mathiasbynens.be/notes/async-analytics-snippet">here</a> would work too).</p>

<p>This should allow the page rendering to start sooner.</p>

<h2>Reduce the size of downloads</h2>

<h3>The problem</h3>

<p>WebPagetest is accounting for 1,425KB of data transferred. That is quite a lot.</p>

<p>The worst offender in GitHub&#8217;s case seems to be the Gravatar 3rd party service. Gravatar is a popular service that allows to show a personal avatar for users of the interweb based on their email address. In the case of that GitHub page, Gravatar is loading 34 images for a total of 500KB. That is more than a third of the payload.</p>

<p>The second worst offender is the host called <code>camo.githubapp.com</code>. It seems to be serving 2 images in our example. At first, I was a bit puzzled about that host as I could not quite figure out why GitHub was serving directly 2 images worth 500KB (that is another third of our total payload) instead of using their CDN. After a bit of research I found the <a href="https://github.com/atmos/camo">Camo project</a>. GitHub is enforcing SSL for every page. When GitHub users write comments and insert funny cat pictures to illustrate their point, the said cat pictures might be served from a non SSL host. This will cause a nagging mixed content warning from the browser. Camo is basically an SSL image proxy that solves the issue. See more on <a href="https://github.com/blog/743-sidejack-prevention-phase-3-ssl-proxied-assets">this blog post</a>. Note that one of the 2 images is taking 7 seconds to load.</p>

<h3>Solutions</h3>

<p>We have about 1,000KB of images. A common practice is to compress and optimize images. There is a lot of tools out there for that purpose. WebPagetest performance review tab estimates that some of the images can be compressed and save about 40KB. Note that it does not include one of the largest images, which is a animated gif proxied through Camo. I sent the gif to Smush.it and it came back 50KB lighter. Bottom line: potential savings would be around 10%. Compressing images might not be easily achievable. I don&#8217;t think it would be a good idea to compress them on the fly (it would take some extra CPU resources to do that through Camo for instance). A better approach might be to have the image compressed at the source (in the case of Gravatar, when a user uploads an avatar). That would probably require a significant effort and I am not sure it&#8217;ll be worth the gain.</p>

<p>An alternative could be to implement asynchronous image loading. When you first load the GitHub page, none of that content is visible (all the images are below the fold). Knowing that, the HTML page could be generated with a placeholder for the image which would be loaded later on via javascript. The javascript could be listening for scroll events and monitor the visibility of the images in order to decide when to load them. Pamela Fox <a href="http://blog.pamelafox.org/2012/02/delayed-image-loading-on-long-pages.html">wrote about that</a> not long ago. You can also see the technique in action on Meetup&#8217;s website (for instance visit <a href="http://www.meetup.com/SF-Web-Performance-Group/events/45587992/">this meetup page</a> and look at the sidebar with the list of attendees while you scroll). Note that for users browsing with javascript disabled, they would miss the images. I am not sure that would be a deal breaker as I am assuming most of GitHub users have javascript turned on.</p>

<h2>Reducing the number of HTTP requests</h2>

<h3>The problem</h3>

<p>WebPagetest shows 71 HTTP requests. Trying to reduce those numbers is usually a good idea. There is always some overhead with HTTP request, so the less you do, the better it is.</p>

<p>I mentioned earlier the presence of 2 <code>&lt;script&gt;</code> tags in the head. I am wondering if there is a specific reason for them to not be combined together. The same goes for the CSS stylesheets (<code>github-xxxx.css</code> and <code>github2-xxxx.css</code>).</p>

<p>GitHub uses some sprites which is good and avoids some HTTP requests. I am wondering if GitHub would see any gain by combining sprites together (aka über-sprite ). I am looking at the various icons in the png files (in WebPagetest, under the waterfall, click the link &#8220;View all Images&#8221;). It looks <code>like mini_button_icons.png</code>, <code>repostat.png</code>, <code>public.png</code>, <code>file_modes.png</code>, <code>jump.png</code>, <code>diffstat.png</code>&#8230; could all be combined into one.</p>

<p>Some pages include several individual icons which could be sprited. For instance a <a href="https://github.com/jphpsf">github profile/dashboard page</a> has all the timeline icons in individual files (<code>pull_request.png</code>, <code>push.png</code>, <code>fork.png</code>, <code>issues_closed.png</code>, <code>issues_comment.png</code>, <code>watch_started.png</code>, etc).</p>

<h3>Solutions</h3>

<p>Well, I guess I spoiled that one. You&#8217;ve read it above. Combine all the things!s</p>

<h2>The double sometimes quadruple logo</h2>

<p><img src="http://blog.jphpsf.com/images/blog/2012-04-19-quadruple-logo-ie.png" title="IE performance waterfall" ></p>

<h3>The problem</h3>

<p>In the waterfall for Firefox, you can see 2 logos being loaded (the regular black version and the alternative hover version in blue: <code>logov7@4x.png</code> and <code>logov7@4x-hover.png</code>).</p>

<p>In the waterfall for IE, you&#8217;ll notice something interesting: GitHub is loading 4 logos! It is loading a smaller version (both regular and hover) as well as a higher resolution one (I am assuming given the 4x in the filename that is intended for retina displays). It seems to be a bug in the code. The smaller logos are enclosed in a conditional HTML comment targeted at IE. The conditional has an if branch but not a else branch. So when the browser is not IE, the if branch is ignored and the high resolution logos are used. But when the browser is IE, the if branch is executed loading the smaller logos. Then the high resolution logos are loaded as well. I am actually wondering why does IE need the smaller logos? Are the higher resolution logos not suitable for IE?</p>

<h3>Solutions</h3>

<p>The change between regular and hover is done with a CSS <code>:hover</code> rule that tweaks the logos opacity to 0 or a 100 to hide or show the desired version. The two version of the logos could probably be sprited together and used as CSS background image instead of inline <code>&lt;img&gt;</code> tags. Another approach: always load the regular black logo and lazy load (or preload) the hover logo via javascript. The hover effect could be achieved via javascript as well.</p>

<p>For the issue specific with the IE conditional comment, maybe look at removing the conditional comment all together.</p>

<h2>Caching issue with IE over SSL?</h2>

<p><img src="http://blog.jphpsf.com/images/blog/2012-04-19-cache-repeat-views.png" title="Cache repeat views" ></p>

<h3>The problem</h3>

<p>With Firefox, WebPagetest summary shows 82 requests and 1,420KB for the first view. The repeat view seems to be using caching and performs only 12 requests for a total of 65KB. Great!</p>

<p>With IE however, WebPagetest shows that a repeat view executes 45 requests for a total of 1,329KB (first view was 71 for 1,425KB). Looking at the various requests details (click on a filename in the waterfall), I can see that a far future expire header is set as well as the Cache-Control header for max-age. According to <a href="https://blogs.msdn.com/b/ieinternals/archive/2010/04/21/internet-explorer-may-bypass-cache-for-cross-domain-https-content.aspx">this page on MSDN</a>, this might be a known issue with IE (or more accurately with WinINET)</p>

<h2>Epic pull requests can be big</h2>

<p><img src="http://blog.jphpsf.com/images/blog/2012-04-19-epic-pull-request.png" title="Chrome dev tools" ></p>

<h3>The problem</h3>

<p>Some pull requests on GitHub can affect a lot of files and generate a really long diff. Take <a href="https://github.com/emberjs/ember.js/pull/248">this one</a> for instance. Look at the diff. It generates an HTML document of 18.48MB (1.05MB gzipped). It takes 10 seconds in Chrome before getting the first byte of that page.</p>

<h3>Solution</h3>

<p>This is a tough one. My first thought would be to look at asynchronous requests and reusing the viewport visibility trick mentioned above. Generate the diff skeleton without the diff content for each file. Then, use <a href="https://github.com/defunkt/jquery-pjax">pjax</a> to load the diff of each file. pjax could be triggered in 3 cases: First, after the initial page load, the diff of each file could be loaded one by one. Second, if a user clicks a specific file anchor at the top, then immediately load that diff via pjax. Third, as the user scrolls up or down the page, maybe some javascript code could detect which diff is visible and load it via pjax?</p>

<h2>Closing words: A note about performance metrics</h2>

<p>You know the saying &#8220;Premature optimization is the root of all evil&#8221;. Related: don&#8217;t optimize without measuring first.</p>

<p>Measure. Optimize. Monitor. Rinse &amp; Repeat.</p>

<p>The above analysis is looking at a very specific page but it was chosen fairly randomly from a tweet.</p>

<p>A better and more proper approach would be to setup first some kind of real user monitoring (such as <a href="https://github.com/yahoo/boomerang">Boomerang</a>, <a href="http://newrelic.com/rum">New Relic</a> or the <a href="http://www.torbit.com/insight/">new Torbit Insight</a>) and find which pages are the worst offenders. Then start optimizing. After that, monitor the performance metrics and see if the optimization works as expected and if metrics are improving.</p>

<p>Monitoring is one thing, but using web analytics in addition to performance metrics is also important to help drive optimizations decision. For instance, let&#8217;s imagine that GitHub&#8217;s visitors using IE represents less than 1% of all GitHub&#8217;s visitors. In this case, fixing the issues specific to IE (such as double logo or SSL caching) might not be the most important optimization. Now, let&#8217;s imagine that GitHub&#8217;s visitors are in 99% of the case repeat users. At which point, they might be visiting GitHub with a primed cache (which would include assets such as avatars and icon images).</p>

<p>In the end, is GitHub slow? I actually don&#8217;t think so. When I use GitHub, I don&#8217;t have a perception of slowness or lag. Perceived performance is an important concept to consider (by opposite to the hard numbers discussed above, which tend to say &#8220;GitHub is slow&#8221;). Yet, I am wondering what would be the performance business case for GitHub? Even if GitHub does not feel slow, faster is always better. In the case of e-commerce websites or search engines, there is a direct correlation between performance and revenue (Amazon, Bing, Google, Walmart, they all shared numbers over the past few years). In the case of GitHub, what is the performance business pitch? Would a faster GitHub translate to more users? Would that then drive more revenue?</p>

<p><em>Thanks to <a href="https://twitter.com/#!/ryanbigg">Ryan Bigg</a> for reviewing this post and providing great feedback.</em></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Hello world]]></title>
    <link href="http://blog.jphpsf.com/2012/04/16/hello-world/"/>
    <updated>2012-04-16T18:22:00-07:00</updated>
    <id>http://blog.jphpsf.com/2012/04/16/hello-world</id>
    <content type="html"><![CDATA[<p>In December 2011, I wrote a <a href="http://calendar.perfplanet.com/2011/performance-testing-with-selenium-and-javascript/">guest post</a> on the <a href="http://calendar.perfplanet.com/">Performance Calendar blog</a> (a project from <a href="http://twitter.com/#!/stoyanstefanov">Stoyan Stefanov</a>). While I&#8217;ve been using the Internet for ages and reading blogs for a long time*, I actually never owned my own blog. The Performance Calendar article was a premiere for me.</p>

<p>This was a very interesting and enriching experience. I never thought I would have enjoyed writing so much. Not only that, I also really liked the preparation phase (researching and gathering the information I needed for my post). Finally, I liked getting some feedback after publication.</p>

<p>Earlier this year, my wife and I were chatting about our year 2011, looking back at it and discussing what we wanted to accomplish in 2012. One item on my list was: starting a blog. I enjoyed writing a guest post enough that I wanted to make it a recurring habit. Better get going!</p>

<p>So here we are, April 2012, introducing my blog &#8220;Tech talk with a french twist&#8221;. You can expect to read about web development in general and web performance in particular. I am also thinking to post book reviews (both technical and non-technical). Occasionaly, I may talk about gadgets or life in general.</p>

<p>Welcome to my blog, I hope you&#8217;ll enjoy the reading.</p>

<p><em>* If I recall properly, I have been using Intenet since 1999 and reading blogs since 2004/2005.</em></p>
]]></content>
  </entry>
  
</feed>
