プレゼンモード
再生
← / →で移動
fでフルスクリーン
escでおわる
こんにちは,id:hitode909です.このあと14時から品川のマイクロソフト様のオフィスでおこなわれている,YAP(PはパチモンのP)Cで発表します.
この記事では,発表資料を公開いたします.現地の方は今すぐCルームに来てください.そうでないかたは懇親会でお会いしましょう.
はてなブログのトピックもあるようです.
はてなブログのAMP対応で学ぶウェブサービスのAMP対応
2016/07/03 YAP(achimon)C::Asia Hachioji 2016 mid in Shinagawa
hitode909
自己紹介
YAPC 2015でベストトーク賞いただきました
YAPC::Asia Tokyo 2015 | 写真共有サービス 30days Album
副賞のXboxをオフィスに導入しました
この発表について
- 資料はこちら
- 質問などあれば随時 #yapc8ojiCまで
- 余裕があれば拾っていきたい
話したいこと
はてなブログのAMP対応の事例を紹介しつつAMP対応のノウハウを共有したい
話題
- AMPの紹介
- 素朴なウェブサービスのAMP対応
- Quyoの話
- 複雑なウェブサービスのAMP対応
- はてなブログの話
みなさま
- ウェブサービス作ってる人?
- HTML書いてる人?
- AMP知ってる人?
- AMP書いたことある人?
- AMP書いて本番投入した人?
- AMP Projectにコントリビュートしている人?
AMP(Accelerated Mobile Pages)の紹介
- 静的なコンテンツを高速に配信してレンダリングするための仕組み
- GoogleやTwitter等の企業が進めている
- 実装はオープンソース
AMPはどこに表示されるか
スマホ版のGoogleの検索結果
はてなブックマークのスマホアプリ
http://bookmark.hatenastaff.com/entry/2016/06/23/155916
左:AMP対応ページ・右:AMP非対応ページ
TwitterアプリのMoments
- 日本ではリリースされていない
- Explore links in Moments | Twitter Blogs
AMPの構成要素
- AMP HTML
- HTMLのサブセット
- これを作ると配信してくれる
- 高速に表示するための工夫
- AMP JS
- AMP HTMLをレンダリングするためのランタイム
- Google AMP Cache
- AMP HTMLをキャッシュしてCDN経由で配信する
AMP HTML
- 高速にレンダリングできるよう工夫されたHTMLのサブセット
- リフロー・リペイントを防ぐ仕組み
- 使える要素や属性を制限
- 自由なscriptは書けない
- styleは1箇所にまとめる
- 自由なwebfontは使えない
- AMP用の要素(コンポーネント)が用意されている
- imgのかわりにimg-srcを使う,など
AMPは静的コンテンツに向いている
向いている
- アクセスして読む
- ニュースやブログの配信
向いてない
- その場で何かできるのは難しい
- チャットや掲示板
- ブログを書く機能
AMPの紹介おわり
完成品
QuyoはAMP対応しやすい
- テキストと,写真1点を投稿できるサービス
- リンクも貼れない
- ほぼ固定のテンプレートに,本文を流しこめば完成
AMP対応の手順
簡単5ステップ
- エンドポイントを作る
- HTMLからlinkタグを設定
- テンプレートを作る
- メタデータを埋める
- CSSを作って完成
1.エンドポイントを作る
- /amp とかなんか適当に決めましょう
- /ampとか,?ampとか,?amp=1とか,区別できればなんでもいい
- 普段はCDNから配信されるので,URL直接打たない限りは表には出ない
2.HTMLからlinkタグを設定
- クローラ向けに,このページにはAMP版があるということを教える
<link rel="amphtml" href="http://quyo.hatelabo.jp/items/5476d8e33531320002220000/amp">
3.テンプレートを作る
- 記事ページだけ作る
- 普段はCDNから配信されるので,ログインの仕組みは廃止して,記事を読めるだけ
- ボイラープレートをコピペして用意する
- HTMLタグをかっこよくする
<html ⚡>
もしくは
<html amp>
- AMP JSをロード
<script async src="https://cdn.ampproject.org/v0.js"></script>
- HTML版のテンプレートからコピペしていらないところ消して完成
4.メタデータを埋める
- クローラ用にJSONを埋めておく
- JSON-LD形式 http://json-ld.org/
- 媒体名やロゴなど 検索結果のカルーセルに出てくる
<script type="application/ld+json"> { "@context": "http://schema.org", "@type": "NewsArticle", "mainEntityOfPage": "http://quyo.hatelabo.jp/items/54769e6f31663000020b0000", "headline": "発売と同時に購入して,2週間くらい使ってた", "datePublished": "2014-11-27T03:45:51+00:00", "dateModified": "2014-11-27T03:45:51+00:00", "description": "発売と同時に購入して,2週間くらい使ってたのだけど,やっぱりケース付けない派なので友達にあげた その後さらに人に渡ったようで,いま誰が使ってるんだろ", "author": { "@type": "Person", "name": "hitode909" }, "publisher": { "@type": "Organization", "name": "Quyo", "logo": { "@type": "ImageObject", "url": "http://quyo.hatelabo.jp/images/amp-logo.png", "width": 163, "height": 60 } }, "image": { "@type": "ImageObject", "url": "http://instagram.com/p/nUgAQeRGie/media/?size=l", "height": 640, "width": 640 } } </script>
5.CSSを作る
- 必要そうなところをコピペ
- 使えないスタイルあるので注意
- インラインなスタイルは使えない
- !importantは使えない
- 50KBまで
- ユニバーサルセレクタ(*)は使えない
- Accelerated Mobile Pages Project
- linkタグではなく,styleタグ内に直接展開する
<style amp-custom>ここにスタイルを全部書く</style>
開発中に気をつけること
- バリデーションを通す
- 画像のサイズをサーバーサイドで調べる
1. バリデーションを通す
- AMP HTMLとしてvalidじゃないと,CDNから配信してもらえない
- 検索結果にも出ない
- 本番環境にデプロイしなくても,localhostで起動したサーバーをブラウザで開いて確認できる
- #development=1をつけるとAMPとしてvalidかバリデーションをおこなってくれる
エラーが出ている
直すとバリデーション通る
jQueryとかロードしていたのをやめた
2. 画像のサイズをサーバーサイドで調べる
- AMP HTMLでは,imgのかわりにamp-imgを使う
- スクロール位置に応じて遅延ロードなどを行ってくれる
- 画像をロードせずにアスペクト比を知るため,画像の幅と高さを与えなければならない
- https://github.com/ampproject/amphtml/blob/master/builtins/amp-img.md
<amp-img src="http://instagram.com/p/nUgAQeRGie/media/?size=l" layout="responsive" width="640" height="640" />
作戦
- AMP HTMLを配信するさいに,サーバーサイドで画像を取得
- テンプレートに@item_widthと@item_heightを渡す
- QuyoはRubyとSinatraを使っているので,fastimageを利用
- 画像は1記事に1つだけなので同期的に取得
@item_width, @item_height = *FastImage.size(@item.image_url)
QuyoをAMP対応してわかったこと
- ふだんのウェブサービス開発と近いフローで進められる
- 画像のサイズをサーバーサイドで埋めるのが手間
- 記事内に画像をたくさん貼れると不穏な予感がする
素朴なウェブサービスのAMP対応
おわり
もうちょっと複雑なウェブサービスのAMP対応の事例
はてなブログの事例のご紹介
はてなブログについて
- 2011年夏から開発しているブログサービス
- もうすぐ5周年
HTMLなんでも書ける
- 本文に任意のタグを書ける
- scriptも書ける
- インラインなstyleも書ける
はてなブログをAMPに対応したい
Quyoとの比較
Quyoの場合
- 本文はテキストだけ
- 各行をpで挟んで配信すればよい
- 画像のURLを入力する欄がある
- 指定したURLの画像を取得してamp-imgに入れればよい
はてなブログの場合
- 本文にはなんでも書ける
- 使えない要素や属性は取り除く必要がある
- 画像は本文中にimgタグとなって登場する
- imgを探してamp-imgに書き換える必要がある
- 本文にtwitterとかinstagramとか貼れる
- twitterやinstagramを貼ってそうなところを探してamp-twitterやamp-instagramに書き換えたい
先に完成品
- http://tsukurioki.hatenablog.com/entry/2016/06/27/204738
- http://tsukurioki.hatenablog.com/entry/2016/06/27/204738?amp=1
対応している
- いろんなサイズの画像がちゃんともとのサイズで出ている
- インラインのスタイルを書いても,AMP版では消してくれる
- 動画や音楽を貼れている
- ブログカード(他の記事への言及)も出ている
対応していない
- ログイン機能はなくて,読めるだけ
- コメントを書いたりスターをつけたりできない
本文置き換え作戦
- 記事本文のHTMLを渡すとAMP HTMLに変換して返してくれるコンバータを作る
- 書き換えポリシーをあらわすクラスをいろいろと実装
例
本当はもっといっぱいある
- ImgToAmpImg
- imgをamp-imgに変換
- AmpTwitter
- twitter貼り付けを探してamp-twitterに変換する
- AmpYouTube
- YouTube貼り付けを探してamp-youtubeに変換する
- AmpSoundCloud
- SoundCloud貼り付けをamp-soundcloudに変換する
- ValidationRules
- AMPバリデータのバリデーションルールを使ってHTMLを正規化する
imgをamp-imgに変換
- DOMツリーを作ってimgを探して置き換える
- 画像のサイズは,画像のトリミングなどを行っている社内マイクロサービスに調べさせる
GET /api/dimensions?url=http://***.jpg&api_key=***
でJSONが返ってくる- 結果はマイクロサービスとの間のプロキシでキャッシュさせる
- 画像を取得して解析するのは重い処理なので,変な画像を解析しようとして巻き込まれて一緒に落ちるのを防ぐ
twitter貼り付けをamp-twitterに変換する
- twitterを貼り付けるためのamp-twitterというコンポーネントがあるので利用する
- 構造が複雑
早く鴨川ビールしないと暖かくなってしまう!!!!!
— 趣味はマリンスポーツです (@hitode909) 2016年3月16日
before
<blockquote class="twitter-tweet" data-lang="ja"> <p lang="ja" dir="ltr">早く鴨川ビールしないと暖かくなってしまう!!!!!</p>— 趣味はマリンスポーツです (@hitode909) <a href="https://twitter.com/hitode909/status/710100679805644800">2016年3月16日</a> </blockquote>
after
<amp-twitter width=486 height=657 layout="responsive" data-tweetid="710100679805644800" data-cards="hidden"> <blockquote class="twitter-tweet" data-lang="ja" placeholder=""> <div lang="ja" dir="ltr" class="paragraph">早く鴨川ビールしないと暖かくなってしまう!!!!!</div>— 趣味はマリンスポーツです (@hitode909) <a href="https://twitter.com/hitode909/status/710100679805644800">2016年3月16日</a> </blockquote> </amp-twitter>
やること
- ヒューリスティックにtwitter貼ってそうなところを探している
- twitter-tweetクラスのついたblockquote中のaを探してtweet idを抜き出す
- data-tweetidつきで全体をamp-twitterで囲む
なんとなくできてきた
- なんとなくできてきたので,実際にクロールさせて様子を見たい
- スタッフ限定機能としてリリースしてクロールさせてみる
- 社内でフィードバックをもらって,ちまちま直すけど,きりがない
AMPバリデータのバリデーションルールを使ってHTMLを正規化する
- 「禁止されている属性: style」みたいなエラーがたくさん
- 「禁止されている属性: stye」みたいなtypoもエラー
- きりがないので,AMPバリデータと同じ情報源を使ってバリデーションしたい
AMPバリデータを読む
- AMPのバリデータはオープンソースでGitHubで公開されている
- 1週間に 60Pull Requestくらいマージされていて活発
- バリデーションは,ProtocolBufferで書かれた定義と,それを見て動くJSで出来ている
- このvalidator-main.protoasciiを見ながらHTMLを直してくれるフィルタを作ることにした
AMPバリデータのバリデーションルールを使ってHTMLを正規化する
- validator-main.protoasciiを見て,入力されたinvalidかもしれないAMP HTMLをvalidなAMP HTMLに変換する
- 許可されていない要素は消す
- fontはバリデーションルールに載ってないので消す
- 許可されていない属性は消すか,デフォルト値に直す
- amp-imgはsrcを持てるけど,divはsrcを持てない
- aのtarget=_parentは許可されていないので,_blankに書き換える
amp-imgの定義
- こういう定義と入力されたHTMLのDOMツリーを見比べながら操作していく
- https://github.com/ampproject/amphtml/blob/master/validator/validator-main.protoascii#L2121
tags: { # <amp-img> tag_name: "AMP-IMG" # <amp-img> is whitelisted for <amp-sidebar>, otherwise: # disallowed_ancestor: "AMP-SIDEBAR" attrs: { name: "alt" } attrs: { name: "attribution" } attrs: { name: "placeholder" } attr_lists: "extended-amp-global" attr_lists: "mandatory-src-or-srcset" spec_url: "https://www.ampproject.org/docs/reference/amp-img.html" amp_layout: { supported_layouts: FILL supported_layouts: FIXED supported_layouts: FIXED_HEIGHT supported_layouts: FLEX_ITEM supported_layouts: NODISPLAY supported_layouts: RESPONSIVE } }
なにがよいか
- AMP HTMLの仕様そのものを手で実装すると,AMPバリデータの変更をアプリケーション側で都度再現することになる
- 「fontタグは使えない」といった条件はアプリケーション本体には登場せず,validator-main.protoasciiに書かれているだけ
- 将来的にfontタグを使えるようになったら,validator-main.protoasciiを更新すれば追従できる
バリデータとの違い
- バリデータは,validかどうかを判定する
- これは,invalidなところを消したり直したりする
- invalidだと分かったらなんとかしてvaidに直そうとする
だいたいできた
- ちょっとずつ作ってちょっとずつデプロイ
- デプロイする前に定量的に様子を見たい
デプロイする前に様子を見たい
- クロールを待ってSearch Consoleを見るのは時間がかかる
- 手元で起動して,まとめてバリデーションかけて様子を見たい
- 指定したURLをクロールして順番にバリデーションをかけてvalid率をレポートしてくれるツールを作ることにした
amp-error-collector
- Rubyで書かれたコマンドラインツール
- sitemap.xmlを指定して実行
- sitemap.xmlに載ってるURLを全て見て,AMPを探す
- AMPのページを全てバリデーションして,結果をMarkdownで出力する
実行
- sitemap.xmlのURLを指定して実行
- 開発中はlocalhostで起動したアプリケーション向きに実行する
% bundle exec -- ruby collect-errors.rb http://tsukurioki.hatenablog.com/sitemap.xml Error Report of http://tsukurioki.hatenablog.com/sitemap.xml I, [2016-06-23T15:10:27.721369 #79725] INFO -- : validate http://tsukurioki.hatenablog.com/entry/2016/06/20/090000?amp=1 I, [2016-06-23T15:10:27.924578 #79725] INFO -- : validate http://tsukurioki.hatenablog.com/entry/2016/06/20/033324?amp=1 I, [2016-06-23T15:10:27.934522 #79725] INFO -- : validate http://tsukurioki.hatenablog.com/entry/2016/06/22/092016?amp=1 I, [2016-06-23T15:10:28.086394 #79725] INFO -- : validate http://tsukurioki.hatenablog.com/entry/2016/06/19/095649?amp=1 I, [2016-06-23T15:10:30.955057 #79725] INFO -- : success I, [2016-06-23T15:10:31.060164 #79725] INFO -- : validate http://tsukurioki.hatenablog.com/entry/2016/06/19/005512?amp=1 I, [2016-06-23T15:10:33.135304 #79725] INFO -- : success I, [2016-06-23T15:10:33.227255 #79725] INFO -- : success I, [2016-06-23T15:10:33.247395 #79725] INFO -- : validate http://tsukurioki.hatenablog.com/entry/2016/06/18/213528?amp=1 I, [2016-06-23T15:10:33.287214 #79725] INFO -- : success I, [2016-06-23T15:10:33.352698 #79725] INFO -- : validate http://tsukurioki.hatenablog.com/entry/2016/06/17/082458?amp=1 I, [2016-06-23T15:10:33.406264 #79725] INFO -- : validate http://tsukurioki.hatenablog.com/entry/2016/06/13/234510?amp=1
待つこと数分
Error Report of http://tsukurioki.hatenablog.com/sitemap.xml # Errors - http://tsukurioki.hatenablog.com/entry/2016/05/16/010134?amp=1 - `94:4` Invalid URL protocol 'chrome:' for attribute 'href' in tag 'a'. # Result 308 / 309 = 99% success ---- Generated by [hitode909/amp-error-collector](https://github.com/hitode909/amp-error-collector)
便利
- コンバーターを変更したときには,このツールでリグレッションテストできる
- 定期的に実行すれば日々の監視にも使えそう
- ウェイトなしで並列に実行するので,他人に向けて実行してはいけない
はてなブログをAMP対応してわかったこと
- 複雑なことをしても,バリデータなど,開発を進めるためのツールは揃っているのでストレスなく進められる
- オープンソースなので,既存のツールで足りないときは,サイト全体をまとめてバリデーションするやつとか作れる
リリース
- 企業用のはてなブログMedia向けにリリース
- はてなブログPro向けにベータリリース
編集画面でのプレビュー機能
はてなでの他のAMP対応
日々の暮らし
こういうことをやっています
Search Consoleを眺める
- エラー出てないか見る
AMPの最新情報をチェックする
GitHubを眺める
AMPの公式のWordPress
- 新しいツールが出た!とか教えてくれる
- https://amphtml.wordpress.com/
ampタグのついたブックマークを眺める
- 日本語の情報もぼちぼち流れてきておすすめ
- タグ「amp」を検索 - はてなブックマーク
- 社内Slackの#ampにフィードを連携して流している
複雑なウェブサービスのAMP対応
はてなブログのように複雑なアプリケーションでもAMP対応できる
まとめ
- AMPの紹介
- 素朴なウェブサービスのAMP対応
- Quyoの話
- 複雑なウェブサービスのAMP対応
- はてなブログの話
おまけ
このプレゼンツールについて
はてなブログでプレゼン
- 見出しごとにスライド化
- ちょっとJSを書いて記事をプレゼンに
- #presentation でプレゼン開始
- fでフルスクリーン
はてなブログの便利機能からそのままプレゼン
- リンクそのまま押せる
- 他人のSpeakerDeckをそのままiframeで引用
- 画像をペーストでfotolifeにアップロード
- シンタックスハイライト可能
- 予約投稿して自動ツイート
- スマホでお手元で閲覧可能
- 右上の
<progress>
要素で進捗チェック
はてなグループには2006年から
10年前!!
hatena.g.hatena.ne.jp
まとめ
- AMPの紹介
- 素朴なウェブサービスのAMP対応
- Quyoの話
- 複雑なウェブサービスのAMP対応
- はてなブログの話
反応
sozai #yapc8ojiC
— 顧客満足度 (@fuba) 2016年7月3日
めっちゃハイテク #yapc8ojiC
— ソフトな銭ゲバ (@moznion) 2016年7月3日
https://t.co/WhsgcPdTdPってドメイン、強すぎる #yapc8oji #yapc8ojiC
— みひゃみひゃエール (@mihyaeru21) 2016年7月3日
AMPの説明分かりやすいけど、嬉しいねってwwww#yapc8oji #yapc8ojiC
— ごま は 入れ替わってる (@gomaaburamax) 2016年7月3日
AMP対応の話、ちょっと気になってたのでありがたい #yapc8oji #yapc8ojiC
— もし (@moshisora990) 2016年7月3日
フィードバックが雑 #yapc8ojiC
— ソフトな銭ゲバ (@moznion) 2016年7月3日
そうなんだよねー制限きつい#yapc8oji #yapc8ojiC
— ごま は 入れ替わってる (@gomaaburamax) 2016年7月3日
予想以上にスクロールしながらプレゼンされるの見やすい #yapc8ojiC
— timakin (@__timakin__) 2016年7月3日
<html ⚡> やばい #yapc8ojiC
— 顧客満足度 (@fuba) 2016年7月3日
⚡️ #yapc8ojiC
— timakin (@__timakin__) 2016年7月3日
<html ⚡️>もしくは<html amp> 謎絵文字だ #yapc8oji #yapc8ojiC
— パーセプトロン (@garasyo) 2016年7月3日
<html ⚡> 深夜のノリで仕様策定された感じある #yapc8ojiC
— ソフトな銭ゲバ (@moznion) 2016年7月3日
50KBのCSS... #yapc8ojiC
— 日本の漫画作品一覧_た行 (@side_tana) 2016年7月3日
Quyo の AMP 対応、実にスピーディだ。 #yapc8oji #yapc8ojiC
— ザネリ (@so_zaneli) 2016年7月3日
AMP、異様に画像まわりめんどい #yapc8oji #yapc8ojiC
— Yusuke Wada (@yusukebe) 2016年7月3日
「はい」「確かに」「そうそう」#yapc8ojiC
— timakin (@__timakin__) 2016年7月3日
画像のサイズを埋めなきゃ駄目なのとにかくめんどい #yapc8ojiC
— ソフトな銭ゲバ (@moznion) 2016年7月3日
ウェーまじか、画像の大きさ取得しなきゃいけないのかと思ったら一瞬だった #yapc8ojiC
— timakin (@__timakin__) 2016年7月3日
amp-hatenastar 作らないんですか #yapc8ojiC
— 顧客満足度 (@fuba) 2016年7月3日
なにそれほしい> HTMLtoAMP #yapc8oji #yapc8ojiC
— Yusuke Wada (@yusukebe) 2016年7月3日
チマチマ実装しかないか#yapc8oji #yapc8ojiC
— ごま は 入れ替わってる (@gomaaburamax) 2016年7月3日
AMP対応する人は絶対読んでおいたほうが良い資料出た https://t.co/FG4SC3UTgo
— Yoshifumi YAMAGUCHI (@ymotongpoo) 2016年7月3日
チマチマ実装エグい(・ω・)#yapc8oji #yapc8ojiC
— ごま は 入れ替わってる (@gomaaburamax) 2016年7月3日
ルームC hitode909 さんのトーク「はてなブログのAMP対応の話」の様子です! #yapc8oji #yapc8ojiC pic.twitter.com/B3YbifMR5X
— ヤパチーエイジアハチオウジ (@yapcasia8oji) 2016年7月3日
amp のブログって wordpress なのか #yapc8ojiC
— ソフトな銭ゲバ (@moznion) 2016年7月3日
おお、これは凄い。WebサービスのAMP対応の説明では最強記事では。 / “はてなブログのAMP対応で学ぶウェブサービスのAMP対応 #yapc8oji #yapc8ojiC - hitode909の日記” https://t.co/lxCtcjVZfc
— 辻正浩 | Masahiro Tsuji (@tsuj) 2016年7月3日
ひとでさんくんすごい。
— 辻正浩 | Masahiro Tsuji (@tsuj) 2016年7月3日
見える……見えるぞ……っ!
— 辻正浩 | Masahiro Tsuji (@tsuj) 2016年7月3日
週明け月曜に技術に疎い社長やディレクターから「うちのサービスもAMP対応しちゃってよ!1時間半でできるらしいよ!」と気軽に依頼されるエンジニアの姿が見えるっ! https://t.co/m6fCQFJnHx