Slide 1

Slide 1 text

UserAgentに依存した分岐を捨てられるか (または何故捨てられていないのか) Pasta-K 2024-10-12 at ToKyoto.js #2

Slide 2

Slide 2 text

About me • Pasta-K • x.com/pastak • github.com/pastak • Kyoto.jsオーガナイザー • 京都市出身・在住 • Helpfeel&はてなで働いています

Slide 3

Slide 3 text

このトークについて • 先日、bowserのv1からv2への移行を遂にやることにした • memo: bowser-js/bowserに移管されてメンテが再開している • その過程でUserAgentで判定している箇所を削ったり整理したりした • UserAgentを使わないように出来れば良いが、一方でなかなか捨てられない のが現実でもあるなと改めて思った • 現状取れる手立てなどをもう一度整理して、これからどうすれば良いのか

Slide 4

Slide 4 text

UserAgentを元にした条件分岐 • やっているコードがまだある人〜 !

Slide 5

Slide 5 text

UserAgentの現状 - Chrome • Chromeはフィンガープリンティング対策でnavigator.userAgentなどで取得 できる文字列の情報量を削減 • Versionのメジャーバージョンより下は全て0になるように • • User-Agent Client Hints(UA-CH)に移行を促している

Slide 6

Slide 6 text

UserAgentの現状 - Firefox & Safari • Firefox • UA-CHには反対している • https://github.com/mozilla/standards-positions/pull/579 • パフォーマンスへの懸念・将来の仕様への懸念 • Safari • UA-CHに未対応 • 一度UAのバージョンの凍結を実施しようとするも断念 • SafariのUA文字列が固定されて固定されなくなったおはなし - fragmentary

Slide 7

Slide 7 text

iPadと画面幅とUserAgent • iPadは画面幅に応じてUserAgentが変更される • 画面幅が広いときはIntel Macと同じように見える • 例: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/ 605.1.15 (KHTML, like Gecko) • 画面幅が狭いときはiPadと分かるiPhoneとも異なるUAになる • 例: Mozilla/5.0 (iPad; CPU OS 13_0 like Mac OS X) AppleWebKit/ 605.1.15 (KHTML, like Gecko) Mobile/15E148 • 画面幅が変わったときに動的に変わることはない

Slide 8

Slide 8 text

iPadでSafariを2つ横並びしてGoogleでshow user agentと検索した結果のスクリーンショット

Slide 9

Slide 9 text

ざっくりUA-CHとは • サーバーからのResponse Headerを 使って、必要な情報を宣言すると、 後続のRequest時に付与される • `navigator.userAgentData` でも アクセス可能 • 重要な値は `Critical-CH` を付与す ると、Chromeがその値を追加した 再度のリクエストが実施される IUUQTEFWFMPQFSTHPPHMFDPNQSJWBDZTBOECPYQSPUFDUJPOTVTFSBHFOUΑΓ

Slide 10

Slide 10 text

そもそもUserAgentを使いたいケースとは? MDNの記述(*)より • 特定の機能が利用出来るか確認したい • ブラウザの特定のバージョンに存在しているバグを回避したい • ブラウザや端末に応じて異なるHTMLを返したい IUUQTEFWFMPQFSNP[JMMBPSHKBEPDT8FC)551#SPXTFS@EFUFDUJPO@VTJOH@UIF@VTFS@BHFOU

Slide 11

Slide 11 text

特定の機能が利用出来るか確認したい > ユーザーエージェントによる判定は決して行うべきではありません。その代わりに常に機能の検出を 行う代替手段があります(*) • Feature Detectionとして代替手段はよく知られている • 各種APIやHTML要素の属性などのサポートの有無を検出する • navigator.serviceWorker • 'name' in HTMLDetailsElement.prototype • CSSの機能をサポートしているかを検出する • CSSで @supports () • JSで CSS.supports メソッドを使う IUUQTEFWFMPQFSNP[JMMBPSHKBEPDT8FC)551#SPXTFS@EFUFDUJPO@VTJOH@UIF@VTFS@BHFOU

Slide 12

Slide 12 text

CSSのFeature Detection: @supports 具体的にはこういう感じ and, orやnot なども使える ίʔυ͸IUUQTEFWFMPQFSNP[JMMBPSHFO64EPDT8FC$44!TVQQPSUTΑΓ

Slide 13

Slide 13 text

CSSのFeature Detection: @supports Selectorのサポートの有無の確認 JSのコード上でこの情報を利用したい場合は、同様にCSS.supportsに渡せばOK IUUQTEFWFMPQFSNP[JMMBPSHFO64EPDT8FC"1*$44TVQQPSUT@TUBUJDΑΓ

Slide 14

Slide 14 text

ブラウザの特定のバージョンに存在しているバグを回避したい > 専門のフォーラムで見たり尋ねたりしてみましょう。この問題に最初に遭遇したのがあなたであるこ とはほとんどありません。また専門家、あるいは別の視点を持つ人々が、バグを回避するためのアイデ ィアをくれるかもしれません。(*) • そうは言うものの、どうやってもワークアラウンドで回避のできない致命的なAPIのバグに遭遇する ときもある • バグトラッカーを見ると修正されているが、修正が入るのは次のリリース以降のバージョンであるこ とが多い • Chromeは比較的最新版に上がる環境が多いが、SafariはOSと紐付いていてアップデート頻度が… • 「各ブラウザの最新版のみをサポートしています」と書いていても、実際はもっとサポートする必 要があるのが常 • 辛い・・・ IUUQTEFWFMPQFSNP[JMMBPSHKBEPDT8FC)551#SPXTFS@EFUFDUJPO@VTJOH@UIF@VTFS@BHFOU

Slide 15

Slide 15 text

ブラウザや端末に応じて異なるHTMLを返したい > 形式的な
または 要素を追加することで、それを防ぐことがで きませんか?ユーザーエージェントの検出を正しく行うことは、 HTML の純度 をいくらか損なっても構わないくらい難しいものです。また、デザインを考え 直してください。プログレッシブエンハンスメントや流体レイアウトを使用す ることで、回避することはできませんか?(*) • 出来たら困らないけど、実際問題として結構難しくないですか? • ??「レスポンシブってやつに移行すれば、モバイルでもタブレットでもPCで も同じHTMLでいけるっしょ〜」 IUUQTEFWFMPQFSNP[JMMBPSHKBEPDT8FC)551#SPXTFS@EFUFDUJPO@VTJOH@UIF@VTFS@BHFOU

Slide 16

Slide 16 text

画面幅に応じて表示する要素やCSSを変更する • JavaScriptでMediaQueryListを使用する const mql = window.matchMedia("(max-width: 600px)"); const element = document.querySelector('.text'); mql.addEventListener("change", (e) => { if (e.matches) { element.textContent = 'ڱ͍ը໘'; } else { element.textContent = '޿͍ը໘'; } }); • CSSで@mediaを使用する @media (max-width: 1250px)

Slide 17

Slide 17 text

画面幅に応じて表示する要素やCSSを変更する • ReactなどでMediaQueryListに応じて返すHTMLを変えるとかすると上手くいき そうなものの… • 現状UserAgentでモバイル判定をして出し分けている箇所を漸進的に置き換えるこ とが現実的に可能なのか? • パワー"で乗り切るしか無い? • デザインシステムで使われているmedia queryの値などと足並みを揃える • どこかで変数として埋め込む? • JSからCSS変数に渡す or その逆をやる

Slide 18

Slide 18 text

• 画面幅だけで全てを出し分けることが出来るのか? • 出し分けたいもの達 • アプリのダウンロードリンクを環境に応じて出し分けたい • チュートリアルの文言やスクリーンショット・動画 • ショートカットキーに使用するメタキー ブラウザや端末に応じて異なるHTMLを返したい

Slide 19

Slide 19 text

UserAgentを使いたいケースをそれぞれ見てきた • 特定の機能が利用出来るか確認したい • Feature Detectionしよう! • ブラウザの特定のバージョンに存在しているバグを回避したい • 祈るしかないこともある • ブラウザや端末に応じて異なるHTMLを返したい • 最初からやるなら念頭に置いてみたい • 漸進的に取り組むの難しい気がしている

Slide 20

Slide 20 text

本当にUserAgentの利用をやめないといけないのか? • 今後もOSやブラウザの名前、ブラウザのメジャーバージョンは取得できそうな状況は続きそう • iPadは環境に応じてOSを名乗り分けてくるが…… • Safariが再度UAのバージョンをフリーズする可能性も低そう • この問題にどれくらい我々は向き合う必要があるのかは若干懐疑的 • いつか信頼できなくなる可能性はあるものの、Webの互換性や機能要件的にも廃止すること は無さそう • UA-CHも実際に標準化出来そうな様子も無いので、これらの問題が実際に問題として表面化 するのはいつの未来? • Chromeが提案しているPrivacy Budget(*)が入れば、むやみに取得することはできなくな る可能性はあるものの実際どうなのでしょう… IUUQTEFWFMPQFSTHPPHMFDPNQSJWBDZTBOECPYQSPUFDUJPOTQSJWBDZCVEHFU

Slide 21

Slide 21 text

俺たちの戦いは続く… • 特定のブラウザの特定のバージョンのバグをなんとかしたいケース • 漸進的なUserAgentからメディアクエリを用いた実装への変更 • デザインの調整・しきい値の共有 etc • ここはなんとか進めたいが、イマイチ上手い進め方を思いつけてないの で、エピソードある人いたら教えてください • OSや環境に応じた情報の出し分け • そもそもどれくらいの温度感で向き合うべき話題なのか?