iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 14
1
Modern Web

你應該要知道的新一代Web技術---漸進式網頁(PWA)系列 第 14

[Day14] 使用indexedDB暫存Dynamic Data(Part1)

先來為我的PWA建立一個後台資料庫吧

我目前對於用戶的貼文,是先去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惹。/images/emoticon/emoticon34.gif

我的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 vs Caching Dynamic Data


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官方建議我們使用的離線儲存方式。

簡單總結官方的說明:

  • Cache API和IndexedDB皆為非同步的工作。
  • 對於網址中可尋找的資源,使用Cache API。
  • 對於所有其他數據,使用IndexedDB。

明天再來好好介紹什麼是indexedDB吧^ ^

Day14 結束!! /images/emoticon/emoticon02.gif


上一篇
[Day13] Service Worker進階Caching實作(Part3)
下一篇
[Day15] 使用indexedDB暫存Dynamic Data(Part2)
系列文
你應該要知道的新一代Web技術---漸進式網頁(PWA)29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言