咩話?你個Firestore enable咗persistence之後wkwebview就白畫面?你可能係正版Webkit嘅受害者!

Posted on Mon, Sep 6, 2021 科技趣聞

好啦,長話簡説,話説我呢兩日寫曲面對緊個問題係,因為某啲原因發現某個寫好嘅webapp放落safari .... works。但 wkwebview就boom到七彩,一版白畫面:

開頭因為safari work但wkwebview唔work,以為係ios app嘅問題,但好快發現得wkwebview嘅問題……好啦知大家唔想聽廢話,簡單講就喺研究咗通宵之後發現個問題係,Firestore.enablePersistence()係用來係web開啓offline data嘅喺咪?

Access data offline | Firebase Documentation

Cloud Firestore supports offline data persistence. This feature caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline. You can write, read, listen to, and query the cached data.

而呢個offline data係需要browser 支援 Indexed DB嘅:

IndexedDB | Can I use... Support tables for HTML5, CSS3, etc

"Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers.

當然既然會咁嘅原因就喺可能wkwebview嘅indexedDB API有缺少,所以唔支援,連帶整舊firestore hang住唔識繼續initialize,噉咪導致整個firestore不可用。

最簡單嘅方法就喺唔enablePersistence(), then done.

其次一個簡單少少嘅方法就喺手動check再決定是否enablePersistence:

// angular
if(!platform.IOS && !platform.SAFARI){
    await firebase.firestore().enablePersistence()
}

// dom
const isSafari = (navigator.vendor.match(/apple/i) || "").length > 0
if(isSafari){
    await firebase.firestore().enablePersistence()
}

再進階一點但更正確嘅方法就喺check indexed DB嘅 suuport:

// In the following line, you should include the prefixes of implementations you want to test.
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
// DON'T use "var indexedDB = ..." if you're not in a function.
// Moreover, you may need references to some window.IDB* objects:
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE: "readwrite"}; // This line should only be needed if it is needed to support the object's constants for older browsers
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
// (Mozilla has never prefixed these objects, so we don't need window.mozIDB*)

if (!!window.indexedDB) {
    await firebase.firestore().enablePersistence()
}

Using IndexedDB - Web APIs | MDN

IndexedDB is a way for you to persistently store data inside a user's browser. Because it lets you create web applications with rich query abilities regardless of network availability, your applications can work both online and offline. This tutorial walks you through using the asynchronous API of IndexedDB.

THEN IT WORKS!!!!