モバイル環境でSpeaker Deckを快適に閲覧する方法

TL;DL

モバイル環境からmドメインの先頭に追加してアクセスすると良い感じにスライドが閲覧できます。

例)

https://speakerdeck.com/qrush/the-graphql-way-a-new-path-for-json-apis

https://mspeakerdeck.com/qrush/the-graphql-way-a-new-path-for-json-apis

概要

Speaker Deckはスライドを共有するサービスです。

特に大きなカンファレンスが開催された後はたくさんの発表資料がこのサービスにアップロードされるのでよく閲覧します。

Speaker Deckは、PCで閲覧する分には特に問題はないです。

しかしモバイル環境で閲覧すると少し残念です。

なぜならSpeaker DeckにはPC用のレイアウトしか存在しないからです。

通勤中にTwitterRSSを閲覧することはよくあると思います。

その時、タイムラインに流れてきた発表資料をスマートフォンから見ることはよくあります。

その度にPC用のレイアウトで表示されるのでとても不便に感じます。

なので、モバイル環境でSpeaker Deckを快適に閲覧できるサイトを作りました。

試しにスマホから https://speakerdeck.com/qrush/the-graphql-way-a-new-path-for-json-apis にアクセスしてみると確認できます。

もしPCからアクセスした場合はオリジナルのページへリダイレクトされます。

使い方

(1) Speaker Deckの発表資料のページにアクセスします

例えばこのようなURLです。

(2) ドメインのspeakerdeck.comの頭文字にmを追加します
(3) モバイル環境に最適なレイアウトになります

要するにこういうことです。

https://speakerdeck.com/qrush/the-graphql-way-a-new-path-for-json-apis

↓ mをドメインの先頭に追加

https://mspeakerdeck.com/qrush/the-graphql-way-a-new-path-for-json-apis

必要なことはこれだけです!

アクセスするとこのようなレイアウトになります。

f:id:razokulover:20180513155823p:plain

仕組み

このサービスはこのような流れで動いています。

f:id:razokulover:20180513155740p:plain

(1) まずhttps://mspeakerdeck.com/<user-name>/<slide-name>にアクセスします

(2) Firebase Hostingで動いているNuxt.js製のSPAページが表示されます

(3) URLを解析してユーザー名とIDを取得します

(4) 必要なパラメーターを付与してCloud Functionsにリクエストを送信します

(5) Cloud FunctionsではSpeaker Deckにアクセスし必要な情報を取得します

(6) 取得した情報を利用してスライドの画像URLを構築し表示します

苦労したところ

■ Firebase Hostingで動的ルーティングを使う

Nuxt.jsをFirebase Hostingで動かす時、デフォルトの設定では動的なルーティングに対応していません。

これを回避するためにはNuxt.jsのnuxt.config.jsに下記のような記述を追加する必要がありました。

{
  generate: {
    fallback: true,
  },
  router: {
    fallback: true,
  },
}

■ 最後のスライドが何枚目かを見つける

Speaker Deckのページにはスライドの総数に関する情報がありません。

なので、発表資料が何枚目で最後なのかがわかりません。

この問題を解決するためにスライド画像をいくつか先読みし、画像のレスポンスが404になった枚数を最後のスライドとして認識するようにしました。

具体的にはこのようなコードです。

// Find out total slide count by checking response of each imgs
const img = new Image();
img.onerror = () => {
  vm.slideCount = id - 1;
}
img.src = baseURL + id + ext;

■ ダブルタップでズームするのを防ぐ

iOS10からuser-scalable=noが無効になりました。

なので、iOS10以上の端末ではボタンをダブルタップするとズームされてしまいます。

これを防ぐためにtouchmoveイベントにイベントリスナーを設定して、ダブルタップを無効にしました。

具体的にはこのようなコードです。

containerElement.addEventListener('touchmove', (e) => {
  e.preventDefault()
}, false);

■ Cloud FunctionsのレスポンスをCDNにキャッシュする

Cloud FunctionsのレスポンスはFirebase Hostingにキャッシュできます。

具体的にはこのようなコードを書くだけです。

res.set('Cache-Control', 'public, max-age=300, s-maxage=600');

免責

最後に、このサービスはSpeaker Deckの非公式のサービスです。

特にスライドのURLはSpeaker Deckの画像を直リンクとして利用しています。

これはあまり良くない実装です。

もし、運営会社であるGitHub社からこのサービスを直ちに停止するように連絡があればすぐに対応します。

ソースコードはここにあります。

以上です。

※ mediumに英語で投稿してみようと思い、翻訳しやすそうな日本語を書いたら全体的に魂が抜けたような文章になってしまった...