1Password で SSH の鍵生成・管理、また Git のコミット署名を行うのが便利そう。今後はこれを使っていきたい

developer.1password.com

パスワード管理ソフトで有名な 1Password に SSH の鍵管理の機能が追加されていた。 新たにセットアップする機会がなかったのでスルーしていたが、セットアップ機会が訪れたので試してみたところ、思った以上に体験が良かった。

また GitHubSSH 鍵でコミットの署名・検証を行える機能が追加された。 これらが組み合さって、これまでの鍵管理やコミット署名と比べて手間無くセキュアに出来ることに気づいてきたので紹介してみる。

1Password での SSH 鍵生成/管理

まず、1Password 8 から SSH の鍵を生成 / 管理できるようになった。

blog.1password.com

詳しいやり方は上記のブログやドキュメントを見てもらう方がわかりやすい。

この機能を使った GitHub への鍵の登録イメージはブログにもあるこの動画を見てもらうと想像出来ると思う。

youtu.be

見ての通り、1Password 拡張を入れていればブラウザだけで SSH 鍵の生成と登録が出来るようになる。 自動で公開鍵をペーストしてくれるので、よくわからずに秘密鍵の方を貼り付けるといったこともなくなる。 さらに署名アルゴリズムのデフォルトが Ed25519 で生成するので、よくあるコピペそのままを使って RSA を利用するといったこともなくなる*1

1Password で生成した SSH 鍵を使い Git のコミット署名をする

次に 1Password で生成した SSH 鍵を使って Git のコミット署名を行うことについて説明する。

これまでも GitHub は GPG や S/MIME を使った署名・検証を行えたが、この8月の機能追加で SSH 鍵を使ったコミット署名の検証に対応した。

github.blog

そして2週間後、1Passwordを使いGitのコミット署名を行うブログが出た。これがビジネスのスピード感。

blog.1password.com

これも同じようにブログにある動画を見てもらった方がわかりやすい。

youtu.be

動画の通りわずか1分で署名用の鍵の登録と Git の設定が完了した。 上手く見せてるだけと思うかもしれないが、自分自身が試したときもこれと同じステップで設定が完了した。時間を使ったのはせいぜい 1Password に登録する名前を考えるくらい。

自分はこれらの機能が出る前から GitHub でコミット検証が出来るように設定していたが、1Password を使うやり方と比べたらはるかに手間や知識が必要と感じた。

基本的には GitHub が用意しているドキュメント通りにやれば出来るものの、GnuPGを入れたりCLI操作が必要だったり、コミットに署名するための設定を .gitconfig に追記したり等、様々な手順が必要だった。

コミット署名の検証を管理する - GitHub Docs

それがこの 1Password での SSH 鍵管理と GitHubSSH 鍵によるコミット検証対応で、非常に簡単な操作かつ追加のインストールを必要とせず行えるようになった。 このことの衝撃が多少なりとも伝わればと思う。

試してみた感想

既に書いてしまっているが、実際に試してみた感想や思ったことを書き出してみる。

SSH 鍵の管理を考えなくてよくなった

これまで真面目に鍵の管理を考えていたわけではないが、1Password に保存されることで全てをそちらに任せられる。

鍵の管理を意識するのは、特に端末を移行する際鍵をどう移行させるかといったときに考える。 もちろん移行はそこまで手間のかかる作業ではないが、面倒で新しく鍵を生成することもよくあった。

これが 1Password に保存されることで 1Password のセットアップさえ出来ればそれで済むことになり、管理だけでなく SSH 鍵のポータビリティが向上していると思う。

コミット署名の設定が楽

これは既に書いているが、コミット署名の設定が非常に楽になった。

追加のインストールが必要ないだけでなく、1Password が自動で .gitconfig に追記してくれるので、ボタン1クリックでコミット署名の設定が完了した。 デフォルトでコミット署名を行うようになるので、ユーザーは何も意識せずに署名と検証が出来るようになる。

これまでは設定が手間でコミット署名を行ってこなかった人も、こんなに簡単に出来るのなら設定しておくかと思うのではないか。

全ての開発者に Git のコミット署名をお願いしやすくなった

Git のコミット署名・検証は行えた方がよいとされているはず*2GitHub でどのアカウントによる変更か正しく追跡できるようになるし、Branch Protection Rule で署名付きコミットのみに制限することも可能になる。

しかし、Git のコミット署名は面倒だったので設定しないことが多かった。自分も面倒さのために最近まで設定できていなかった。 自分自身が出来ていないので、他人に勧めたりチームや会社のルールにして必須化するまでは考えにくかったが、この 1Password と GitHub の機能追加によって状況が変わったように思う。

ターミナル操作を行わなくても10クリック程度でコミット署名の設定が行えるようになったし、1Passwordで鍵のポータビリティが上がったことで鍵の移行も間違いなく出来る。

この利便性の向上によって、全ての開発者に Git のコミット署名の設定をお願いしやすくなったと思う。 ここでの開発者はエンジニアだけでなく、デザイナーなどの職種も含んでいる。

コミット署名はやれた方がいいが、他に優先させることがあれば後回しになる類の設定になると思う*3。 署名しなくても Git は使えるし、設定不備によるサポートの手間も考えなくてはいけなくなる。 署名によるセキュリティの向上具合を考えたら、他に取り組むべき課題を優先させることがあってもおかしくはないだろう。 しかし、10クリック程度で簡単に設定できるなら、簡単なので署名をしようという方向に出来ると思う。

SSH 鍵の管理と Git のコミット署名の設定の体験が良くなったことで、特別なことをせずにセキュリティを向上させられていると感じている。 このことは 1Password もブログに書いていて、複雑さを無くすことでセキュリティリスクを下げられることについて書いている。

blog.1password.com

気になるかもしれないこと

懸念もないわけではないので、書いておく。

SSH 鍵のパスフレーズを設定できない?

既にパスフレーズが設定されているものをインポートしたときは要求されたが、新規で作る際は要求されなかった。UIも見辺らないし今は実装されていないのかもしれない。

このパスフレーズ秘密鍵が窃取されたり、端末にアクセスされた際に利用されないようにするもの*4。 端末へアクセスについては 1Password のマスターパスワードで代替できているとしてもいいだろう。 一方秘密鍵が窃取された状況はカバー出来ていないかもしれない。 そう考えるとこれはやや微妙に感じるポイントかもしれないが、そもそも 1Password 保管庫にある情報が窃取されている状況はもっと深刻な被害になるような気はする……。

秘密鍵クラウド上に保管していいのか?

秘密鍵をローカルPC以外に保存したことがなかったので一瞬考えたが、既に重要なサービスの認証情報を 1Password に置いているのなら何も気にすることはないと思い杞憂であると思った。 むしろ秘密鍵~/.ssh/ 以下にそのまま置いてあるより安全なのではないか。 これはもう 1Password をどの程度信用するかに寄ると思う。

SSH 鍵をコミット署名に利用していいのか

GPG の方が確実で信用できる、といった議論が出来る知識は乏しいのでここでは議論しない。

使いものになるかの話で言うと、1Password で管理することで鍵のポータビリティが上がり同じ SSH 鍵を利用し続けるコストが低くなったため、署名・検証が機能するのではと考えている。

まとめ

1Password で SSH の鍵生成・管理、また Git のコミット署名を行うことについて紹介した。

第一印象は今すぐにでも広めたいくらいだが、まだ気づいていない問題点があるかもしれない。 実際私用で試し始めたばかりなので、しばらく使ってみて改めて振り返ってみようと思う。

パスワードレスの世界が本当に来そうなタイミングで、1Password が開発者向けツールを模索していることはとても納得がいく。 複雑さを無くすことでセキュリティリスクを下げるといったことにも共感するので、これからの動向にも期待したい。

参考情報

自分の行っているセキュリティ関連の情報収集

聞いてるポッドキャストでセキュリティ情報収集どうしているのかといった話題があった*1ので、いい機会だから自分の行っているセキュリティ関連の情報収集をまとめてみた。

前提

  • どんな人
    • セキュリティに興味あるWebアプリケーションエンジニア*2
  • 興味の範囲
    • Webアプリケーションにまつわるセキュリティ全般
    • サービス開発・運用まわりに関するセキュリティ
  • 知りたい情報
    • 関係ありそうな脆弱性情報
    • 興味範囲の最近の話題やトレンド
    • その他セキュリティ関係で話題になっていそうなこと

話題やトレンドはキーワードを拾い後から調べられるように脳にインデックスを作っておくのが目的で、網羅や詳細に知ることはあまり意識していない。

情報ソース

前提に書いた知りたい情報を、各種サイト・ブログ、TwitterPodcast から収集している。 Twitter脆弱性情報などスピードが重要なものからトレンドまで幅広く知れてやっぱり便利。

サイト・ブログ

インシデントや脆弱性情報などのニュース的なものは Security NEXT で知り、ブログや発表などは はてなブックマーク に流れてくるものを見ている。 はてブに流れてくるものは関心ワード機能を使ってセキュリティに関する情報を集めるようにしている。

id:piyokango さんのブログは出来事を詳細にかつ客観的にまとめてくださっているので、理解の助けになる。 また、自分がでタイトルだけ見てスルーしていた出来事でも、ここで取り上げているのを切っ掛けに出来事を知ったり考えたりしているので、新たな視点を得る機会にもなっている。いつもありがとうございます。

CISA を見ているのは Known Exploited Vulnerabilities Catalog に追加される脆弱性を見てヤバそうな脆弱性を把握するため。本当は KEV の更新だけ見たいが、これだけ見るには ML に登録する必要があり、面倒で見なくなる気がしたので CISA の更新を丸ごと見ている。

他にも見ているサイトやブログはあるが、常に見ているのはこの4つが主。 他のサイトは大チェッカーにまとめておく。

Twitter

興味範囲の界隈の人をTwitterのリストに入れて見ている。 過去24時間分を遡れないくらいの人数は入れていない。今数えたら35アカウントだった。

これについては先人の方がまとめてくださっているのでそちらを参照しておく。

ポッドキャスト

日本語でセキュリティについて話すポッドキャストがいくつかあるので聞いている。

ポッドキャストは情報の内容を知ることはもちろんだが、情報そのものよりもそれを元に話される考察だったり話者の反応だったりが一番タメになると思って聞いている。 考察はニュース的なメディアだと得づらいし、テキストだと反応や雰囲気を感じにくい場合もあるので、ここがポッドキャストを聞く価値かなと思う。

また、雑談パートがあるなど聞いていて楽しくラジオ的に聞けるのも重要だと思う。 自分の性格かもしれないが、娯楽な要素があることで聞き続けられる面もあると感じている。

一時期英語圏ポッドキャストも登録していたが、英語のリスニングと内容理解を同時に行うことは今の自分にはやや負荷になるなと思いやめてしまった。いつか再チャレンジしたい。

情報収集に使っているツールと使い方

ここではツールの紹介。

  • Slack RSS
    • サイト・ブログの更新チェックに使っている
    • RSS リーダーも使っていたけど、これが一番定着した
    • Slack はずっと立ち上げているし、更新もわかりやすい
    • PC / スマホ / タブレット とマルチデバイスで同期も取れているというもの要素の一つかも
  • Twitter
    • リスト機能で気になる人のツイートを見るため
  • はてなブックマーク関心ワード
    • 話題になっている情報を見るため
    • ホットエントリーだと見たい情報を絞れないので、関心ワード機能で気になる話題だけ見ている
    • キーワードにしているのは Securityセキュリティ の2つ
      • 微妙に流れてくる情報が違うので、2つ入れることで網羅性を上げている
      • ただし、 セキュリティ の方は時期によってはサイバーセキュリティ以外の情報が多く流れてくるので注意が必要
  • Google Podcasts
    • ブラウザがあればどこでも聞けるのが便利で使っている
    • ただし質は微妙な気がするので、代わりになりそうなものがあれば検討したい

普段の情報収集の様子

毎日・週1、更新があればの3パターン。 全部丁寧に見ていると大変なので、ポッドキャスト以外はあまり時間をかけずにさっと流す程度にしている。

  • 毎日
    • Twitterのリストに入れている人の直近の更新を眺める
    • RSSの更新を眺める
    • 更新量は日に1回でも見切れる量だが、2,3回に分けてみると丁度いい
      • 自分は暇になったり休憩中に見たりしている
  • 週1
    • はてなブックマークの関心ワードを1週間分眺める
      • 週に1回会社のセキュリティ会という集まりがあるので、それにあわせて見る
      • 全部見るのではなく、気になったページを開く程度
      • 読むのに時間がかかりそうなものはブラウザのタブで開きっぱなしにしていたり あとで読む 系ものに放り込んだりする
    • セキュリティのアレを聞く
      • 月曜の夜更新なので、だいたい火曜の午前中に聞いている
  • 更新があれば

まとめ

自分のセキュリティ関連の情報収集のやり方をまとめてみた。 書き出してみると、結構色々やっていることに気がついた。

インプット分のアウトプットやそれ以外の何かが出来ているのかと言うと微妙な気もしてきたので、今後はアウトプットの方も意識していきたいなと思う。 まずは感想をツイートしてみるくらいから始めていきたい。

Best practices for writing Dockerfiles読んだメモ

docs.docker.com

何これ

  • Docker 公式ドキュメントにある Dockerfile の書き方のベストプラクティスがまとまっているページ
  • 巷に書いてあるような意識したいことや具体的なプラクティスがまとまっている
    • build context を理解しましょう、multi-stage buildを使いましょう、Dockerfile 命令の良い書き方 etc...
    • イメージサイズを小さくしたり、ビルドスピードを高速にしたりするプラクティスが目立つ
  • これまで雰囲気で Dockerfile を書いていたりプラクティスをつまみ食いしているだけの状態だったいので、改めて読んでみた

感想

  • build context について色々書かれていたのは発見
    • これまであまり意識していなかった
    • 確かにビルドサイズやスピードを抑えるために、必要なファイルしか見ないようにするのはその通り
    • セキュリティ的にも余分なファイルを加えないのは正しそう
  • 標準入力から docker build できるのは知らなかった
    • 1回限りのビルドや Dockerfile を保持し続けない場合などにいいらしい
    • 「ビルドコンテキストを省略すればもっと早いぞ!」みたいに書かれていたのは面白い
    • ただしサービス開発の場面で使えそうな時がパッと思い浮ばない
    • ツール的な使い方をするものだったら使いどころがあるのかも
    • git レポジトリなどをビルドコンテキストに出来る remote build context は使い道ありそう
  • ENTRYPOINT のコンテナ起動時にヘルパースクリプトを実行させるテクニックは使えそうで、覚えておきたい
    • 色々なイメージがこのやり方を使って機能を提供している*1*2ので、自分で使わなくても知っているとトラブルシュートの場面で役立ちそう
  • セキュリティのプラクティスがまとまっていないのは気になった
    • セキュリティの側面で書いてないだけな気もする
    • ビルドコンテキストを絞ったり、イメージサイズを減らしていくのはセキュリティの面からも良いプラクティスではあるだろう
    • とはいえ別の文書で当たった方がよさそうに思える
      • root を避けましょうとか書いてあるけど、あんまりハッキリ言ってなくて「あれれ?」といった感想を持った
    • 以前話題になっていたこの記事辺りがよいのだろうか

余談

アクセシビリティに興味を持ち始めたきっかけ

アクセシビリティの琴線に触れるいくつかのアプローチ の記事を読んで、自分がアクセシビリティに興味を持ち始めたきっかけについて書き残しておきたくなったので書く。

自分の場合はアンチャーテッドというゲームのメイキングインタビュー動画をみたのが、アクセシビリティを意識するようになったきっかけになっている。

5分程度の動画なのでまずみてほしいのだけど、一部暴力的なゲーム内シーンもあるのでこういうのが大丈夫な人は再生ボタンを押してほしい。

www.youtube.com

内容を要約すると以下のような動画になっている。

  • アンチャーテッド4というゲームは多くの人にゲームを楽しんでもらえるようにアクセシビリティに取り組んでいる
  • これまでのシリーズではボタンを連打するなどの複雑な操作が必要な場面で健常者の助けなしではクリアできなかったが、障がいを抱えたゲーマーの話をきっかけにアクセシビリティに取り組んだ
  • 過去作からのアクセシビリティ機能を拡大してボタン連打が必要なものを長押しに出来るようにしたり、色覚によって区別できない色を使っている部分を変更したりした

自分はこの動画をみて、かなり気づかされることが多いなと思った。

自分が出来ることが出来ない人がいること、出来ないことを出来るようにする実現の仕方、ゲームの操作が出来ないことはもうそのゲームを楽しめないということ。

出来ない人がいるなんてちょっと考えてみれば当然だったけれど、全然意識したことがなかった。

特に冒頭のインタビューが強く印象に残っている*1

開発者に気づいてほしい ぼくらにはゲームが単なる娯楽以上のものだと 障がいをかかえているとう憂うつさを忘れさせてくれるんだ 交流の機会も与えてくれる 外見で判断されるんじゃなく ゲーム内での行動やその結果だけで判断される機会だ

印象に残ったのは当時の自分の立場ともリンクしていたからもあると思う。

自分は当時*2Web小説サイトの開発に関わっていて、ここではユーザーさんが小説を書いて自分の考えた物語を表現したり、読んでその世界に浸ったり、感想を述べて交流したりしている。 これはインタビューで言われていた ゲーム内での行動やその結果だけで判断される機会 と同じだし、サイトが使えないことはこの機会がないことになってしまい、すごく残念な気持ちになった。

このように自分に置き換えてみると、アクセシビリティに対して「あ、これって大事なことだ」と素直に思い、以来アクセシビリティについて興味を持ち始めた。

琴線に触れるいくつかのアプローチでいう「人権」や「福祉」に近いきっかけだったと思う。

もちろんこれはゲームの販促動画なので、エモい発言や見せ方になっていると思う。 動画内では語られていないけど、法律などの要請もあった可能性もある。 けれどもおかしなことは言っていないし、タイミングもあっただろうけど自分が意識するきっかけになってくれた。その意味でとてもいいインタビュー動画だと思う。

これまで普段WebサービスのUIを実装する時はブラウザなどのユーザーの環境の違いを考えて動くように実装することはあっても、そもそもそのUIを使えない人がいるところまでは正直想像できていなかった*3。 やっぱりアプリケーションエンジニアとして多くの人が使えるサービスを作っていきたいなと思うし、アクセシビリティは良いサービスを作る技術的な意味でも自然に受け入れられた考えだったし、面白いとも感じた。

恐らくこの先どんなものを作る場面でも、それこそWeb/Appアクセシビリティに限らず全ての人が利用できることを意識だろうから、この気づき方はよかったと感じている。何をするにしてもこの考えはもっていたいと思う。

最後に、アンチャーテッドと同じスタジオが制作したThe Last of Us Part IIを全盲の人がクリアした記事を貼っておく。 このゲームも自分もプレイしていたゲームで、目が見える自分でもちょっとやっかいだなと感じる敵がいたのに、それを目が見えなくてもクリアできるのかと驚いたことが強い印象だった。

automaton-media.com

*1:この人はDAGERSystemというゲームのアクセシビリティ関するメディアの編集長で、アンチャーテッドを開発している会社のノーティドッグアクセシビリティについて話した人。

*2:2021年現在も

*3:環境の違いを想像し切れていなかったという話ではある

Webブラウザセキュリティ読んだ

年始に話題になったWebブラウザセキュリティの本をようやく読んだ。

Webブラウザセキュリティ ― Webアプリケーションの安全性を支える仕組みを整理するwww.lambdanote.com

なんとなく知っているつもり・名前は聞いたことあるのような概念や仕様を、それが作られた背景から丁寧に説明されていてとてもわかりやすかった。 特にOriginやCSPの章では「そもそもどういう攻撃から守ろうとしているのか」「その攻撃に関する基本的な知識は何か」から説明しているので、頭にすっと入ってくる。

デモ環境を Docker 上で試せるのもよくて、サクっと立ち上げてブラウザで動作を確かめられるのはこれまでの手元で試す系のものよりも体験がよかった。

著者とレビュアーの対談記事も出ているので、そちらも合せて読んでみると良さそう。読みながら感じていた、Webセキュリティの過渡期感と攻撃を受けないように制約をかけていきつつも後方互換性を保つ努力について語られていてよかった。

本の内容とは関係ないけど、紙の本とPDFを行き来するのは便利だった。ラムダノートのサイトで買うと紙書籍と一緒にPDFもダウンロードできて、それをiPadに入れて気分によって行ったり来たりしながら読み進めていた。

技術書の類は基本紙で読みたいのだけど、シュッとこの単語をググりたいとか、デモ試すときにページを保ちながらやるのややこしいなとなったときに電子で読めるのはとても便利だった。

以下箇条書き感想

  • CSP改めてムズいなと思った
    • 既存の挙動を実現できつつ制約はかけたいのはわかりつつも、制約の掛け方色々ありすぎて笑ってしまった
  • というかセキュリティ対策をちゃんとやるというのがそもそもムズい
  • セキュリティの問題があるWebの機能を塞ごうと思っても、それを塞ぐことによってこれまでのWebが壊れるので困るというのがよくわかる
  • 引用元の論文やブログの数が多くてすごい

Emacsのlsp-modeが遅いときはlsp-doctorを見てみるといい

emacs-lsp.github.io

タイトルと↑のリンクでFAなのだけれど、EmacsのLSPクライアントであるlsp-modeで補完などの動作が遅いなと感じたときは M-x lsp-doctor とやると遅い原因を列挙してくれる。

Emacsのデフォルト設定値ではlsp-modeの利用に最適ではない場合があるのは、言われてみればその通りなのだけど完全に失念していた。 lsp-mode側でよしなに書き換えてしまってもいいのに……と思ったけど、それをやるのは流石に思想の違いがありそう。

自分の場合はGCが発生するメモリの閾値gc-cons-threshold と、一度の読み取り操作でサブプロセスから何バイト読み取るかの read-process-output-max の値を調節すると、補完候補が出る速度が体感でわかるほど早くなった。 元々候補が出るのに一瞬ひっかかるなと感じる程だったので、明らかに体験が良くなった。

lsp-mode 遅いなと感じている時は試してみるとよさそう。

※ 追記 v7.0 までは lsp-diagnose って名前だったらしい

github.com

ページのコンテンツから離れたタイミングのブラウザイベントの選び方

これは はてなエンジニアAdvent Calendar 2020 1日目のエントリーです。

ブラウザに何か表示させるアプリケーションを作っている人は、ブラウザのAPIやイベントの発火タイミングについて調べる機会が年に何度かあると思います。今回はそんな調査の一つを紹介です。

知りたいこと

ユーザーがページから離れたタイミングを取れるイベントが知りたい。

  • ユーザーがページから離れたら際に行いたい処理があったので、契機となるイベントがほしい
  • ここでは「ページから離れた = ページのコンテンツを見ていないと想定される」とする。具体的には以下のようなタイミング
    • ページ遷移
    • タブ移動
    • ページ破棄 (タブ/ブラウザを閉じる)
    • 画面がロックされる
    • 別のアプリケーションに切り替える (PCなら画面の最小化/モバイルならアプリ切り替え)
  • beforeunloadイベントでタブやブラウザ自体を閉じる際に処理を挟めるのは知っていたが、タブの切り替えやPC/モバイルの画面がロックされた場合にも処理を行いたいので、何を使えばいいのか知りたい

結論

  • visibilitychangeイベントで「ページから離れた」のユースケース全てを満せるので、このイベントを契機に処理を行う
  • Safariではバグがあるので、一部pagehideイベントと合せて実現する
  • (未検証)IEではページ遷移時の処理が途中で打ち切られているような挙動をしているので、IEをサポートするのならbeforeunloadも合せて実現する

以下この結論に至った過程を紹介。

調査と検討過程

基本方針

改めて対応したいことは「ページから離れた = ページのコンテンツを見ていないと想定される」タイミングで発火されるイベントが何かということ。

このケースは全てPage Visibility APIで対応できる。

developer.mozilla.org

visibilitychangeイベントが発火し、 visibilityState === 'hidden' であれば「ページから離れた」と判断できるので、このタイミングで処理を行えば良い。 Can I Useを見る限り主要ブラウザではサポートされているので、気にせず使っていけば良さそう。

ただしSafariにバグがある。

Safari向け対応

Can I UseのSafariの注釈[3]を読むと、こう書いてある。

https://caniuse.com/mdn-api_document_visibilitychange_event

Doesn't fire the visibilitychange event when navigating away from a document, so also include code to check for the pagehide event (which does fire for that case in all current browsers)

(意訳) visibilitychangeがページ遷移時に発火しないので、このタイミングではpagehideを利用する必要がある

そんな……。

ページ遷移時だけを考えるならpagehideのみを使えばよいが、今回はページから離れた時全般なので、visibilitychangeとpagehideのそれぞれで処理を行う必要がある。

このときvisibilitychangeとpagehideの両方に処理を登録すると、ページ遷移時に2回処理が実行されてしまうので、Safariのみpagehideイベントに行いたい処理を登録する必要がある*1

このSafariのバグについて、WebKit Bugzilla見てみると 2020/09/25 時点で更新がある。もしかしたら近いリリースでの修正が期待できるかもしれない。

IEの挙動について

IEではページ遷移時にvisibilitychangeやpagehideのイベントが発火はしているものの、処理が終わり切らず途中で終わっているような挙動をしているように見えるため、代替手段が必要になる。挙動は深く追ってはいないものの、beforeunloadなら処理を最後まで終了させているようなので、IEをサポートする必要があるならこれを利用する必要もあるだろう*2

以上をまとめると以下のようなコードになる。

const doSomething = () => { /* ページのコンテンツから離れた際の処理 */ };

document.addEventLisnter('visibilitychange', () => {
  const state = document.visibilityState;
  if (state === 'hidden') {
    doSomething();
  }
});

if (isSafari()) {
  window.addEventListener('pagehide', () => {
    doSomething();
  });
}

if (isIE()) {
  window.addEventListener('beforeunload', () => {
    doSomething();
  });
}

調査過程で得た情報

調査の過程で得た、他にも応用できそうな情報を上げておく。

Page Lifecycle API

developers.google.com

ページが開かれてから閉じるまでの状態やイベントの遷移をまとめたもの。

これを読んでおけばページの状態にまつわる処理を書きたくなった時にサッと参照出来てお得。ただしPage Lifecycle API自体はChromeでしか実装されていなさそうなので、あくまで参考程度に止めた方がよさそう。

ライフサイクルをまとめた図を見ると、モバイルのネイティブアプリのライフサイクルと似たイメージなのかなとも思ったりする。

またbeforeunloadで何か処理を行うのは、ページ離脱時のユーザー体験を損ねる可能性があるので、保存前の変更を警告するため だけ に使うべきなど、Legacy Lifecycle APIの節で言及されており、勉強になる。

デバッグ便利情報

event-logger.glitch.me

WebKit BugzillaのIssueコメントにあった、動作確認用のglitch。visibilitychangeやpageshow/hideの発火毎にログを表示してくれるもので、今回のAPIの挙動理解の助けになった。

また実装がデバッグの手段の一つの参考になる。素朴なイベントの動作確認方法だと、イベント発火時にconsole.debugでコンソールに出力させるのがあるけど、今回は発火のタイミングがタブやブラウザを閉じるまで含まれるのでコンソールから消えてしまう。このglitchではローカルストレージにイベント発火のログを残しており、タブやブラウザを閉じても消えないようにしている。

ローカルストレージに残す発想は考えてみたら当たり前ではあるが、使ったことの無い手法なので参考になる。

まとめ

ページのコンテンツから離れたタイミングのイベントの選び方とその検討過程について紹介した。Page Visibility APIやライフサイクルの図は覚えておくと便利なタイミングがありそう。

ほしいブラウザのAPIを調べるのが最初だったけれど、ページのライフサイクルだったりデバッグテクニックまで知れてお得な題材だった。

明日は id:nabeop さんです!

*1:ブラウザによる条件分岐を避けたいのなら、行いたい処理をべき等にしたり、処理が実行されたらフラグを立て1度しか実行されないようにするなども考えられる。

*2:同僚の id:koudenpa さんが挙動回りを確認してくれた。