我目前對於用戶的貼文,是先去request一個假的Restful API Endpoint,再用createCard() function建立一個假的貼文。這邊開始我要使用firebase的「Realtime Database」和「Storage」作為後台資料庫來儲存PWA中用戶貼文的Dynamic Data。
我只對firebase的使用方式稍微說明並不會深入。因為目前只拿firebase提供的兩個服務做儲存資料用而已
進入firebase console後建立一個project,接著點擊Database中的Realtime Database。之後會跳出設定安全性規則,我這裡為了之後開發的方便,選擇「以測試模式啟動」(這讓任何人都可以讀寫我們的Realtime Database)。
可以看到畫面如下(它的儲存格式類似json format):
這裡我會先輸入一則貼文到Database以及圖片到Storage中。由於目前我的PWA還沒有實作讓用戶主動「新增貼文」的功能,這邊先破梗一下之後我會使用Firebase提供的「Functions Serverless服務」來實作API Endpoint。這樣我們的用戶就可以使用這些API發佈貼文並儲存到資料庫中。
以下為我在Firebase Realtime Database加入的貼文資料:
image欄位之所以先寫"XXX",是因為等一下我們需要將儲存在Firebase Storage中的圖片加進去。
接著在Firebase Storage加入貼文圖片:
右邊可以看到下載網址的url,這就是我們要儲存到Realtime Database中的image欄位。
當後台資料庫設定好後,接下來就要回到PWA project看如何透過HTTP Request取得後台資料庫的Data:
首先,在前面的Firebase Realtime Database的截圖中可以看到一段url,以我的來說為" https://trip-diary-f56de.firebaseio.com/ "。
我今天要取得裡面posts資訊,最簡單的方式就是對" https://trip-diary-f56de.firebaseio.com/posts.json "發出一個HTTP GET Request。
我在feed.js以及sw.js中的fetch url改成上面所說的網址後,由於目前createCard() function裡面的資料都是寫死的,所以這裡我在feed.js中新增一個updateUI() function,來更新createCard()的內容,並對createCard() function新增一個參數來接收從firebase取回來的posts資料:
function updateUI(data) {
clearCards();
for(var i=0; i<data.length; i++) {
createCard(data[i]);
}
}
function createCard(data) {
var cardWrapper = document.createElement('div');
cardWrapper.className = 'shared-moment-card mdl-card mdl-shadow--2dp';
var cardTitle = document.createElement('div');
cardTitle.className = 'mdl-card__title';
cardTitle.style.backgroundImage = 'url(' + data.image + ')'; // 取得貼文中image欄位的資訊
cardTitle.style.backgroundSize = 'cover';
cardTitle.style.height = '180px';
cardWrapper.appendChild(cardTitle);
var cardTitleTextElement = document.createElement('h2');
cardTitleTextElement.style.color = 'white';
cardTitleTextElement.className = 'mdl-card__title-text';
cardTitleTextElement.textContent = data.title; // 取得貼文中title欄位的資訊
cardTitle.appendChild(cardTitleTextElement);
var cardSupportingText = document.createElement('div');
cardSupportingText.className = 'mdl-card__supporting-text';
cardSupportingText.textContent = data.location; // 取得貼文中location欄位的資訊
cardSupportingText.style.textAlign = 'center';
cardWrapper.appendChild(cardSupportingText);
componentHandler.upgradeElement(cardWrapper);
sharedMomentsArea.appendChild(cardWrapper);
}
因為我們fetch回來的資料是json格式,所以接下來要對這部分的資料做一些處理。我希望在updateUI中輸入的參數是一個Array的型式,這樣我就可以將每則貼文資訊一個個的製作成card,最後把createCard()替換成updateUI() function就OK惹。
我的feed.js中fetch和cache的程式碼最後如下:
fetch(url).then(function(res) {
return res.json();
}).then(function(data) {
networkDataReceived = true;
console.log('From Web', data);
var dataArray = [];
for(var key in data) {
dataArray.push(data[key]);
}
updateUI(dataArray);
});
if('caches' in window) {
caches.match(url).then(function(response) {
if(response) {
return response.json();
}
}).then(function(data) {
console.log('From Cache', data);
if(!networkDataReceived) {
var dataArray = [];
for(var key in data) {
dataArray.push(data[key]);
}
updateUI(dataArray);
}
});
}
Dynamic Caching和Caching Dynamic Content這兩者都是使用瀏覽器的儲存空間,但是使用它們的pattern和目的是不太相同的。目前為止我都是透過service worker來去動態暫存用戶訪問到的html、css、js和image資源到cache中,以便未來在網路離線狀態下,也能正常瀏覽我的PWA,簡單來說在cache中儲存的就是「HTTP的Request和Response」。
但是對於像用戶需要經常不斷新增和更新的貼文資訊(尤其是json或xml格式的data)來說,cache並不是一個好的選擇。IndexedDB也是一個key-value Database,用來儲存動態資料尤其是json format是再適合不過了。這也是google官方建議我們使用的離線儲存方式。
簡單總結官方的說明:
明天再來好好介紹什麼是indexedDB吧^ ^
Day14 結束!!