Slide 1

Slide 1 text

Introduction to Performance APIs Chrome Tech Talk Night #12 Shogo Sensui (@1000ch)

Slide 2

Slide 2 text

Shogo Sensui (@1000ch) Software Engineer Merpay, Inc / Mercari, Inc

Slide 3

Slide 3 text

Table of contents ● Lazy Loading ● Prefetch ● Off The Main Thread

Slide 4

Slide 4 text

Lazy Loading

Slide 5

Slide 5 text

Intersection Observer > The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport. const observer = new IntersectionObserver((entries) => { for (const entry of entries) { if (entry.isIntersecting) { console.log(entry); } } }); const el = document.querySelector('#el); observer.observe(el);

Slide 6

Slide 6 text

WebKit shipped!!!

Slide 7

Slide 7 text

Intersection Observer v2 Intersection Observer v2 will detect the actual visiblity (like “opacity”). ● New options ○ trackVisiblity constructor option to track visiblity ○ isVisible property in IntersectionObserverEntry ● IntersectionObserver v2 demo const el = document.querySelector('#el); const observer = new IntersectionObserver((entries) => { for (const entry of entries) { if (entry.isVisible) { console.log(entry); } } }); observer.observe(el, { trackVisiblity: true });

Slide 8

Slide 8 text

Browser native lazy-loading lazyload attribute to load if display with-in viewport. ● will be enabled on... ○ ○ ● Lazyload images and iframes by bengreenstein · Pull Request #3752 · whatwg/html. ● Blink LazyLoad Design Docs (public)

Slide 9

Slide 9 text

⚡ Prefetch

Slide 10

Slide 10 text

Priority Hints for resource loading importance attribute to indicate resource priority. ● will be enabled on... ○ ○ ○ ○ <link> ○ fetch() ● Priority Hints Draft Community Group Report 18 October 2018 <img src="https://example.com/image.jpg" importance="high"> <iframe src="https://example.com" importance="low"> </iframe> <script> fetch('https://google.com', { importance: 'high' });

Slide 11

Slide 11 text

Resource Hints Resource Hints provides speculative loading which consists of... ● DNS Prefetch: host ● Preconnect: host ● Prefetch: resources ● Prerender: specified page

Slide 12

Slide 12 text

https://www.igvita.com/2015/08/17/eliminating-roundtrips-with-preconnect/

Slide 13

Slide 13 text

Preload Preload provides aggressive loading ● For nested resources for initial loading ○ e.g) Images referred in CSS ○ e.g) JavaScript loaded on JavaScript ● Similar to Resource Hints

Slide 14

Slide 14 text

Chrome Prerender History chrome://net-internals/#prerender

Slide 15

Slide 15 text

GoogleChromeLabs/quicklink > Faster subsequent page-loads by prefetching in-viewport links during idle time Speculative prefetch links with-in viewport using following APIs. ● Intersection Observer ● Prefetch (Resource Hints) ● requestIdleCallback() ● Network Information API. quicklink({ ignores: [ /\/api\/?/, uri => uri.includes('.zip'), (uri, el) => el.hasAttribute('noprefetch') ] });

Slide 16

Slide 16 text

Nuxt v2.4 supports prefetching links in viewport > Nuxt.js will automagically prefetch the code-splitted pages linked with when visible in the viewport by default. This hugely improves the end user performances, inspired by quicklink.

Slide 17

Slide 17 text

AMP is the best example for Prefetch/Prerender AMP prefetch/prerender some resources to achieve instant loading ● Prefetch resources ○ from Google AMP Cache hosted on Google ● Prerender documents ○ AMP’s prerender differs from ■ Why AMP HTML does not take full advantage of the preload scanner

Slide 18

Slide 18 text

AMP’s URL is a long-standing problem..

Slide 19

Slide 19 text

Web Packaging will solve the AMP’s URL problem Web Packaging consists of... ● Signed HTTP Exchanges: Signs request/response including URL with private keys and creates .sxg file ● Bundled HTTP Exchanges: Bundles subresources in response ● Loading Signed Exchanges: Loads signed .sxg file and displays the original URL instead of distributed URL

Slide 20

Slide 20 text

Off The Main Thread

Slide 21

Slide 21 text

More rich, More heavy. Web Page’s payload is increasing continuously

Slide 22

Slide 22 text

Main Thread is busy ● Loading (almost described by Critical Rendering Path) ○ Fetch HTML ○ Parse HTML and construct DOM ○ Fetch sub-resources including CSS ○ Parse CSS and construct CSSOM ○ Eval heavy JavaScript (especially in recent web app) ○ etc... ● Runtime ○ Interact to user operations ○ Fetch data and render async ○ etc...

Slide 23

Slide 23 text

Performance metrics are changing 1. Focused to Server Response (old SSR) ○ load event ○ DOMContentLoaded event 2. Focused to First View (CSR a.k.a SPA) ○ Speed Index ○ First Paint, First Contentful Paint, First Meaningful Paint ○ Async smooth page transition 3. Focusing to interactivity <= now ○ First CPU Idle (Time to interactive) ○ Responsibility on Runtime

Slide 24

Slide 24 text

https://dev.to/addyosmani/web-page-usability-matters-3aok

Slide 25

Slide 25 text

DOM manipulation is heavy ● Virtual DOM was born ○ to solve rendering performance ○ The Inner Working Of Virtual DOM ○ View library has implemented it such as React, Vue.js, Angular, Preact ● Virtual DOM achieve effective rendering, but... ○ Diff algorithm is also heavy ○ Can we use DOM in Worker? ● Split DOM manipulation ○ React Suspense provides async render with Promise ○ Vue.js mutation will use requestIdleCallback()

Slide 26

Slide 26 text

Off The Main Thread (inner browser) ● Parse and compile scripts in V8 ● HTMLParser Redesign ● Will Worklets work on Worker thread?

Slide 27

Slide 27 text

Off The Main Thread (web page land) ● ampproject/worker-dom: DOM API implementation in Worker ○ using MutationRecord and postMessage ○ Browser-native Worker DOM is…? ● OffscreenCanvas: Canvas in Worker ○ Draw canvas on Worker Context ● Concurrent JavaScript idea by WebKit

Slide 28

Slide 28 text

https://threejs.org/examples/webgl_worker_offscreencanvas.html

Slide 29

Slide 29 text

More easier postMessage() !!!

Slide 30

Slide 30 text

postMessage() interface override We could only pass string messages to postMessage(), but new interface is added. postMessage( // primitives, object, File, Blob, etc... message, // targetOrigin, transfer options ); postMessage( // string message, // targetOrigin targetOrigin, // transfer transfer );

Slide 31

Slide 31 text

JavaScript "blöcks" proposal We could only pass string messages to postMessage(), but new interface is added. const result = await worker{| const res = await fetch("people.json"); const json = await res.json(); return json[2].firstName; |};

Slide 32

Slide 32 text

GoogleChromeLabs/comlink > Comlink removes the mental barrier of thinking about postMessage and hides the fact that you are working with workers. // main.js const MyClass = Comlink.proxy(new Worker("worker.js")); // `instance` is an instance of `MyClass` that lives in the worker! const instance = await new MyClass(); // logs “myValue = 42” await instance.logSomething();

Slide 33

Slide 33 text

Further prospects ● More adoptive loading ○ By using Resource Hints, Intersection Observer, lazyload attribute, etc ● More effective prefetch ○ Like quicklink, Nikkei ● Will View libraries use Worker? ○ To calculate Virtual DOM diffs in Worker Thread ○ To apply Virtual DOM patch from Worker Thread ● Pray for browser optimizations