狠狠撸

狠狠撸Share a Scribd company logo
HOW
AMP WORKS?
TaiHoon Kim(NAVER)
kishu@navercorp.com
about me
TaiHoon Kim kishu@navercorp.com
NAVER Front-End Platform
SADI HTML5 invited professor?
NHN NEXT WebUI Basic adjunct professor
Project Management Professional(PMP)
Front-End Development Group Sysop
http://facebook.com/groups/webfrontend
AMP?
Bench-marking
How AMP works?
AMP Inside
AGENDA
AMP?
ACCELLERATED MOBILE PAGES by Google
ウェブページをもっと早くレンダリングするための技術?
パフォーマンス向上のためのグーグルの経験に基づいたベストプラクティス
AMPs are just Web Pages!
AMP HTML
拡張可能な HTML : AMP 拡張タグとプロパーティ
AMP 拡張タグを使って<amp-carousel> などのコンポーネント利
?AMP 拡張タグはカスタムエレメント基盤のウェブコンポーネント
パフォーマンスのための制約 : <img> は <amp-img> を使うなど
amp.js
AMP ページとリソースのライフサイクル及びレンダリングタイム制御
AMP カスタムエレメント実装コード
ウェブページのパフォーマンス向上のため
のベストプラクティス
AMP は外部の JS を許可してない。
カスタム JS は sandbox iframe で使える。
AMP STYLE = CSS
外部のスタイル、インラインスタイルは許可しない
ドキュメントに注?する形のインラインスタイルは使?可能
最? 50KB まで許可
例
Naver モバイルメインページ - 合計 2つのファイルで約 100KB
Naver モバイルニュースホーム - 合計 2つのファイルで約 67KB
Naver モバイルニュースエンド - 合計 8つのファイルで約 50KB
<style amp-custom>
/* any custom style goes here */
body {
background-color: white;
}
amp-img {
background-color: gray;
border: 1px solid black;
}
</style>
How AMP Work?
AMP コンポーネントを使って HTML を作成し
AMP JS をロードすることで
ウェブページの?速レンダリングを保証
+ グーグル検索結果で即時ロード
+ グーグル CDN キャッシュ
How AMP Work?
How AMP Work?
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=/slideshow/how-amp-work/71098843/"https:/cdn.ampproject.org/v0.js"></script>
</head>
<body>
<h1>Welcome to the mobile web</h1>
</body>
</html>
AMP COMPONENTS
/* AMP 基本コンポーネント - イメージ */
<amp-img src=/slideshow/how-amp-work/71098843/"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
... 35 more
AMP-CAROUSEL
/* AMP 拡張コンポーネント - カルーセル */
<amp-carousel width=300 height=400>
<amp-img src=/slideshow/how-amp-work/71098843/"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>
<script async custom-element="amp-carousel"
src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
AMP EXTENDED COMPONENT
/* AMP コンポーネント - lightbox */
<amp-image-lightbox id="lightbox1"
layout="nodisplay">
</amp-image-lightbox>
AMP EXTENDED COMPONENT
/* AMP コンポーネント - サイドバー */
<amp-sidebar id='sidebar'
layout="nodisplay"
side="right"> ...
How AMP Work?
AMP ベンチマーク
NAVAR TV芸能
AMP プロトタイピング
AMP ベンチマークイシュー
動画
動作する。ただし URL は https
placeholder ?のイメージが必要
JS
カスタム JS は使えない。コメントと TOP ボタンが動作しない
sandbox iframe で実装しようともしたが、セキュリティ問題など発?
nClick は amp-analytics で対応できるかリサーチが必要
外部 CSS ロードを許可しない
HTML ヘッダーにスタイル注? 4KB
HTML エレメントにインラインスタイルは許可しない
AMP ベンチマーク TIMELINE
localhost で?
network throttling 4Mb↓, 3Mb↑, 20ms RTT に設定
AMP ベンチマーク NETWORK
AMP 未适応
AMP ベンチマーク NETWORK
AMP 適応
画?に表?されるリソースを先にダウンロード
スクロースの外側のリソースは順次に遅延ロード
HOW AMP
SPEEDS UP
PERFORMANCE
How AMP Speeds Up Performance
?同期スクリプトのみ許可
ページのレンダリングを遮断する JS 防?
AMP JS 以外の他の JS も許可しない
全てのリソースのサイズ指定
リソースをダウンロードせずにサイズと位置を計算してレイアウトしておく
拡張コンポーネントをレンダリングを遮断せずに実?可能
追加で HTTP リクエストはあるかもしれないが、ページのレイアウトとレ
ンダリングは遮断しない
How AMP Speeds Up Performance
3rd Party JS をクリティカルパースから除外
3rd Party JS は sandbox iframe の内部だけ許可
親ページの実?を遮断しなくて性能に影響しない
CSS は HTML 内部スタイルシートのみ許可しサイズを制限
HTML ページの内部に style タグを?れて使?
スタイルシートのサイズは 50KB までに制限
Web フォントを効率的にダウンロード
ブラウザを遮断する HTTP リクエストが発?いないように Web フォントをダウン
ロード
How AMP Work?
How AMP Speeds Up Performance
スタイル再計算の最?化
不必要なレイアウト防?のため、先に測定をして変更を後に処理
フレーム毎スタイルので?度だけ再計算できるように保証
GPU 加速アニメーションのみ実?
ページのレイアウトが発?しない CSS アニメーションのみ使?
transform, opacity
How AMP Speeds Up Performance
リソーツのロード順番を制御
ダウンロードするリソースの優先順位を計算
重要なリソースからダウンロード
ページの即時ロード
preconnect API
取得するページをビューポート分だけインポート
INSIDE OF AMP
AMP: CUSTOM ELEMENTS
export function registerElement(win, name, implementationClass) {
knownElements[name] = implementationClass;
win.document.registerElement(name, {
prototype: createAmpElementProto(win, name),
});
}
src/custom-element.js
export function installImg(win) {
registerElement(win, 'amp-img', AmpImg);
}
builtins/amp-img.js
AMP: CUSTOM ELEMENTS
Custom Element
BaseElement HTMLElement.prototype
AmpImg ElementProto
this.implementation_ = ?
new AmpImg();
AMP Components = HTML Custom Elements
新しい HTML タイプを定義し?
ライフサイクルを制御
createdCallback カスタムエレメントの登録する時に発?
attachedCallback カスタムエレメントを DOM に追加する時に発?
detachedCallback カスタムエレメントを DOM から削除する時に発?
attributeChangedCallback カスタムエレメントの属性を追加、修正、削除する時に発?
AMP: CUSTOM ELEMENT
Lifecycle Callbacks
firstAttachedCallback カスタムエレメントの最初の DOM に追加する時に発?
buildCallback カスタムエレメントと?エレメントが使?可能になった時に発?
layoutCallback AMP がカスタムエレメントをレンダリングする時に発?
viewportCallback カスタムエレメントがビューポートに?る時と出る時に発?
documentInactiveCallback ドキュメントをアンロードする前に発?
AMP: CUSTOM ELEMENT
AMP's Extended Lifecycle Callbacks
AMP: FSM(Finite-State Machine)
AMPはコンポーネントの条件によって?つの状態をもつ
条件が変わると別の状態に変わる
状態が変わるとそれに伴うアクションを実?する
OFF ON
turn on
turn off
AMP: FSM(Finite-State Machine)
prerender
paused
inactive
doPass
unload
resume
doPass
doPass
doPass
doPass
doPassdoPass
doPass
doPass
doPass
paused
paused
unload
unload
doPass
doPassvisible
hidden
AMP: FSM(Finite-State Machine)
doPass = discoverWork + work
applySizesAndMediaQuery
discoverWork
measure
scheduleLayoutOrPreload
setInViewport
calcTaskScore
peek
startLayout
work
AMP: FSM(Finite-State Machine)
applySizesAndMediaQuery
メディアクエリを適応して AMP サイズ関連の属性をパース
measure
リソースのサイズと位置を測定。リソースは READY_FOR_LAYOUT 状態になる
scheduleLayoutOrPreload
ビューポートを拡張した特定領域内のリソースをレイアウトするための Job スケジューリング
setInViewport
リソースがビューポートの内にあるのか外にあるのかを計算し viewportCallback を実?
discoverWork
AMP: FSM(Finite-State Machine)
calcTaskScore
スケジューリングした Job の優先順位を計算
1) どの AMP カスタムエレメントなのか? 2) どんな作業なのか? 3) ビューポートはどれくらい近いのか?
peek
優先順位が最も?い Job を選択
startLayout
選択した Job の対象リソースを LAYOUT_SCHEDULED 状態に変更しレイアウトを開始
例えば、リソースが amp-img だとすると src 属性にイメージを指定することでレイアウト可能
work
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();
}
// 実?する Job を Pass に登録
new Pass(this.win, () => this.doPass_());
// Job Queue の最後の実?時間を元に次の実?時間を計算
let nextPassDelay = (now - this.exec_.getLastDequeueTime()) * 2;
nextPassDelay = Math.max(Math.min(30000, nextPassDelay), 5000);
AMP: PROMISE
initialize src
call layoutComplete
AMP: OPTIMIZATION REFLOW
Reflow
Width と Height などエレメントの幾何学的構造に影響する属性を変更すると
該当エレメントのサイズを位置をまた計算
エレメントの変更が影響する他のエレメントのサイズと位置もまた計算
Reflow は Repaint を発?させるので
できるだけ Reflow と Repaint を少なくする?がいい
AMP: OPTIMIZATION REFLOW
枠の厚さを変更し?さを変更する場合
厚さ変更 → Reflow → Repaint→ ?さ変更→ Reflow → Repaint
厚さ変更 Job を保存 → ?さ変更 Job 保存 → 保存された Job 実? → Reflow → Repaint
ブラウザは変更作業を集めて必要な時に実?
AMP: OPTIMIZATION REFLOW
エレメントのサイズ、位置、スクロールに関連した
スタイル属性をリクエストすると?
ブラウザはリクエストしたスタイルの属性を値を正確に計算するために
保存されていた変更作業を実?し Reflow、Repaint する
スタイル属性をリクエストする時には不必要な Reflow が発?しないように
AMP: OPTIMIZATION REFLOW
// measure - (保存された Job があると) Reflow 発生
var h1 = element1.clientHeight;
// mutate - 変更 Job 保存
element1.style.height = (h1 * 2) + 'px';
// measure - Reflow 発生
var h2 = element2.clientHeight;
// mutate - 変更 Job 保存
element2.style.height = (h2 * 2) + 'px';
// measure - Reflow 発生
var h3 = element3.clientHeight;
// mutate - 変更 Job 保存
element3.style.height = (h3 * 2) + 'px';
AMP: OPTIMIZATION REFLOW
// measure
var h1 = element1.clientHeight; // (保存された Job があると) 発生
var h2 = element2.clientHeight; // 保存された Job なし
var h3 = element3.clientHeight; // 保存された Job なし
// mutate
element1.style.height = (h1 * 2) + 'px'; // 変更Job 保存
element2.style.height = (h2 * 2) + 'px'; // 変更Job 保存
element3.style.height = (h3 * 2) + 'px'; // 変更Job 保存
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
How AMP Work?
THANK YOU

More Related Content

How AMP Work?