Quantcast
Channel: WFU BLOG
Viewing all articles
Browse latest Browse all 571

用 Line、FB 手機 APP 開啟網頁對前端工程師的困擾﹍JS 辨識內建瀏覽器(webview)的方法

$
0
0
前陣子的一個專案,客戶反應很多使用者用手機操作時,網頁會有錯誤導致無法註冊。但我手機實測的結果又沒有發生任何問題,於是請客戶提供使用者的操作環境,例如 Android 或 iOS 系統,瀏覽器版本等等。

結果都不是這些原因,最後才發現是因為使用者在 Line 上面開啟網站連結所引起。當 Line 點擊連結時,並不會呼叫手機的預設瀏覽器(例如 Chrome、Safari 等),而是會開啟內建瀏覽器,專有名詞叫做 In-App browser,或是 webview。

這件事就非常麻煩了,因為內建瀏覽器並不像主流瀏覽器能支援最新的網頁技術、JS 或 CSS 語法等等,要 Debug 問題也是非常麻煩的事。

偏偏客戶的使用者有很大的比例會操作 Line,所以解決網頁在「內建瀏覽器」上的問題,變成一件必要且急迫的事。

先說結論,研究半天後發現,這件事以目前的技術,沒有治本的解法,只能先用治標的方式撐著,等待科技的進步來化解這個麻煩,或是看能否有消滅「內建瀏覽器」這個產物的可能性。

(圖片出處: pixabay.com)


一、什麼是內建瀏覽器


前端工程師已經夠悲情了,要應付 PC 網頁、各種行動裝置的眾家瀏覽器(及不同版本)的網頁效果,現在竟然還有手機「內建瀏覽器」這個大魔王。

為何說是大魔王呢?以前多半只要告訴客人 "請使用主流瀏覽器,才能支援最新的網頁技術,獲得最佳效果",但現在這句話已經無法輕易打發客人了,因為越來越多手機 APP 在開啟網頁連結時,都不呼叫外部瀏覽器,反而一律使用「內建瀏覽器」,例如 Line、FB、twitter、instagram、微信....等等族繁不及備載

可參考這篇「關於 WebView: 10 件你需要知道的事」,實際上手機的 "內建瀏覽器"並不具備完整的瀏覽器功能,所以前端開發者也不太可能用這個環境來開發網頁。

那為何這個殘缺的瀏覽器,卻成為眾多手機 APP 的最愛,一定要用內建瀏覽器來開啟網頁,不惜犧牲使用者體驗呢?



二、為何 APP 要用 webview


原本跟客戶說這是 Line 的問題,不是我們網頁的問題,還想說請客戶去跟 Line 抗議,要求取消強制用內建瀏覽器來開啟網頁。

不過大概爬了一下文後,就知道這是不可能的事,APP 不會放棄使用內建瀏覽器,原因大致是這樣:

  • 使用外部瀏覽器後,使用者注意力一分散,就會忘了回到 APP
  • APP 死命也要將使用者注意力留住,而內建瀏覽器按右上角關閉後,會立即回到 APP
  • 使用外部瀏覽器開啟時間長,而內建瀏覽器輕薄短小,開啟速度快,回到 APP 也快
  • 使用外部瀏覽器後,蒐集不到使用者的數據
  • 在 APP 內執行 webview,所有使用者行為都被 APP 掌握
  • 掌握使用者行為的數據,不會輕易被 APP 放棄



三、內建瀏覽器會產生什麼問題


既然「內建瀏覽器」已經確定成為前端開發者的夢魘,那麼必須試著與惡魔相處。

雖無法百戰百勝,但知己知彼仍是非常必要,這篇「你知道你的網站可能在 InAppBrowser/webview 無法使用嗎?」是前端開發者必讀的一篇整理:

  • 購物網站會發生的問題
  • 哪些基本的 JS 語法無法執行
  • 哪些語法執行效果跟網頁不一樣
  • 提供一個測試網頁,可用來測試各種 APP 開啟連結的效果



四、解決方法


1. 沒有治本之道

如果能夠有一個 js 判斷方式,偵測到「內建瀏覽器」時作對應的處置,相信這可以算是 "治本"的方法。

可惜的是,測試了大部分 Google 到的語法,多半都沒有作用,這代表:

  • 網頁技術不斷在更新
  • 行動裝置作業系統不斷在升級
  • 一些過去可行的判斷語法,會隨著時間失效
  • 就算目前找到了可行的語法,也可能一段時間後就無效


2. 後端處理語法

這個 Github 上的專案,可用來偵測 APP 是否呼叫內建瀏覽器:


不過是用來裝在後端,所以我不清楚效果如何。

而且如前面我說的,除非這個專案持續有人不斷在維護,否則隨著網頁技術、環境改變,語法可能就失效了。


3. 變通作法

最後是退而求其次的作法,也是我採用的方法,針對客群使用者環境處理。例如 Line 的使用者族群較多,就偵測是否使用 Line 開啟內建瀏覽器。

參考這篇「檢查目前瀏覽器的版本」,提供了 3 種檢測手機 APP 是否開啟內建瀏覽器的語法:

(function() {
var u = navigator.userAgent,
ua = navigator.userAgent.toLowerCase(),
isLineApp = u.indexOf("Line") > -1, // Line 內建瀏覽器
isFbApp = u.indexOf("FBAV") > -1, // FB App 內建瀏覽器
isWeixinApp = ua.match(/MicroMessenger/i) == "micromessenger"; // 微信內建瀏覽器

// 如果是 Line 內建瀏覽器
if (isLineApp) {
// do sth
}

// 如果是 FB App 內建瀏覽器
if (isFbApp) {
// do sth
}

// 如果是 微信內建瀏覽器
if (isWeixinApp) {
// do sth
}
})();

以我客戶的狀況為例,使用者在手機用 Line 開啟連結後會導致特定管道的登入功能失效,那麼可以使用 isLineApp 來偵測是否用 Line 開啟內建瀏覽器。當偵測到時,關閉「特定管道的登入/註冊」的功能來減少不良的用戶體驗。



五、沒有完美的解決方案


由於手機的 APP 太多了,且不會知道將來要流行什麼 APP,所以目前真的只能看到一個洞、塞一個洞。但麻煩的是,有些洞是堵不起來的。

這個 stackoverflow 討論串「How to detect pages when a user browses inside twitter in app?」,有人提出 twitter 要如何偵測呼叫內建瀏覽器,可惜答案是 "不可能",因為 twitter 沒有針對 webview 這件事,在 navigator.userAgent 塞相關字串。

我們需要慶幸的是,至少一些使用率較高的 APP,例如 FB、Line 等,會在 navigator.userAgent 塞字串讓我們判別。將來如果有使用者回報網頁在某些 APP 執行異常時,前端工程師們再想辦法 Google 該內建瀏覽器的偵測字串吧!


更多 Javascript 相關技巧:

Viewing all articles
Browse latest Browse all 571

Trending Articles