Slide 1

Slide 1 text

re-evaluating front-end performance best practices

Slide 2

Slide 2 text

@bentlegen

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

http://getsentry.com

Slide 5

Slide 5 text

car·go cult

Slide 6

Slide 6 text

ccccccejlfevnigejevgjkglrc hibhjrtcjlngnfblfb cargo cult science

Slide 7

Slide 7 text

cargo cult web performance

Slide 8

Slide 8 text

how did we get here?

Slide 9

Slide 9 text

deprecated books 2007 2009 2010

Slide 10

Slide 10 text

stackoverflow answers

Slide 11

Slide 11 text

analysis tools

Slide 12

Slide 12 text

analysis tools 2014 2013

Slide 13

Slide 13 text

practices on live websites

Slide 14

Slide 14 text

conference talks

Slide 15

Slide 15 text

today’s agenda • hostname sharding • for-loop array length caching • dynamic script insertion

Slide 16

Slide 16 text

hostname sharding

Slide 17

Slide 17 text

in the beginning (HTTP 1.0)

Slide 18

Slide 18 text

with more connections 2 4 8 www www www

Slide 19

Slide 19 text

with hostname sharding 2 2 2 www www1, www2 www1 www2 www3 www4

Slide 20

Slide 20 text

still common Website # Static Hosts plus.google.com 4 tumblr.com 4 alibaba.com 4 theverge.com 4 ebay.com 6 businessinsider.com 6 netflix.com 11!

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

not a big deal anymore

Slide 23

Slide 23 text

browser connections/origin Browser # HTTP / origin Chrome 42 6 Firefox 37 8 Safari 7 6 IE 8, 9 6 IE 10 8 IE 11 13 bit.ly/rprf-bscope

Slide 24

Slide 24 text

chrome caps parallel image requests at 10 anyways bit.ly/rprf-bscope

Slide 25

Slide 25 text

rise of https stalled/ proxy negotiation dns lookup connection + tls/ssl time-to-
 first-byte download tls/ssl handshake

Slide 26

Slide 26 text

and http/2 will make all this irrelevant anyways

Slide 27

Slide 27 text

“2 domains for non- [HTTP2] modern browsers” – Souders in 2013 bit.ly/rprf-2domains

Slide 28

Slide 28 text

etsy case study • 4 image domains → 2 • 50-80 ms faster for image heavy pages • 30-50 ms faster overall • up to 500ms faster on mobile bit.ly/rprf-etsy

Slide 29

Slide 29 text

the web’s moving on Website # Static Hosts netflix.com* 1 nytimes.com 1 youtube.com 2 twitter.com 2 facebook.com 2 pinterest.com 2 bbc.co.uk 2 etsy.com 3

Slide 30

Slide 30 text

looping

Slide 31

Slide 31 text

specifically array length caching in for loops

Slide 32

Slide 32 text

for (var i = 0, len = arr.length; i < len; i++) { // do stuff } for (var i = 0; i < arr.length; i++) { // do stuff } vs

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

does it still hold?

Slide 37

Slide 37 text

cache vs no cache Chrome 42 Firefox 37 Safari 7 IE9+ IE8 ops/second (normalized), bigger is better cache no cache 78%

Slide 38

Slide 38 text

V8 (and other browsers) recognize this pattern bit.ly/rprf-v8opt

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

uncached version

Slide 41

Slide 41 text

cached version

Slide 42

Slide 42 text

“we should start assuming that our code is optimized” - Vyacheslav Egorov, V8 bit.ly/rprf-v8opt

Slide 43

Slide 43 text

if you can trivially optimize it, the browser (probably) can too

Slide 44

Slide 44 text

mobile disagrees, a little Chrome 41
 (Android 5.1) Firefox 34 
 (Android 5.1) Safari
 (iOS 8) ops / second (normalized), bigger is better cache no cache 95%

Slide 45

Slide 45 text

new in es6 for (x of arr) { … }

Slide 46

Slide 46 text

dynamic script insertion

Slide 47

Slide 47 text

blocking scripts (2009) 
 vendor.js 
 finishes app.js starts img, css, iframe

Slide 48

Slide 48 text

dynamic script insertion var script = document.createElement('script'); script.src = '/app.js'; document.getElementsByTagName('head')[0] .appendChild(script); all load in parallel

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

you’ve used this • analytics: GA, Mixpanel, Chartbeat, Wordpress • widgets: Disqus, Facebook Comments • JS module loaders: RequireJS, LabJS • script managers: Google Tag Manager, Segment

Slide 52

Slide 52 text

small problem: CSS Object Model

Slide 53

Slide 53 text

CSS Object Model (CCSOM) window.getComputedStyle(document.body).margin; can’t execute until CSS ready

Slide 54

Slide 54 text

CSSOM + dynamic script insertion var script = document.createElement('script'); script.src = '/app.js'; document.getElementsByTagName('head')[0] .appendChild(script); can’t execute until CSS ready

Slide 55

Slide 55 text

dynamic script insertion scripts execute inline scripts can’t execute until CSSOM ready; downloading is delayed

Slide 56

Slide 56 text

blocking 2nd script downloads after 1st executes 1st script preloaded 1st script executes

Slide 57

Slide 57 text

blocking with Chrome 1st and 2nd script preloaded 1st and 2nd script execute (blocked for CSSOM)

Slide 58

Slide 58 text

2014

Slide 59

Slide 59 text

3rd option: async attribute

Slide 60

Slide 60 text

ideal: async attribute scripts execute before CSS finished all 3 resources download in parallel

Slide 61

Slide 61 text

we should probably start using async

Slide 62

Slide 62 text

new: GA + async attr

Slide 63

Slide 63 text

closing thoughts

Slide 64

Slide 64 text

don’t always believe what you read on the internet

Slide 65

Slide 65 text

benchmark your own stuff

Slide 66

Slide 66 text

benchmark your own stuff every few years

Slide 67

Slide 67 text

always bet on browsers (and JS engines)

Slide 68

Slide 68 text

thanks

Slide 69

Slide 69 text

acknowledgements • performance research: Steve Souders, Ilya Grigorik, Guy Podjarny, Vyacheslav Egorov, Jonathan Klein, Paul Irish, Nicholas Zakas • photos: Christian Junker, André Hofmeister, “My aim is true” • me: Ben Vinegar (@bentlegen) • Sentry plug: http://getsentry.com