AMP tries to fix the web - What can we learn from it

22725c2d3eb331146549bf0d5d3c050c?s=47 stefan judis
November 12, 2016

AMP tries to fix the web - What can we learn from it

22725c2d3eb331146549bf0d5d3c050c?s=128

stefan judis

November 12, 2016
Tweet

Transcript

  1. AMP tries to fix the web What can we learn

    from it? (◠‿◠✿) @stefanjudis
  2. Stefan Judis Frontend Developer, Occasional Teacher, Meetup Organizer ❤ Open

    Source, Performance and Accessibility ❤ @stefanjudis
  3. PERF TOOLING TODAY

  4. OFF WITH ITS HEAD! Contentful the headless CMS...

  5. CONTENT SOCKS

  6. 6 the here and now

  7. SLOW LOADING PAGES 110 requests & 956KB Page size

  8. GOOGLE CONTINUES TO INFLUENCE SEARCH RESULTS

  9. https://www.youtube.com/watch?v=3tUmh8OfAiY

  10. INTERVENTIONS https://github.com/WICG/interventions

  11. WHAT'S DISCUSSED IN THERE? Stop dummy history fast-forwarding Ignore clicks

    on iframes that have moved in the last 200ms Defer image loading until they are viewable Defer iframe loading until they are viewable Lower loading priority of cross-origin iframe
  12. DOCUMENT.WRITE ON SLOW CONNECTIONS MAY BE BLOCKED IN FUTURE https://github.com/WICG/interventions/issues/17

  13. https://github.com/h5bp/html5-boilerplate/blob/master/src/index.html#L26 WATCH OUT! YOU MIGHT HAVE IT IN YOUR STACK!

  14. SCROLL-ANCHORING https://github.com/WICG/interventions/blob/master/scroll-anchoring/explainer.md

  15. 15 The web is "broken"

  16. None
  17. “For many, reading on the mobile web is a slow,

    clunky and frustrating experience - but it doesn’t have to be that way.” Accelerated Mobile Pages Project
  18. https://search.googleblog.com/2016/09/search-results-are-officially-ampd.html SEARCH RESULTS ARE NOW OFFICIALLY AMP'D

  19. HOW CAN IT BE SO FAST?

  20. THREE MAIN PARTS AMP HTML AMP JS Google AMP Cache

  21. <!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>Hello

    World</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="amphtml" href="amp/hello-world.html"> <link rel="stylesheet" href="css/main.css"> </head> <body> <h1>Hello World!</h1> </body> </html> GETTING STARTED HTML file
  22. <!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>Hello

    World</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="amphtml" href="amp/hello-world.html"> <link rel="stylesheet" href="css/main.css"> </head> <body> <h1>Hello World!</h1> </body> </html> GETTING STARTED HTML file
  23. GETTING STARTED double the maintenance AMP HTML HTML

  24. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> GETTING STARTED AMP file
  25. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> GETTING STARTED AMP file
  26. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> GETTING STARTED AMP file
  27. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> GETTING STARTED AMP file
  28. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> GETTING STARTED AMP file
  29. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> GETTING STARTED AMP file
  30. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> GETTING STARTED AMP file
  31. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> GETTING STARTED AMP file
  32. GETTING STARTED AMP file HTML TAGS CAN BE USED UNCHANGED

    IN AMP HTML EXCEPT IMG, SCRIPT, VIDEO, IFRAME, ... https://www.ampproject.org/docs/reference/spec
  33. THREE BUILTINS AMP-IMG AMP-PIXEL AMP-VIDEO <amp-img src="/img/amp.jpg" width="1080" height="610" layout="responsive"

    alt="an image" ></amp-img> <amp-pixel src="https://foo.com/px?123" ></amp-pixel> <amp-video width="400" height="300" src="https://yourhost.com/myvideo.mp4" poster="poster.jpg"> <div fallback> <p>No support for HTML5</p> </div> <source type="video/mp4" src="foo.mp4"> <source type="video/webm" src="foo.webm"> </amp-video>
  34. CUSTOM MARKUP IF YOU NEED MORE ELEMENTS <script async custom-element="amp-sidebar"

    src="https://cdn.ampproject.org/v0/amp-sidebar-0.1.js"></script> <script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
  35. THREE BUILTINS AMP-IMG AMP-PIXEL AMP-VIDEO <amp-img src="/img/amp.jpg" width="1080" height="610" layout="responsive"

    alt="an image" ></amp-img> <amp-pixel src="https://foo.com/px?123" ></amp-pixel> <amp-video width="400" height="300" src="https://yourhost.com/myvideo.mp4" poster="poster.jpg"> <div fallback> <p>No support for HTML5</p> </div> <source type="video/mp4" src="foo.mp4"> <source type="video/webm" src="foo.webm"> </amp-video>
  36. CUSTOM MARKUP // src/custom-element.js export function registerElement(win, name, implementationClass) {

    win.document.registerElement(name, { prototype: createAmpElementProto(win, name), }); } https://github.com/ampproject/amphtml/blob/master/src/custom-element.js#L1429-L1435 // builtins/amp-img.js export function installImg(win) { registerElement(win, 'amp-img', AmpImg); } https://github.com/ampproject/amphtml/blob/master/builtins/amp-img.js#L145-L147
  37. CUSTOM ELEMENTS http://w3c.github.io/webcomponents/spec/custom/

  38. Custom elements v0 Custom elements v1

  39. POLYFILL https://github.com/WebReflection/document-register-element WebReflection/document-register-element

  40. CUSTOM MARKUP Custom Elements v0 Custom Elements v1 <hey-there></hey-there> var

    MyElement = document.registerElement( 'hey-there', { prototype: Object.create( HTMLElement.prototype, { createdCallback: { value: function() { console.log('registered'); }}, attachedCallback: { value: function() { console.log('live on DOM :-)'); }}, detachedCallback: { value: function() { console.log('leaving the DOM :-('); }}, attributeChangedCallback: {value: function( name, previousValue, value ) {}} }) } ); class HeyThere extends HTMLElement { constructor() { super(); console.log('registered'); } connectedCallback() { console.log('live on DOM :-)'); } disconnectedCallback() { console.log('leaving the DOM :-('); } attributeChangedCallback() {} } customElements.define('hey-there', HeyThere); http://codepen.io/stefanjudis/pen/ZpZzmY http://codepen.io/stefanjudis/pen/dpvyok
  41. CUSTOM MARKUP LIFECYCLE HTML ELEMENT createdCallback attachedCallback

  42. CUSTOM MARKUP upgrade firstAttachedCallback buildCallback layoutCallback viewportCallback LIFECYCLE AMP ELEMENT

    createdCallback LIFECYCLE HTML ELEMENT createdCallback attachedCallback
  43. CUSTOM MARKUP /** @override */ buildCallback() { /** @private @const

    {boolean} */ this.isPrerenderAllowed_ = !this.element.hasAttribute('noprerender'); } /** @override */ layoutCallback() { this.initialize_(); let promise = this.updateImageSrc_(); // We only allow to fallback on error on the initial layoutCallback // or else this would be pretty expensive. if (this.allowImgLoadFallback_) { promise = promise.catch(e => { this.onImgLoadingError_(); throw e; }); this.allowImgLoadFallback_ = false; } return promise; } https://github.com/ampproject/amphtml/blob/master/builtins/amp-img.js
  44. HOW TO SPEED UP? Control everything

  45. 45 resource priority

  46. RESOURCE PRIORITY without preloader http://yoavweiss.github.io/preloader-velocity-nyc-talk

  47. RESOURCE PRIORITY with preloader http://yoavweiss.github.io/preloader-velocity-nyc-talk

  48. <img src="https://tracking.com/~text?tracking&txt=14&w=1&h=1"> <img src="https://tracking.com/~text?tracking&txt=15&w=1&h=1"> <!-- a lot more things here

    --> <img src="https://tracking.com/~text?tracking&txt=16&w=1&h=1"> <img src="https://tracking.com/~text?tracking&txt=17&w=1&h=1"> <!-- a lot more things here --> <img src="https://tracking.com/~text?tracking&txt=18&w=1&h=1"> <!-- a lot more things here --> <img height="335" width="900" src="http://some/path/image.jpg"> RESOURCE PRIORITY where the preloader fails
  49. RESOURCE PRIORITY where the preloader fails

  50. RESOURCE PRIORITY where the preloader fails

  51. <amp-pixel src="https://tracking.com/~text?tracking&txt=14&w=1&h=1"></amp-pixel> <amp-pixel src="https://tracking.com/~text?tracking&txt=15&w=1&h=1"></amp-pixel> <amp-pixel src="https://tracking.com/~text?tracking&txt=16&w=1&h=1"></amp-pixel> <amp-pixel src="https://tracking.com/~text?tracking&txt=17&w=1&h=1"></amp-pixel> <amp-pixel src="https://tracking.com/~text?tracking&txt=18&w=1&h=1"></amp-pixel>

    <amp-img layout="responsive" height="335" width="900" src="http://some/path/image.jpg"></amp-img> RESOURCE PRIORITY the AMP runtime
  52. RESOURCE PRIORITY the AMP runtime

  53. NON CRITICAL RESOURCES GET OUT OF THE WAY RESOURCE PRIORITY

    the AMP runtime
  54. RESOURCE PRIORITY the AMP runtime class AmpPixel extends BaseElement {

    getPriority() { // Loads after other content. return 1; } }
  55. 55 reflow management

  56. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> REFLOW MANAGEMENT
  57. <!doctype html> <html ⚡> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate> body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } </style> <noscript> <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none}</style> </noscript> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html> REFLOW MANAGEMENT
  58. REFLOW MANAGEMENT <body class="amp-mode-touch" style="opacity: 1; visibility: visible; animation: none;"

    >
  59. REFLOW MANAGEMENT

  60. REFLOW MANAGEMENT EXTERNALLY FETCHED RESOURCES MUST BE GIVEN AN EXPLICIT

    SIZE amp-img { background-color: grey; } <amp-img src="https://chameleon-catching-bubbles.jpg" width="1080" height="610" layout="responsive" alt="A chameleon catching bubbles"></amp-img>
  61. REFLOW MANAGEMENT NO REFLOWS!

  62. <amp-img src="https://chameleon-catching-bubbles.jpg" width="1080" height="610" layout="responsive" alt="A chameleon catching bubbles"> <i-amp-sizer

    style="display: block; padding-top: 56.4815%;"></i-amp-sizer> <img alt="A chameleon catching bubbles" class="-amp-fill-content" src="https://chameleon-catching-bubbles.jpg"> </amp-img> REFLOW MANAGEMENT https://www.smashingmagazine.com/2016/08/ways-to-reduce-content-shifting-on-page-load/ AVOID REFLOWS TODAY
  63. <amp-img src="https://chameleon-catching-bubbles.jpg" width="1080" height="610" layout="responsive" alt="A chameleon catching bubbles"> <i-amp-sizer

    style="display: block; padding-top: 56.4815%;"></i-amp-sizer> <img alt="A chameleon catching bubbles" class="-amp-fill-content" src="https://chameleon-catching-bubbles.jpg"> </amp-img> REFLOW MANAGEMENT https://www.smashingmagazine.com/2016/08/ways-to-reduce-content-shifting-on-page-load/ AVOID REFLOWS TODAY
  64. HOW TO SPEED UP? Enforce best practices

  65. 65 inline css

  66. INLINE CSS https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css AVOID RENDER BLOCKING CSS

  67. INLINE CSS <style amp-custom> body { color: #404040; font-family: Helmet,Freesans,Helvetica,Arial,sans-serif;

    font-size: 14px; } .container { padding: 0 8px; } @media (min-width: 480px) { .container { padding: 0 16px; } } // // more things here // </style>
  68. 68 custom fonts

  69. CUSTOM FONTS @font-face { font-family: 'BioRhyme'; font-style: normal; font-weight: 400;

    src: local('BioRhyme'), local('BioRhyme-Regular'), url(https://some.font.url/font.woff2) format('woff2'); } "traditional" approach .custom-font-bold { font-family: 'BioRhyme', Arial, sans-serif; font-weight: 700; font-style: normal; } .custom-font { font-family: 'BioRhyme', Arial, sans-serif; font-weight: 400; font-style: normal; } @font-face { font-family: 'BioRhyme'; font-style: normal; font-weight: 700; src: local('BioRhyme Bold'), local('BioRhyme-Bold'), url(https://some.font.url/font-bold.woff2) format('woff2'); }
  70. "traditional" approach CUSTOM FONTS

  71. "traditional" approach CUSTOM FONTS FOIT!

  72. "new" approach <amp-font layout="nodisplay" font-family="BioRhyme" font-weight="400" on-load-add-class="bio-rhyme-font-loaded"></amp-font> CUSTOM FONTS https://ampbyexample.com/components/amp-font/

    <amp-font layout="nodisplay" font-family="BioRhyme" font-weight="700" on-load-add-class="bio-rhyme-bold-font-loaded"></amp-font>
  73. "new" approach .custom-font { line-height: 1.3; letter-spacing: 2.675px; } .bio-rhyme-font-loaded

    .custom-font { font-family: 'BioRhyme', Arial, sans-serif; font-weight: 400; font-style: normal; letter-spacing: 0; line-height: 1.25; } CUSTOM FONTS https://ampbyexample.com/components/amp-font/
  74. "new" approach CUSTOM FONTS fixed-

  75. "new" approach CUSTOM FONTS fixed-

  76. "new" approach CUSTOM FONTS fixed- FOUT!

  77. "new" approach if (this.canUseNativeApis_()) { // Check if font already

    exists. if (this.document_.fonts.check(fontString)) { resolve(); } else { // Load font with native api if supported. this.document_.fonts.load(fontString).then(() => { // Workaround for chrome bug // https://bugs.chromium.org/p/chromium/issues/detail?id=347460 return this.document_.fonts.load(fontString); }).then(() => { if (this.document_.fonts.check(fontString)) { resolve(); } else { reject(new Error('Font could not be loaded,' + ' probably due to incorrect @font-face.')); } }).catch(reject); } } https://github.com/ampproject/amphtml/blob/master/extensions/amp-font/0.1/fontloader.js#L112-L131 CUSTOM FONTS
  78. "new" approach if (this.canUseNativeApis_()) { // Check if font already

    exists. if (this.document_.fonts.check(fontString)) { resolve(); } else { // Load font with native api if supported. this.document_.fonts.load(fontString).then(() => { // Workaround for chrome bug // https://bugs.chromium.org/p/chromium/issues/detail?id=347460 return this.document_.fonts.load(fontString); }).then(() => { if (this.document_.fonts.check(fontString)) { resolve(); } else { reject(new Error('Font could not be loaded,' + ' probably due to incorrect @font-face.')); } }).catch(reject); } } https://github.com/ampproject/amphtml/blob/master/extensions/amp-font/0.1/fontloader.js#L112-L131 CUSTOM FONTS
  79. CSS FONT LOADING https://drafts.csswg.org/css-font-loading/

  80. "new" approach CUSTOM FONTS CSS FONT LOADING https://github.com/zachleat/fontfaceonload POLYFILL

  81. "new" approach CUSTOM FONTS @font-face { font-family: 'BioRhyme'; font-display: swap;

    src: local('BioRhyme'), local('BioRhyme-Regular'), url(https://some.font.url/font.woff2) format('woff2'); } https://developers.google.com/web/updates/2016/02/font-display
  82. "new" approach CUSTOM FONTS @font-face { font-family: 'BioRhyme'; font-display: swap;

    src: local('BioRhyme'), local('BioRhyme-Regular'), url(https://some.font.url/font.woff2) format('woff2'); } https://developers.google.com/web/updates/2016/02/font-display
  83. "new" approach CUSTOM FONTS CSS FONT-RENDERING CONTROLS font-display

  84. FONT LOADING STRATEGY Rethink the usage of fonts! 01 Avoid

    FOIT! 02 03 Go for FOUT and adjust fallback fonts! https://www.zachleat.com/web/comprehensive-webfonts/
  85. 85 GPU-accelerated animations

  86. GPU-ACCELERATED ANIMATIONS .sidebar { position: fixed; left: -300px; top: 0;

    bottom: 0; width: 300px; transition: left .5s ease-in-out; } .sidebar.is-open { left: 0; }
  87. GPU-ACCELERATED ANIMATIONS

  88. NOT 60 FRAMES PER SECOND ANYMORE

  89. <amp-sidebar id='sidebar1' layout='nodisplay'> <ul> <li> Nav item 1</li> <li> Nav

    item 2</li> <li> Nav item 3</li> </ul> </amp-sidebar> <button class="hamburger" on='tap:sidebar1.toggle'></button> GPU-ACCELERATED ANIMATIONS <script async custom-element="amp-sidebar" src="https://cdn.ampproject.org/v0/amp-sidebar-0.1.js"></script>
  90. GPU-ACCELERATED ANIMATIONS .sidebar { position: fixed; right: 100%; top: 0;

    bottom: 0; width: 300px; transform: translate( 0, 0 ); transition: transform .5s ease-in-out; will-change: transform; } .sidebar.is-open { transform: translate( 100%, 0 ); }
  91. GPU-ACCELERATED ANIMATIONS .sidebar { position: fixed; right: 100%; top: 0;

    bottom: 0; width: 300px; transform: translate( 0, 0 ); transition: transform .5s ease-in-out; will-change: transform; } .sidebar.is-open { transform: translate( 100%, 0 ); }
  92. FPS

  93. ANIMATIONS Use transform and opacity 01 Promote moving elements with

    'will-change' 02 03 Don't overdo it https://developers.google.com/web/fundamentals/.../stick-to-compositor-only-properties-and-manage-layer-count https://csstriggers.com/
  94. HOW TO SPEED UP? Ban everything harmful

  95. 95 the validator

  96. https://addons.opera.com/en-gb/extensions/details/amp-validator/ https://chrome.google.com/webstore/detail/amp-validator/nmoffdblmcmgeicmolmhobpoocbbmknc #development=1

  97. Google AMP Cache

  98. Google AMP Cache

  99. Google AMP Cache VALIDATION ERRORS

  100. 100 inline css

  101. CSS CSS (gzipped) github.com ~109KB 23KB guardian.com ~295KB 46KB wired.com

    ~329KB 135KB dribbble.com ~385KB 68KB medium.com ~550KB 236KB m.facebook.com ~820KB 168KB mobile.nytimes.com ~900KB 189KB NOT INLINED CSS SHIPPED THESE DAYS (tested with iPhone 5 User agent)
  102. AMOUNT OF INLINED CSS MAX KB 50

  103. 103 script loading

  104. SCRIPT LOADING <script type="text/javascript" src="https://seal.websecurity.norton.com/ getseal?host_name=www.example.com"></script>

  105. SCRIPT LOADING

  106. SCRIPT LOADING REAL LIFE EXPERIENCE

  107. SCRIPT LOADING REAL LIFE EXPERIENCE THIS REALLY HAPPENS!

  108. SCRIPT LOADING <script type="text/javascript" src="https://seal.websecurity.norton.com/ getseal?host_name=www.example.com"></script>

  109. <script> (function() { var src = (document.location.protocol === 'https:' ?

    'https:/' : 'http:/') + '/imagesrv.adition.com/js/srp.js'; document.write('<scr' + 'ipt type="text/javascript" src="' + src + '" charset="utf-8"></scr' + 'ipt>'); })(); </script> document.write SCRIPT LOADING
  110. “But what happens when the JavaScript fails to load?”

  111. NO PROGRESSIVE ENHANCEMENT

  112. “We need to come up with a standard alternative real

    quick” Yoav Weiss Akamai https://twitter.com/yoavweiss/status/659141410990350336
  113. “I’ve been on the jQuery team for many years, and

    personally have seen how a library can drive meaningful, healthy change to the ecosystem at large. This is what we want.” Paul Bakaus Open Web Developer Advocate at Google https://medium.com/@pbakaus/doesnt-come-across-snarky-all-good-9d4269f7dbe6
  114. Feature Policy Ressource Limits CPU and Bandwidth Priority User Experience

    CONTENT PERFORMANCE POLICY http://wicg.github.io/ContentPerformancePolicy/
  115. https://wicg.github.io/feature-policy/ Feature-Policy: { "vibrate": ["self", "https://foo.com"], "sync-xhr": [], "usermedia": ["*"]

    } FEATURE POLICY <meta http-equiv="Feature-Policy" content='"vibrate": ["self", "https://foo.com"], "sync-xhr": []'> VIA HEADERS VIA META ELEMENT <iframe src="example.com" enable="vibrate" disable="sync-xhr"> VIA ATTRIBUTE Might change! currently in investigation
  116. RESOURCE SIZE LIMITS NO CONCRETE PROPOSAL YET currently in investigation

  117. CPU AND BANDWIDTH PRIORITY VIA META ELEMENT <meta http-equiv="cgroup" name="ads"

    content="cpu-share 0.2; cpu-priority medium; net-share 0.8; net-priority medium;"> <script cgroup="ads" src="/ads-manager.js" async></script> <iframe cgroup="ads" src="//3rdparty.com/widget" async></iframe> Might change! currently in investigation
  118. USER EXPERIENCE NO CONCRETE PROPOSAL YET currently in investigation

  119. https://github.com/WICG/aspect-ratio ASPECT-RATIO img { size: calc(2/1); } Might change!

  120. 120 The web is catching up

  121. HOW CAN IT BE SO FAST?

  122. AMP CACHE & SEARCH How can it be so fast?

    https://cdn.ampproject.org/v/www.bbc.co.uk/news/amp/36202424 COMPLETE DOCUMENTS GO INTO AMP CACHE
  123. AMP CACHE & SEARCH How can it be so fast?

    <iframe class="u2quVpIWVr0__amp-doc" allowfullscreen="true" scrolling="no" src="https://cdn.ampproject.org/v/www.bbc.co.uk/news/amp/ 36202424? amp_js_v=5#dialog=0&prerenderSize=1&amp;visibilityState=hid den&amp;paddingTop=54&amp;history=1&amp;p2r=0&amp;horizonta lScrolling=0&amp;csi=0&amp;storage=1" style="height: 568px;"></iframe> SMART PRELOADING https://www.google.nl/amp/www.bbc.co.uk/...
  124. 124 What is AMP? CONTROL BEST PRACTICES VALIDATION FOUNDER

  125. 125 Can we be as fast as AMP? JUP!

  126. 126 Is AMP the solution? ¯\_(ϑ)_/¯

  127. “If you try to convince somebody, that contents are worth

    their time, you don't want a loading bar to get in their way.” Anand Varma National Geographic
  128. Thanks! @stefanjudis bit.ly/fix-the-web Slides bit.ly/did-you-like-amp Feedback