はてなにおけるPortals
株式会社はてな Pasta-K / hitode909
アジェンダ
マンガビューワ特有の苦労
Portals以前のアプローチ
マンガビューワへPortalsの導入デモ3連発とその開発中の知見
Portalsへの期待
自己紹介(1)
pastak.icon Pasta-K
京都大学工学部情報学科 在籍中
株式会社はてな マンガチーム アルバイト 主にフロントエンド
Notaでスクリーンショット共有サービスGyazoのフロントエンドもやってます
自己紹介(2)
hitode909.icon hitode909
株式会社はてな マンガチーム サーバーサイドとフロントエンド
インターネットが好きで、自分のブログで新しいブラウザのAPIの練習をしている
はてなにおけるPortals
二人の所属するマンガチームでの取り組みを紹介します
GigaViewerについて
サーバーサイドでの画像や書誌の取り込み+更新情報を伝えるメディア面+いい感じに表示するビューワで
2017年1月リリース
現在7サイトに対応
いろんなサイトに同じビューワ・アプリケーションが導入されている
よく見るといろんな違い
オフラインに保存する機能や、目次機能など
ウェブブラウザで快適に漫画を読めるマンガビューワ
URLを開くとすぐに読み始められる
スマホでもPCでもタブレットでもブラウザさえあればOK
とはいえ、ほとんどスマホなので余計な帯域を使わないように
ブラウザで出来ることをドンドン取り込んで進化させている
GIFアニメ埋め込み・フルウィンドウ・オフラインなどなど
アプリケーション全体の設計
さまざまなサイトのコードベースは共通
管理しやすく、あるサイト用に作った機能の横展開を容易に
1行書いたら新機能が追加される
アプリケーションサーバーも共通
サイトによって更新スケジュールがちがうので、サーバーを束ねてトラフィックのスパイクに強く
マンガの更新直後にアクセスが集中するという特徴がある
フロントエンド側も色々なことをしながら、ビューワーなどが共通で在れるようにしている
マンガサービス固有の課題と、高速化へのアプローチ
一般的な話題として
サービス全体の速度
WebPを試している
動的なリサイズが不要なところから練習
ビューワーでは幾つかの問題があって利用できていない
何のための速度を求めるのか
画像の先読みが必要である
サクサク読み進めたい。ページをめくるたびに待ち時間が発生してしまう
次のエピソードの先読みが必要である
「連載」という形でさまざまな作品の最新エピソードが毎日公開されているので、たくさん読んでほしい
→紙の単行本や雑誌に負けないように
地下鉄など、回線状況が悪いときにも読みたい
無駄な通信をしたくない
最新話を読みたいこともあれば、1話から一気に読みたいパターンもある
アプリケーションが遅いと読書体験悪化
ページ読み込み高速化が体験に直結する
大量の画像を表示する
プレミアムユーザーになると雑誌をまるごとブラウザで読める
分厚い雑誌は700ページくらいある
ビューワの設計
2015年にジャンプルーキー用にjQuery, MVPアーキテクチャパターンで実装
その設計をひきついでGigaViewerも実装
touchイベント等をハンドリングして自前でページめくりを管理
現在表示中のページを管理することで、画像の遅延ロードを実現
ページ遷移へのアプローチ
2018年夏のインターンで画面遷移を高速化
ビューワ→ビューワのみ
MVPアーキテクチャからReactなどを使ってSPAにする難しさ
フルスクリーンで読み続けたい→次の話に行くとフルスクリーンが解除されて不便という話題もあった
他のモダンブラウザでは解除されるが、Safariでは解除されないまま遷移してしまう
手作り画面遷移の課題
実装が難しい
ページ遷移で変わる部分と変わらない部分を分ける
取得するまで読めるか読めないかわからない問題
遷移先が読めるビューワでないときは普通の画面遷移にフォールバック
動けば良いだけではなくサードパーティのグッズとの兼ね合い
計測、広告、SNSウィジット
通常はブラウザがやってくれている機能をページ内部に実装することになる
プログレスバーを手作り
ページを開きっぱなしにしたときに古いコードが動き続ける
毎日デプロイしてると昨日のJSはもう動かないということがある
そこでPortals pastak.icon
Portals触ったことある?
動画は見た
色々遊んでみている
仕様を読んだ
はてなマンガチームとPortals
uskayさんにご紹介頂いて、昨年のからぼんやりと試していて、4月くらいから本格検証をしています
GigaViewerでどう使えるかデモをしたりしながら、方向性を探っている最中
検証の過程で見つけたことをchromiumのissueで積極的に還元しています
GigaViewerでのデモ
3連発紹介します
※ 画面は開発中のものです
デモ①
巻末の次のページへの遷移のところにPortalsで自作の冒頭ページを埋め込む
https://youtu.be/jUYqdiw-RPk
デモ②
埋め込む箇所を左下に
カウントダウンさせて5秒経ったら次の作品へ移るみたいなのもやったけど、動画内には無いです
今のところactivate()はユーザージェスチャーを要求しないので出来る
https://youtu.be/GE6xE-3ZiKg
デモ③
メディアトップからビューワーを開く
ビューワーの裏にはadoptPredecessorでトップページを埋め込んでいる
https://youtu.be/A9MAcJWigDY
開発中のエピソード
デモを色々作っていたときのエピソード紹介のコーナー
現状のPortalsの使用感
<portal src='...'></portal>書くだけでウェブサイトを埋め込めて、適当なタイミングでactivate()呼べば遷移してくれるのでとにかくお手軽
ちょっとした体験の向上やページ遷移の高速化のためだけだったら、これで十分。数分で取り込める。
他のウェブサイトがによってPortalsで埋め込まれた際に体験を提供することも出来そう
デモでは、window.portalHostがあるときだけ、1ページ目の画像を表示するようにしています
ページ遷移を手作りしていたのを代替出来る+表現力とpreloadがアップ
iframeの代替ではなくて、preloadと画面遷移の体験の向上の為に利用している
preload的にページを先に読んでDOMなどの構築も終えているのでスピードアップ
adoptPredecessorがあれば前のページ(BrowserContext)に戻れる
pushStateとかでやっていたのをPortalsに移譲出来る
ページ遷移ではなく、前のページがそのまま保持される(うつのみやさんも話されそう)
ページ内での状態をリストアする必要がないので便利、ここはiframeとpushStateでは作りきれない部分
手作りの課題が解決される
取得するまで読めるか読めないかわからない問題
→画面内に表示できるのでユーザーにフィードバックは返せる
→postMessage、activate(data)、window.portalHost
通常はブラウザがやってくれている機能をページ内部に実装することになる
→プログレスバー作らなくて良くなる
困ったところ
ブラウザのヒストリーバック出来ないの仕様ではなくバグらしい
計測、広告
普通に作るとJSがPortals内でも動いてしまうので、PVが倍になったりしませんか
行って戻った場合にページの訪問を増やすべきなのかそうでもないのか
Portalsとして埋め込まれたPVが増えるのはよいが、広告のインプレッションが増えてしまうのはまずいのではないか
window.portalHostとかをみて制御したらよい?
アニメーションと組み合わせて遷移させたりすると、adoptPredecessorを使って戻ってきたときにその状態が維持されている
activate()で遷移した後にバックグラウンドでJSとかでゴリゴリ元に戻しておく
これ結局SPAとかの辛さがあるのでは🤔
今後への期待
開発者ツール
Portalsをinspect elementしたい
クリックしても選択できない
onclickでactivateしている場合、activateされてしまう
Portalsの前後の要素をinspectして、そのまわりをたどっていくとinspectできている
遷移時にDevtoolがdeactivateされてしまうので、上手い感じになってほしい
Portalがループしたときに無限に読み込みが続く hitode909.icon
<portal src="."></portal>すると自分自身を読み込み続ける
自分自身を参照することはないにせよ、相互に参照する場合はありそう
リダイレクトループの検知みたいな感じで防いでもらえるとうれしそう
X-Frames-Option相当のものが入るらしい
We should explicitly cover how this specification interacts with CSP, RFC7034 and other specifications that confine the behavior of frames. 読み込まれる側でもそうだし、読み込む側でも制御したいですね
読み込まれる側で制御したい場合(X-Frame-Optionsのようなイメージ)→ログインページとかを知らない外部サイトにPortalsとして貼られてしまうのは怖い
Content Security Policyは見てくれている
Portals内がフィッシングサイトにすりかわっていると怖い
標準化と他のブラウザでの導入の温度感どうですか?
Chromeだけでしか入ってない状態で大きくブラウザに依存するUXを作るのは怖い
PortalsはそれくらいUI/UXに大きな影響を与える要素だと感じています
特にadoptPredecessorが非常に強力でPortalsの魅力を体現している
<portal><iframe><img alt=...></iframe></portal> で回避するのは?
portalを使って認証して、戻ってくることで、ブラウザをリロードしなくてもよい、という体験を作れる
はてなブログを見たときにログインしていない→グローバルヘッダをPortalsにする、というユースケースを話していました
<iframe>やhistory.pushStateを組み合わせてもpolyfillできない
<iframe>は親フレームにネストする形でブラウザコンテキストを共有している。Portalsはそうではない。
まとめ
Portalsは非常に強力な武器
ページ遷移体験を簡単に向上できる
まだまだ発展途上という認識
ドンドン遊んで試して良いものになるように貢献していきたい
左下に埋め込むようなデモくらいだと代替可能なので、まずはそれくらいからやってみると良いかも?
We are hiring! hitode909.icon
https://developer.hatenastaff.com/intern2019 https://cdn-ak.f.st-hatena.com/images/fotolife/h/hatenatech/20190516/20190516190954.png
↑これもPortalsにしたかったけどScrapboxのContent Security Policyに阻まれて失敗
code:a.js
const portal = document.createElement('portal');
document.body.appendChild(portal);
portal.style = 'position: fixed; right: 10px; bottom: 10px; width: 300px; height: 200px;z-index: 99999';
portal.addEventListener('click', () => portal.activate());
https://gyazo.com/8d95ca69ca52e5579369fa935f9289bb
Portalsでインターン来てくれを体験できるURL
Question?