Slide 1

Slide 1 text

AMP tries to fix the web What can we learn from it? (◠‿◠✿) @stefanjudis

Slide 2

Slide 2 text

Stefan Judis Frontend Developer, Occasional Teacher, Meetup Organizer ❤ Open Source, Performance and Accessibility ❤ @stefanjudis

Slide 3

Slide 3 text

PERF TOOLING TODAY

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

CONTENT SOCKS

Slide 6

Slide 6 text

6 the here and now

Slide 7

Slide 7 text

SLOW LOADING PAGES 110 requests & 956KB Page size

Slide 8

Slide 8 text

GOOGLE CONTINUES TO INFLUENCE SEARCH RESULTS

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

DOCUMENT.WRITE ON SLOW CONNECTIONS MAY BE BLOCKED IN FUTURE https://github.com/WICG/interventions/issues/17

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

15 The web is "broken"

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

“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

Slide 18

Slide 18 text

https://search.googleblog.com/2016/09/search-results-are-officially-ampd.html SEARCH RESULTS ARE NOW OFFICIALLY AMP'D

Slide 19

Slide 19 text

HOW CAN IT BE SO FAST?

Slide 20

Slide 20 text

THREE MAIN PARTS AMP HTML AMP JS Google AMP Cache

Slide 21

Slide 21 text

Hello World

Hello World!

GETTING STARTED HTML file

Slide 22

Slide 22 text

Hello World

Hello World!

GETTING STARTED HTML file

Slide 23

Slide 23 text

GETTING STARTED double the maintenance AMP HTML HTML

Slide 24

Slide 24 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! GETTING STARTED AMP file

Slide 25

Slide 25 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! GETTING STARTED AMP file

Slide 26

Slide 26 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! GETTING STARTED AMP file

Slide 27

Slide 27 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! GETTING STARTED AMP file

Slide 28

Slide 28 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! GETTING STARTED AMP file

Slide 29

Slide 29 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! GETTING STARTED AMP file

Slide 30

Slide 30 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! GETTING STARTED AMP file

Slide 31

Slide 31 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! GETTING STARTED AMP file

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

THREE BUILTINS AMP-IMG AMP-PIXEL AMP-VIDEO

No support for HTML5

Slide 34

Slide 34 text

CUSTOM MARKUP IF YOU NEED MORE ELEMENTS

Slide 35

Slide 35 text

THREE BUILTINS AMP-IMG AMP-PIXEL AMP-VIDEO

No support for HTML5

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

CUSTOM ELEMENTS http://w3c.github.io/webcomponents/spec/custom/

Slide 38

Slide 38 text

Custom elements v0 Custom elements v1

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

CUSTOM MARKUP Custom Elements v0 Custom Elements v1 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

Slide 41

Slide 41 text

CUSTOM MARKUP LIFECYCLE HTML ELEMENT createdCallback attachedCallback

Slide 42

Slide 42 text

CUSTOM MARKUP upgrade firstAttachedCallback buildCallback layoutCallback viewportCallback LIFECYCLE AMP ELEMENT createdCallback LIFECYCLE HTML ELEMENT createdCallback attachedCallback

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

HOW TO SPEED UP? Control everything

Slide 45

Slide 45 text

45 resource priority

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

RESOURCE PRIORITY where the preloader fails

Slide 49

Slide 49 text

RESOURCE PRIORITY where the preloader fails

Slide 50

Slide 50 text

RESOURCE PRIORITY where the preloader fails

Slide 51

Slide 51 text

RESOURCE PRIORITY the AMP runtime

Slide 52

Slide 52 text

RESOURCE PRIORITY the AMP runtime

Slide 53

Slide 53 text

NON CRITICAL RESOURCES GET OUT OF THE WAY RESOURCE PRIORITY the AMP runtime

Slide 54

Slide 54 text

RESOURCE PRIORITY the AMP runtime class AmpPixel extends BaseElement { getPriority() { // Loads after other content. return 1; } }

Slide 55

Slide 55 text

55 reflow management

Slide 56

Slide 56 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! REFLOW MANAGEMENT

Slide 57

Slide 57 text

body{ animation:-amp-start 8s steps(1,end) 0s 1 normal both } @keyframes -amp-start{ from{visibility:hidden} to{visibility:visible} } body{-webkit-animation:none;-moz-animation:none;-ms- animation:none;animation:none} Hello World! REFLOW MANAGEMENT

Slide 58

Slide 58 text

REFLOW MANAGEMENT

Slide 59

Slide 59 text

REFLOW MANAGEMENT

Slide 60

Slide 60 text

REFLOW MANAGEMENT EXTERNALLY FETCHED RESOURCES MUST BE GIVEN AN EXPLICIT SIZE amp-img { background-color: grey; }

Slide 61

Slide 61 text

REFLOW MANAGEMENT NO REFLOWS!

Slide 62

Slide 62 text

A chameleon catching bubbles REFLOW MANAGEMENT https://www.smashingmagazine.com/2016/08/ways-to-reduce-content-shifting-on-page-load/ AVOID REFLOWS TODAY

Slide 63

Slide 63 text

A chameleon catching bubbles REFLOW MANAGEMENT https://www.smashingmagazine.com/2016/08/ways-to-reduce-content-shifting-on-page-load/ AVOID REFLOWS TODAY

Slide 64

Slide 64 text

HOW TO SPEED UP? Enforce best practices

Slide 65

Slide 65 text

65 inline css

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

INLINE CSS 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 //

Slide 68

Slide 68 text

68 custom fonts

Slide 69

Slide 69 text

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'); }

Slide 70

Slide 70 text

"traditional" approach CUSTOM FONTS

Slide 71

Slide 71 text

"traditional" approach CUSTOM FONTS FOIT!

Slide 72

Slide 72 text

"new" approach CUSTOM FONTS https://ampbyexample.com/components/amp-font/

Slide 73

Slide 73 text

"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/

Slide 74

Slide 74 text

"new" approach CUSTOM FONTS fixed-

Slide 75

Slide 75 text

"new" approach CUSTOM FONTS fixed-

Slide 76

Slide 76 text

"new" approach CUSTOM FONTS fixed- FOUT!

Slide 77

Slide 77 text

"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

Slide 78

Slide 78 text

"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

Slide 79

Slide 79 text

CSS FONT LOADING https://drafts.csswg.org/css-font-loading/

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

"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

Slide 82

Slide 82 text

"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

Slide 83

Slide 83 text

"new" approach CUSTOM FONTS CSS FONT-RENDERING CONTROLS font-display

Slide 84

Slide 84 text

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/

Slide 85

Slide 85 text

85 GPU-accelerated animations

Slide 86

Slide 86 text

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; }

Slide 87

Slide 87 text

GPU-ACCELERATED ANIMATIONS

Slide 88

Slide 88 text

NOT 60 FRAMES PER SECOND ANYMORE

Slide 89

Slide 89 text

  • Nav item 1
  • Nav item 2
  • Nav item 3
GPU-ACCELERATED ANIMATIONS

Slide 90

Slide 90 text

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 ); }

Slide 91

Slide 91 text

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 ); }

Slide 92

Slide 92 text

FPS

Slide 93

Slide 93 text

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/

Slide 94

Slide 94 text

HOW TO SPEED UP? Ban everything harmful

Slide 95

Slide 95 text

95 the validator

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

Google AMP Cache

Slide 98

Slide 98 text

Google AMP Cache

Slide 99

Slide 99 text

Google AMP Cache VALIDATION ERRORS

Slide 100

Slide 100 text

100 inline css

Slide 101

Slide 101 text

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)

Slide 102

Slide 102 text

AMOUNT OF INLINED CSS MAX KB 50

Slide 103

Slide 103 text

103 script loading

Slide 104

Slide 104 text

SCRIPT LOADING

Slide 105

Slide 105 text

SCRIPT LOADING

Slide 106

Slide 106 text

SCRIPT LOADING REAL LIFE EXPERIENCE

Slide 107

Slide 107 text

SCRIPT LOADING REAL LIFE EXPERIENCE THIS REALLY HAPPENS!

Slide 108

Slide 108 text

SCRIPT LOADING

Slide 109

Slide 109 text

(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>'); })(); document.write SCRIPT LOADING

Slide 110

Slide 110 text

“But what happens when the JavaScript fails to load?”

Slide 111

Slide 111 text

NO PROGRESSIVE ENHANCEMENT

Slide 112

Slide 112 text

“We need to come up with a standard alternative real quick” Yoav Weiss Akamai https://twitter.com/yoavweiss/status/659141410990350336

Slide 113

Slide 113 text

“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

Slide 114

Slide 114 text

Feature Policy Ressource Limits CPU and Bandwidth Priority User Experience CONTENT PERFORMANCE POLICY http://wicg.github.io/ContentPerformancePolicy/

Slide 115

Slide 115 text

https://wicg.github.io/feature-policy/ Feature-Policy: { "vibrate": ["self", "https://foo.com"], "sync-xhr": [], "usermedia": ["*"] } FEATURE POLICY VIA HEADERS VIA META ELEMENT VIA ATTRIBUTE Might change! currently in investigation

Slide 116

Slide 116 text

RESOURCE SIZE LIMITS NO CONCRETE PROPOSAL YET currently in investigation

Slide 117

Slide 117 text

CPU AND BANDWIDTH PRIORITY VIA META ELEMENT Might change! currently in investigation

Slide 118

Slide 118 text

USER EXPERIENCE NO CONCRETE PROPOSAL YET currently in investigation

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

120 The web is catching up

Slide 121

Slide 121 text

HOW CAN IT BE SO FAST?

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

AMP CACHE & SEARCH How can it be so fast? SMART PRELOADING https://www.google.nl/amp/www.bbc.co.uk/...

Slide 124

Slide 124 text

124 What is AMP? CONTROL BEST PRACTICES VALIDATION FOUNDER

Slide 125

Slide 125 text

125 Can we be as fast as AMP? JUP!

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

“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

Slide 128

Slide 128 text

Thanks! @stefanjudis bit.ly/fix-the-web Slides bit.ly/did-you-like-amp Feedback