Perfecting

eCommerce
Frontend

(for various loose definitions of 'perfecting')

Denis IRL


@jumph4x
elsewhere*




* - twitter, instagram, github, flickr

I like quick things.

   ❤






    

                  

     


Being faster than others is great






$$$

YOU                        COMPETITOR












WOW. SUCH SPEED.
MUCH PLEASANT.
A+, BUY AGAIN.


-Happy Customer


But it usually involves
some work to get there.



It's totally worth it.
I will show you how.

This performance work thing is (almost) how I met FCP








Final Cut Pro

❤ Foreign Car Parts 

We've been together for 4 years*

4 tech job years
=

20 normal years

I'm barely over 20, so I've basically been working for FCP my whole life

Getting the most
from your frontend


- Getting the most

 + Performance
from your frontend



~10s iFrames

(lulz)

Steve Souders



"80-90% of the end-user response
time is spent on the frontend. 
Start there."






http://www.stevesouders.com/blog/2012/02/10/the-performance-golden-rule/







http://www.stevesouders.com/blog/2012/02/10/the-performance-golden-rule/



Google: 99/100


Page load path explorer
Draw: 350ms
Done: 740ms

Let's briefly
talk about CSS


 Overqualification and Specificity

body table tr td .even #my-element

Key Selector

#my-element body table tr td 

(Browsers parse CSS selectors RTL!)

CSS Selector Performance

Superb

IDs:                   #my-element
Classes:               .my-element

Adequate*

Tags:                             element
Siblings:                  elements + el
Children:                  element > el
Descendants:               element el



* ∞ ❤ 4 tenderlove

Slow

Universal:                                *
Attribute:           [attrb="string"]
Pseudo:                     nth-child()
Regexp?!           [attrib^='omfg']


CSS Explain


https://github.com/josh/css-explain

ProTip: Check SASS compiler output


Nesting + Extend in Sass


CSS Wisdom

Shallow reusable utility-oriented classes

Experimental CSS Wisdom

In-lining essentials into head's style,
async loading the rest

Let's talk about
asset delivery

OG Responsive: Time to start render


  WOW ^

http://www.stevesouders.com/blog/2013/04/26/i/e to begin render

<html>

<head>

    <link rel='stylesheet' …

    <!-- ALL ELSE -->

    <skript async='async' />

</head>

Caveat:

No JS in body can

use external scripts as a dep

Common Pattern

External JS ref right before
closing body tag, not as fast

HeadJS

Nicer version of HTML5's

async JS loading


~200 http requests :(















http://ask.slashdot.org/story/12/03/06/175223/ask-slashdot-what-is-an-acceptable-broadband-latency

Asset Pipeline is awesome

(Hi haters)

// Sass/Scss/CSS
@import "variables"
@import "header"


*/ JS/Coffee /*
//= require ./one
//= require ./two

CSS Sprites

Data URI Scheme



.icon
- image-url(stuffs.png)
+ asset-data-url(stuffs.png)



http://en.wikipedia.org/wiki/Data_URI_scheme

Asset Domains


http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/

~1000ms blocking :(

$$$ ProTip

# config/environments/production.rb
config.asset_host = Proc.new { |*args| 
    source, request = args
    images = source && source.match(/products/)
    no_ssl = request && !request.ssl?
 
    if no_ssl && images
        "//assets#{rand(5)}.fcpstores.com" 
    else 
        "//123456abcde.cloudfront.net" 
    end 
}

Parallelism!

HTTP Streaming

def action
    -@collection = Objekt.gimme.all
    respond_to do |format|
        -format.html
        +format.html{ render :action, :streaming => true }
    end
end
 
+ helper_method :collection
+ def collection
+
@collection ||= Objekt.gimme.all
+ end

Why stream?


                   ^ Time-to-first-byte


Good News, Everyone!

Just tune the first few frames

of your conversion funnel!


Browser Hints


<link rel="dns-prefetch"
href="//mysite.cloudfront.com">

<link rel="prefetch" href="/next-step.html">
<link rel="prefetch" href="large-image.png">

<link rel="subresource" href="end-of-
document.js
">

It gets even better though


Abstract

Servers can initiate stream and send sub-resources the client doesn't even know it will need

SPDY Usage

Google, Twitter, Facebook all think its the bees knees

Support


Google Chrome/Chromium
Firefox supports 11(off), 13(on) 
Opera 12.10+
Internet Explorer 11+*


http://en.wikipedia.org/wiki/SPDY

Let's talk about
JavaScript

Median Pageload


http://www.stevesouders.com/blog/2012/01/13/javascript-performance/

No more JS


Yeah, but...


Not ideal


Yeah, but, but!


Performance

Due to statefulness,

pre-fetched templates

and async-requests

Diminishing ROI

Due to Fast Enough (TM) and

assumptions about engagement*

To convince the CEO...


...I went to Analytics

Oops...


Oh, and one more thing:

SEO

2x effort
or
PhantomJS

Speaking of which...

Let's talk about SEO

You're already doing it!



http://googlewebmastercentral.blogspot.com/2010/04/using-site-speed-in-web-search-ranking.html

Be firm with your SEO firm

Don't pay for speculation,
hold informed technical calls,
read Webmaster Academy







http://support.google.com/webmasters/bin/static.py?hl=en&page=checklist.cs&tab=1095542


CanonicalRails


"Avoid harm by
neglecting canonicalization

[...], here is a [library] to start
on it..."


https://github.com/jumph4x/canonical-rails

Authoritative version

http://mystore.com/shoes
http://mystore.com/shoes/
http://www.mystore.com/shoes
http://mystore.com/products?taxon_permalink=shoes
http://mystore.com/products?sort=price
http://mystore.com/products?doesnt_exist=true
http://mystore.com/products?keyword_attack=viagra

http://support.google.com/webmasters/bin/answer.py?hl=en&answer=139394

rel='canonical'

# config/initializers/canonical_rails.rb
CanonicalRails.setup do |config|
    config.host = 'www.mywebstore.com'
    config.collection_actions = [ :index, :available ]
    config.whitelisted_parameters = [ :country ]
end


<html>
<head>
<%= canonical_tag -%>
</head>

Semantic Markup


http://schema.org/docs/schemas.html

<div itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating" >
    <span itemprop="ratingValue" >87</span>
    out of <span itemprop="bestRating">100</span>
    by <span itemprop="ratingCount">24</span>
    user 
ratings
</div>

Test your work



Made with Slides.com