ChromeとFirefoxのバージョン100対策、JavaScriptのバージョン判定で不具合が起こる方法とそれを直す方法
Post on:2022年3月16日
ChromeとFirefoxのバージョンがいよいよこの5月に、100になります。
参考: Chromeのスケジュール、Firefoxのスケジュール
100になることで2桁から3桁になり、JavaScriptでuserAgentからユーザーエージェント文字列を検出してバージョン判定をしていると、期待通りに動作しないかもしれません。バージョン100で不具合が起こる検出方法、そしてそれを直す方法を紹介します。
Encyclopedia Of Broken UserAgent String Detections
by Karl Dubost
Karl氏は、Mozillaのエンジニアマネージャーです。
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
ユーザーエージェント文字列を正しく検出していますか?
この記事は包括的な百科事典ではありませんが、将来壊れたり、失敗するであろうユーザーエージェント文字列を特定するパターンを解説します。
もしこれらを使用しているなら、必ず修正してください。
1. 数値の代わりに文字列を比較する
これはSlack is optimized for Firefox version 520で詳しく説明したものです。
userAgentのバージョン番号を整数ではなく、文字列で抽出します。
1 2 3 4 5 6 7 8 |
var browser_version = "100"; var support_min_version = "90"; if (browser_version < support_min_version) { console.log("too old"); } else { console.log("supported"); } // too oldになり、サポートされません |
上記のより良い方法は整数を抽出することです。
1 2 3 4 5 6 7 8 |
var browser_version = parseInt("100", 10) // 文字列としての「100」 var support_min_version = 90; // 文字列ではなく整数 if (browser_version < support_min_version) { console.log("too old"); } else { console.log("supported"); } // supportedになり、期待どおりにサポートされます |
2. 位置に応じた部分文字列のスライス
ここでの前提は、数値を表す部分文字列(substring)がスラッシュの2文字後にあることです。8
はFirefox/
の場合です。
1 2 3 4 5 6 |
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0" // "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0" start = ua.indexOf('Firefox') // 67 version = ua.substring(start + 8, start + 10) // "10" |
上記のより良い方法は次のとおりです。
1 2 3 4 5 6 7 8 |
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0" // "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0" start = ua.indexOf('Firefox') // 67 ua.substring(start + 'Firefox'.length + 1) // "100.0" parseFloat(ua.substring(start + 'Firefox'.length + 1)) // 100 |
3. 正規表現が2桁にしかマッチしない
これはかなり一般的な間違いです。
ブラウザのバージョンが1桁から2桁に変わったときに、検出アルゴリズムのほとんどは修正されましたが、固定長に依存するコードがはまだ存在しています。
1 2 3 4 5 6 7 8 |
const ua_string = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Firefox/91.0"; const ua_100 = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0"; ua_string.match(/Firefox\/(\d\d)/); // ["Firefox/91", "91"] ua_string.match(/Firefox\/(\d{2})/); // ["Firefox/91", "91"] ua_string.match(/Firefox\/(\d\d)\./); // ["Firefox/91.", "91"] ua_100.match(/Firefox\/(\d\d)/); // ["Firefox/10", "10"] ua_100.match(/Firefox\/(\d{2})/); // ["Firefox/10", "10"] ua_100.match(/Firefox\/(\d\d)\./); // null |
上記のより良い方法は次のとおりです。
1 2 |
ua_string.match(/Firefox\/(\d+)/); // ["Firefox/91", "91"] ua_string.match(/Firefox\/(\d+)/); // ["Firefox/100", "100"] |
4. iOS上のFirefoxをAndroidとして検出する
多くのサイトでは、各ブラウザでサポートされる最小バージョン番号のグリッドがあります。現在、iOS版のFirefoxのuserAgentの文字列は下記の通りです。
Mozilla/5.0 (iPhone; CPU OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/33.0 Mobile/15E148 Safari/605.1.15
FxiOS/33.0
は、iOSバージョン33のFirefoxを意味します。Webデベロッパーは、次のように返すライブラリをよく使用していました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ "ua": "Mozilla/5.0 (iPhone; CPU OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/33.0 Mobile/15E148 Safari/605.1.15", "browser": { "name": "Firefox", "version": "33.0", "major": "33" }, "engine": { "name": "WebKit", "version": "605.1.15" }, "os": { "name": "iOS", "version": "14.4.2" }, "device": { "vendor": "Apple", "model": "iPhone", "type": "mobile" }, "cpu": {}, "gpu": {} } |
一応大丈夫ですが、問題はサイトが「これはスマホ版Firefoxだから、Androidですね」となることです。Android版のFirefoxは78以降からサポートされています。そして、サイト全体や動画へのアクセスをブロックしたり、iOS版のFirefoxの最新版を使用しているユーザーにブラウザのアップグレードを求めてしまいます。
上記のより良い方法は、ブラウザが動作しているOSやエンジンを検出し、サポートマトリックスを調整することです。さらに良い方法は、ブラウザのバージョンに応じて、サイトに適切な劣化を処理させることです。
終わりに
質問や疑問点、私が見落としたかもしれないことなどがあれば、GitHubにお気軽にコメントをください。
sponsors