AMP는 어떻게 빠른 성능을 내나? AU개발 김태훈 kishu@navercorp.com
AMP 란무엇인가?
AMP 방식으로 HTML을 만들고 AMP JS를 로딩하고 AMP 컴포넌트만 사용하면 웹페이지의 빠른 렌더링을 보장 + 구글 검색 결과에서 즉시 로딩(빠르고 멋있게)
AMPs are just Web Pages!
AMPs are just Web Pages!
HELLO AMP!!! <!doctype html> <html amp lang="en"> <head> <meta charset="utf-8"> <title>hello, AMPs</title> <link rel="canonical" href="http://example.ampproject.org/article-metadata.html" /> <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate>body{... }</style> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body> <h1>welcome to the mobile web</h1> </body> </html>
AMP COMPONENTS /* AMP - */ <amp-img src="welcome.jpg" alt="welcome" height="400" width="800"></amp-img> /*AMP - */ <amp-video width=400 height=300 src="https://yourhost.com/videos/myvideo.mp4" poster="myvideo-poster.jpg"> </amp-video> amp-ad amp-embed amp-img amp-pixel amp-video
AMP EXTENDED COMPONENT /* AMP - */ <amp-carousel width=300 height=400> <amp-img src="my-img1.png" width=300 height=400></amp-img> <amp-img src="my-img2.png" width=300 height=400></amp-img> <amp-img src="my-img3.png" width=300 height=400></amp-img> </amp-carousel> /* AMP - */ <amp-youtube data-videoid="mgenrkrdogy" layout="responsive" width="480" height="270"></amp-youtube> amp-accordion amp-analytics amp-carousel amp-facebook amp-list amp-sidebar amp-youtube amp-mustache... 30 more
AMP STYLE <style amp-custom> /* any custom style goes here */ body { background-color: white; } amp-img { background-color: gray; border: 1px solid black; } </style>
AMP VALIDATION
AMP 벤치마킹 repository https://oss.navercorp.com/kishu/amp-prototype.git http://viewoss.navercorp.com/kishu/amp-prototype/blob/master/default.html http://viewoss.navercorp.com/kishu/amp-prototype/blob/master/video.html
AMP 벤치마킹이슈
AMP 벤치마킹 TIMELINE
AMP 벤치마킹 NETWORK
AMP 벤치마킹 NETWORK
HOW AMP SPEEDS UP PERFORMANCE
How AMP Speeds Up Performance
How AMP Speeds Up Performance
How AMP Speeds Up Performance
INSIDE OF AMP
AMP: CUSTOM ELEMENTS builtins/amp-img.js export function installimg(win) { registerelement(win, 'amp-img', AmpImg); } src/custom-element.js export function registerelement(win, name, implementationclass) { knownelements[name] = implementationclass; } win.document.registerelement(name, { prototype: createampelementproto(win, name), });
AMP: CUSTOM ELEMENTS BaseElement HTMLElement.prototype AmpImg ElementProto this.implementation_ = new AmpImg(); Custom Element AMP Components = HTML Custom Elements
AMP: CUSTOM ELEMENT Lifecycle Callbacks createdcallback attachedcallback detachedcallback attributechangedcallback
AMP: CUSTOM ELEMENT AMP's Extended Lifecycle Callbacks firstattachedcallback buildcallback layoutcallback viewportcallback documentinactivecallback
AMP: FSM(Finite-State Machine) OFF ON
AMP: FSM(Finite-State Machine)
AMP: FSM(Finite-State Machine) dopass = discoverwork + work applysizesandmediaquery calctaskscore measure peek schedulelayoutorpreload startlayout setinviewport
AMP: FSM(Finite-State Machine) discoverwork applysizesandmediaquery measure schedulelayoutorpreload setinviewport
AMP: FSM(Finite-State Machine) work calctaskscore peek startlayout
AMP: SINGLE PASS PROCESS class Pass { constructor(win, handler, opt_defaultdelay) { this.handler_; this.defaultdelay_; this.scheduled_; this.nexttime; this.running_; } ispending(); schedule(opt_delay); cancel(); } new Pass(this.win, () => this.dopass_()); let nextpassdelay = (now - this.exec_.getlastdequeuetime()) * 2; nextpassdelay = Math.max(Math.min(30000, nextpassdelay), 5000);
AMP: PROMISE
AMP: OPTIMIZATION REFLOW
AMP: OPTIMIZATION REFLOW
AMP: OPTIMIZATION REFLOW
AMP: OPTIMIZATION REFLOW // measure - ( ) var h1 = element1.clientheight; // mutate - element1.style.height = (h1 * 2) + 'px'; // measure - var h2 = element2.clientheight; // mutate - element2.style.height = (h2 * 2) + 'px'; // measure - var h3 = element3.clientheight; // mutate - element3.style.height = (h3 * 2) + 'px';
AMP: OPTIMIZATION REFLOW // measure var h1 = element1.clientheight; //( ) var h2 = element2.clientheight; // var h3 = element3.clientheight; // // mutate element1.style.height = (h1 * 2) + 'px'; // element2.style.height = (h2 * 2) + 'px'; // element3.style.height = (h3 * 2) + 'px'; //
NO batching DOM read/write operations
batching DOM read/write operations
AMP: OPTIMIZATION REFLOW class Vsync {.... mutate(mutator) {... } measure(measurer) {... } run(task, opt_state) {... }.... }
AMP: OPTIMIZATION REFLOW for (let i = 0; i < tasks.length; i++) { if (tasks[i].measure) { tasks[i].measure(states[i]); } } for (let i = 0; i < tasks.length; i++) { if (tasks[i].mutate) { tasks[i].mutate(states[i]); } }
AMP: OPTIMIZATION REFLOW
AMP: CONCLUSION
THANK YOU