国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

創(chuàng)建一個(gè)離線優(yōu)先,數(shù)據(jù)驅(qū)動(dòng)的漸進(jìn)式 Web 應(yīng)用程序

csRyan / 1237人閱讀

摘要:原文地址譯文出自我的個(gè)人博客概述在本文中,您將學(xué)習(xí)如何使用和創(chuàng)建離線優(yōu)先數(shù)據(jù)驅(qū)動(dòng)的漸進(jìn)式應(yīng)用程序。在離線的情況下也可以使用后臺(tái)同步功能將應(yīng)用程序與服務(wù)器同步。保存數(shù)據(jù)到中現(xiàn)在我們保存數(shù)據(jù)到剛創(chuàng)建的數(shù)據(jù)庫(kù)中的對(duì)象中。

原文地址:Build an offline-first, data-driven PWA
譯文出自:我的個(gè)人博客
概述

在本文中,您將學(xué)習(xí)如何使用 Workbox 和 IndexedDB 創(chuàng)建離線優(yōu)先、數(shù)據(jù)驅(qū)動(dòng)的漸進(jìn)式Web應(yīng)用程序(PWA)。在離線的情況下也可以使用后臺(tái)同步功能將應(yīng)用程序與服務(wù)器同步。

將會(huì)學(xué)習(xí)到

如何使用 Workbox 緩存應(yīng)用程序

如何使用 IndexedDB 存儲(chǔ)數(shù)據(jù)

如何在用戶脫機(jī)時(shí)從 IndexedDB 中檢索和顯示數(shù)據(jù)

脫機(jī)時(shí)如何保存數(shù)據(jù)

如何在脫機(jī)時(shí)使用后臺(tái)同步更新應(yīng)用程序

應(yīng)該了解的

HTML, CSS, 和 JavaScript

ES2015 Promises

如何使用命令行

熟悉一下 Workbox

熟悉一下 Gulp

熟悉一下 IndexedDB

需具備的條件

擁有 terminal/shell 訪問權(quán)限的電腦

Chrome 52 或更高版本

編輯器

Nodejs 和 npm

設(shè)置

如果你沒有安裝 Nodejs 需要安裝一下

之后通過下面的方式 clone 快速啟動(dòng)倉(cāng)庫(kù)

git clone https://github.com/googlecodelabs/workbox-indexeddb.git

或者直接下載 壓縮包

安裝依賴并啟動(dòng)服務(wù)

到下載好的 git 倉(cāng)庫(kù)目錄中,轉(zhuǎn)到 project 文件夾

cd workbox-indexeddb/project/

然后安裝依賴并啟動(dòng)服務(wù)

npm install
npm start
說明

這個(gè)步驟中會(huì)根據(jù) package.json 定義的依賴并安裝,打開 package.json 文件查看,有很多依賴,大部分是開發(fā)環(huán)境需要的(你可以忽略),主要的依賴是:

workbox-sw Workbox

workbox-background-sync 是 Workbox 用來后臺(tái)同步的,稍后會(huì)提到

gulp 和 workbox-build 是構(gòu)建工具

npm start 會(huì)構(gòu)建并輸出到 build 文件夾,啟動(dòng) dev server,并且會(huì)開啟一個(gè) gulp watch 任務(wù)。gulp watch 會(huì)監(jiān)聽文件的修改自動(dòng)構(gòu)建。concurrently 可以同時(shí)跑 gulp 和 dev server

打開應(yīng)用

打開 Chrome 并且跳轉(zhuǎn)到 localhost:8081 你會(huì)看到一個(gè)事件列表的控制臺(tái),在彈出的權(quán)限確認(rèn)菜單中點(diǎn)擊允許

我們使用通知系統(tǒng)來告知用戶 app 的后臺(tái)同步已經(jīng)更新,試著測(cè)試一下頁(yè)面底部的添加功能

說明

這個(gè)小項(xiàng)目的目標(biāo)是離線保存用戶的事件日歷。你可以查看一下 app/js/main.js 文件的 loadContentNetworkFirst 方法當(dāng)前是怎么工作的,首先會(huì)請(qǐng)求 server,成功則更新頁(yè)面,失敗會(huì)在控制臺(tái)打印一個(gè)信息,目前脫機(jī)是無法使用的,接下來我們添加一些方法使它脫機(jī)可用。

緩存 app shell 編寫 service worker

要想脫機(jī)工作,就需要 server worker,現(xiàn)在寫一個(gè)。

把下面的代碼添加到 app/src/sw.js

importScripts("workbox-sw.dev.v2.0.0.js");
importScripts("workbox-background-sync.dev.v2.0.0.js");

const workboxSW = new WorkboxSW();
workboxSW.precache([]);
說明

在開頭我們引入了 workbox-swworkbox-background-sync

workbox-sw 包含了 precache 和向 service worker 添加路由的方法

workbox-background-sync 是在 service worker 中后臺(tái)同步的庫(kù),稍后會(huì)提到

precache 方法接收一個(gè)文件列表的數(shù)組,先用一個(gè)空的,下一步我們會(huì)用 workbox-build 去計(jì)算出這個(gè)數(shù)組的結(jié)果。

構(gòu)建 service worker

推薦使用 Workbox 的構(gòu)建模塊,比如 workbox-build

把下面的代碼添加進(jìn) project/gulpfile.js

gulp.task("build-sw", () => {
  return wbBuild.injectManifest({
    swSrc: "app/src/sw.js",
    swDest: "build/service-worker.js",
    globDirectory: "build",
    staticFileGlobs: [
      "style/main.css",
      "index.html",
      "js/idb-promised.js",
      "js/main.js",
      "images/**/*.*",
      "manifest.json"
    ],
    templatedUrls: {
      "/": ["index.html"]
    }
  }).catch((err) => {
    console.log("[ERROR] This happened: " + err);
  });
});

現(xiàn)在取消一些注釋:

gulpfile.js:

// uncomment the line below:
const wbBuild = require("workbox-build");

// ...

gulp.task("default", ["clean"], cb => {
  runSequence(
    "copy",
    // uncomment the line below:
    "build-sw",
    cb
  );
});

保存修改,因?yàn)樾薷牧?gulp,我們得重新跑一下,Ctrl + C 退出當(dāng)前的進(jìn)程,重新運(yùn)行 npm start,會(huì)看到 service worker 的文件被生成在了 build/service-worker.js

取消 app/index.html 中 service worker 注冊(cè)代碼的注釋

if ("serviceWorker" in navigator) {
  navigator.serviceWorker.register("service-worker.js")
    .then(function(registration) {
      console.log("Service Worker registration successful with scope: ",
      registration.scope);
    })
    .catch(function(err) {
      console.log("Service Worker registration failed: ", err);
    });
}

保存修改,刷新瀏覽器 service worker 就會(huì)被安裝。Ctrl + C 關(guān)閉 dev server,再返回到瀏覽器中刷新頁(yè)面,已經(jīng)可以脫機(jī)運(yùn)行了!

說明

在這一步中,workbox-buildbuild-sw 任務(wù)被合并到我們的 gulp 文件中,我們的構(gòu)建過程是使用 workbox-build 庫(kù)來從 swSrc(app/src/sw.js) 中生成 service work 到 swDest(build/service-worker.js),來自 globDirectory(build)staticFileGlobs 文件被注入到 build/service-worker.js 以供 precache 調(diào)用,還有每個(gè)文件的修訂哈希。templatedUrls 選項(xiàng)告訴 Workbox 我們的站點(diǎn)以 index.html 的內(nèi)容響應(yīng)請(qǐng)求。

順便貼一個(gè) injectManifest 的鏈接

安裝生成好的 service worker 緩存 app shell 的資源文件,Workbox 會(huì)自動(dòng)去:

為緩存資源設(shè)置緩存優(yōu)先策略,允許應(yīng)用程序離線加載

service work 更新時(shí),使用修訂哈希來更新緩存的文件

創(chuàng)建 IndexedDB 數(shù)據(jù)庫(kù)

目前為止還不能離線加載數(shù)據(jù),我們接下來創(chuàng)建一個(gè) IndexDB 來保存程序的數(shù)據(jù),數(shù)據(jù)庫(kù)命名為 dashboardr

添加下面代碼到 app/js/main.js

function createIndexedDB() {
  if (!("indexedDB" in window)) {return null;}
  return idb.open("dashboardr", 1, function(upgradeDb) {
    if (!upgradeDb.objectStoreNames.contains("events")) {
      const eventsOS = upgradeDb.createObjectStore("events", {keyPath: "id"});
    }
  })
}

取消調(diào)用 createIndexedDB 的注釋:

const dbPromise = createIndexedDB();

保存文件,重啟 server:

npm start

回到瀏覽器刷新頁(yè)面,激活 skipWaiting 并再次刷新頁(yè)面,在 Chrome 中,你可以在開發(fā)者工具中的 Application 面板中選擇 Service Workers 點(diǎn)擊 skipWaiting,之后使用 開發(fā)者工具 檢查數(shù)據(jù)庫(kù)是否存在。在 Chrome 中你可以在 Application 面板中點(diǎn)擊 IndexedDB 選擇 dashboardr 查看 events 對(duì)象是否存在。

注意:開發(fā)者工具的 IndexedDB UI 可能不會(huì)準(zhǔn)確的反應(yīng)你數(shù)據(jù)庫(kù)的情況,在 Chrome 中你可以刷新數(shù)據(jù)庫(kù)查看,或者重新打開開發(fā)者工具
說明

在上面的代碼中,我們創(chuàng)建了一個(gè) dashboardr 數(shù)據(jù)庫(kù),并把他的版本號(hào)設(shè)置為 1 ,然后檢查 events 對(duì)象是否存在,這個(gè)檢查是為了避免潛在的錯(cuò)誤,我們還給 event 提供了一個(gè)唯一的 key path id

由于我們修改了 app/main.js 文件,gulp 的 watch 任務(wù)會(huì)自動(dòng)構(gòu)建,Workbox 會(huì)自動(dòng)更新修訂哈希,然后智能更新緩存中的 main.js

保存數(shù)據(jù)到 IndexedDB 中

現(xiàn)在我們保存數(shù)據(jù)到剛創(chuàng)建的數(shù)據(jù)庫(kù) dashboardr 中的 event 對(duì)象中。

function saveEventDataLocally(events) {
  if (!("indexedDB" in window)) {return null;}
  return dbPromise.then(db => {
    const tx = db.transaction("events", "readwrite");
    const store = tx.objectStore("events");
    return Promise.all(events.map(event => store.put(event)))
    .catch(() => {
      tx.abort();
      throw Error("Events were not added to the store");
    });
  });
}

然后更新 loadContentNetworkFirst 方法,現(xiàn)在這是完整的方法:

function loadContentNetworkFirst() {
  getServerData()
  .then(dataFromNetwork => {
    updateUI(dataFromNetwork);
    saveEventDataLocally(dataFromNetwork)
    .then(() => {
      setLastUpdated(new Date());
      messageDataSaved();
    }).catch(err => {
      messageSaveError(); 
      console.warn(err);
    });
  }).catch(err => { // if we can"t connect to the server...
    console.log("Network requests have failed, this is expected if offline");
  });
}

取消注釋 addAndPostEvent 中的 saveEventDataLocally 調(diào)用

function addAndPostEvent() {
  // ...
  saveEventDataLocally([data]);
  // ...
}

保存文件,刷新頁(yè)面重新激活 service worker。再次刷新頁(yè)面,檢查一下來自網(wǎng)絡(luò)的數(shù)據(jù)是否被保存到 events 中去(你可能需要刷新一下開發(fā)者工具中的 IndexedDB

說明

saveEventDataLocally 接收一個(gè)數(shù)組并一條條的保存到 IndexedDB 數(shù)據(jù)庫(kù)中,我們把 store.put 寫在了 Promise.all 中,這樣如果某一條更新出錯(cuò)我們就可以終止事務(wù)。

loadContentNetworkFirst 方法中,一旦收到來自服務(wù)器的數(shù)據(jù),就會(huì)更新 IndexedDB 和頁(yè)面。然后,數(shù)據(jù)成功保存時(shí),將存儲(chǔ)時(shí)間戳,并通知用戶數(shù)據(jù)可供離線使用。

addAndPostEvent 中調(diào)用 saveEventDataLocally 方法保證了添加新的 event 時(shí)本地會(huì)存有最新的數(shù)據(jù)。

從 IndexedDB 中獲取數(shù)據(jù)

離線的時(shí)候,我們就要查詢本地緩存的數(shù)據(jù)。

添加下面的代碼到 app/js/main.js 中:

function getLocalEventData() {
  if (!("indexedDB" in window)) {return null;}
  return dbPromise.then(db => {
    const tx = db.transaction("events", "readonly");
    const store = tx.objectStore("events");
    return store.getAll();
  });
}

然后更新 loadContentNetworkFirst 方法,完整的方法如下:

function loadContentNetworkFirst() {
  getServerData()
  .then(dataFromNetwork => {
    updateUI(dataFromNetwork);
    saveEventDataLocally(dataFromNetwork)
    .then(() => {
      setLastUpdated(new Date());
      messageDataSaved();
    }).catch(err => {
      messageSaveError();
      console.warn(err);
    });
  }).catch(err => {
    console.log("Network requests have failed, this is expected if offline");
    getLocalEventData()
    .then(offlineData => {
      if (!offlineData.length) {
        messageNoData();
      } else {
        messageOffline();
        updateUI(offlineData); 
      }
    });
  });
}

保存文件,刷新瀏覽器激活更新的 service worker,現(xiàn)在 Ctrl + C 關(guān)閉 dev server,返回到瀏覽器中刷新頁(yè)面,現(xiàn)在 app 和數(shù)據(jù)都可以離線加載了!

說明

loadContentNetworkFirst 被調(diào)用的時(shí)候如果沒有網(wǎng)絡(luò)連接,getServerData 會(huì)被 reject,之后便會(huì)進(jìn)入到 catch 中去,然后 getLocalEventData 會(huì)調(diào)用本地緩存的數(shù)據(jù)。有網(wǎng)絡(luò)連接的話會(huì)正常的請(qǐng)求 server 并且 updateUI

使用 workbox-background-sync

我們的 app 已經(jīng)可以離線保存和瀏覽數(shù)據(jù),現(xiàn)在我們來用 workbox-background-sync 把離線狀態(tài)下保存的數(shù)據(jù)同步到服務(wù)端去。

把下面的的代碼添加到 app/src/sw.js

let bgQueue = new workbox.backgroundSync.QueuePlugin({
  callbacks: {
    replayDidSucceed: async(hash, res) => {
      self.registration.showNotification("Background sync demo", {
        body: "Events have been updated!"
      });
    }
  }
});

workboxSW.router.registerRoute("/api/add",
  workboxSW.strategies.networkOnly({plugins: [bgQueue]}), "POST"
);

保存,現(xiàn)在轉(zhuǎn)到命令行:

npm run start

刷新瀏覽器,激活更新的 service worker

Ctrl + C 把 app 變?yōu)殡x線狀態(tài),添加一個(gè) event 確認(rèn)請(qǐng)求 /api/add 已經(jīng)被添加進(jìn) bgQueueSyncDBQueueStore 對(duì)象。

說明

當(dāng)用戶試圖在離線情況下添加 event 的時(shí)候,workbox-background-sync 會(huì)把失敗的請(qǐng)求保存為一個(gè)離線隊(duì)列,當(dāng)用戶重新聯(lián)網(wǎng) backgroundSync 會(huì)重新發(fā)送這些請(qǐng)求,甚至都不需要用戶打開 app!但是,從聯(lián)網(wǎng)到重新發(fā)請(qǐng)求的這個(gè)過程大概需要 5 分鐘,下一節(jié)我們將會(huì)介紹如何在 app 中立即發(fā)送這些請(qǐng)求。

重發(fā)請(qǐng)求

因?yàn)橹匕l(fā)請(qǐng)求會(huì)有延遲,所以用戶可能回到 app 之后還沒有同步數(shù)據(jù),所以我們?cè)谟脩袈?lián)網(wǎng)的時(shí)候立即發(fā)送這些請(qǐng)求。

把下面的代碼添加到 app/src/sw.js

workboxSW.router.registerRoute("/api/getAll", () => {
  return bgQueue.replayRequests().then(() => {
    return fetch("/api/getAll");
  }).catch(err => {
    return err;
  });
});

只要用戶請(qǐng)求服務(wù)端數(shù)據(jù)(加載或刷新頁(yè)面時(shí)),該路由就會(huì) replay 排隊(duì)的請(qǐng)求,然后返回最新的服務(wù)端數(shù)據(jù)。這很好,但是用戶還是得刷新頁(yè)面去重新獲取數(shù)據(jù),我們還有更好的做法。

把下面的代碼添加進(jìn) app/js/main.js

window.addEventListener("online", () => {
  container.innerHTML = "";
  loadContentNetworkFirst();
});

重啟 server

npm start

刷新瀏覽器激活新的 service worker,并再次刷新頁(yè)面。

Ctrl + C 把 app 變?yōu)殡x線狀態(tài)

添加一條 event

重啟 server

npm start

這時(shí)你應(yīng)該能立即收到一條數(shù)據(jù)更新的通知,檢查 server-data/events.json 中的數(shù)據(jù)是否已經(jīng)更新。

說明

頁(yè)面加載的時(shí)候會(huì)請(qǐng)求 /api/getAll,我們攔截了這個(gè)請(qǐng)求,之后主要做了兩件事:

同步本地的離線數(shù)據(jù)

重新請(qǐng)求 /api/getAll

也就是在重新獲取服務(wù)端的數(shù)據(jù)之前先同步

注意:本例中的網(wǎng)絡(luò)請(qǐng)求設(shè)計(jì)的非常簡(jiǎn)單,實(shí)際情況下你可能需要考慮更多因素去減少請(qǐng)求的數(shù)量。
添加刪除功能

下面的時(shí)間就交給你了,添加一個(gè)刪除的功能,記得刪除 IndexedDB 中的數(shù)據(jù)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/107129.html

相關(guān)文章

  • 構(gòu)建離線web應(yīng)用(一)

    摘要:我喜歡移動(dòng),而且也是那些堅(jiān)持使用技術(shù)構(gòu)建移動(dòng)應(yīng)用程序的人之一。我們準(zhǔn)備做這樣的一個(gè)漸進(jìn)式應(yīng)用是典型的旨在提高用戶離線體驗(yàn)的應(yīng)用。當(dāng)我們開始構(gòu)建應(yīng)用時(shí),你就能理解上面的場(chǎng)景了。的作用范圍是針對(duì)相對(duì)路徑的。最佳的做法是在應(yīng)用的入口。 我喜歡移動(dòng)app,而且也是那些堅(jiān)持使用Web技術(shù)構(gòu)建移動(dòng)應(yīng)用程序的人之一。 經(jīng)過技術(shù)的不斷迭代(可能還有一些其它的東西),移動(dòng)體驗(yàn)設(shè)計(jì)愈來愈平易近人,給予用戶...

    Sanchi 評(píng)論0 收藏0
  • [譯]介紹一下進(jìn)式 Web App(離線) - Part 1

    摘要:基本上是使用現(xiàn)代技術(shù)構(gòu)建的網(wǎng)站但是體驗(yàn)上卻像一個(gè)移動(dòng),在年,谷歌工程師和創(chuàng)造了。此后谷歌就一直致力于讓能給用戶像原生一般的體驗(yàn)。檢查谷歌瀏覽器的和現(xiàn)在重載你的并且打開,到選項(xiàng)去查看面板,確保這個(gè)選項(xiàng)是勾選的。 Web開發(fā)多年來有了顯著的發(fā)展。它允許開發(fā)人員部署網(wǎng)站或Web應(yīng)用程序并在數(shù)分鐘內(nèi)為全球數(shù)百萬人服務(wù)。只需一個(gè)瀏覽器,用戶可以輸入U(xiǎn)RL就可以訪問Web應(yīng)用程序了。隨著 Prog...

    Wildcard 評(píng)論0 收藏0
  • [譯]介紹一下進(jìn)式 Web App(離線) - Part 1

    摘要:基本上是使用現(xiàn)代技術(shù)構(gòu)建的網(wǎng)站但是體驗(yàn)上卻像一個(gè)移動(dòng),在年,谷歌工程師和創(chuàng)造了。此后谷歌就一直致力于讓能給用戶像原生一般的體驗(yàn)。檢查谷歌瀏覽器的和現(xiàn)在重載你的并且打開,到選項(xiàng)去查看面板,確保這個(gè)選項(xiàng)是勾選的。 Web開發(fā)多年來有了顯著的發(fā)展。它允許開發(fā)人員部署網(wǎng)站或Web應(yīng)用程序并在數(shù)分鐘內(nèi)為全球數(shù)百萬人服務(wù)。只需一個(gè)瀏覽器,用戶可以輸入U(xiǎn)RL就可以訪問Web應(yīng)用程序了。隨著 Prog...

    gaara 評(píng)論0 收藏0
  • [譯]介紹一下進(jìn)式 Web App(離線) - Part 1

    摘要:基本上是使用現(xiàn)代技術(shù)構(gòu)建的網(wǎng)站但是體驗(yàn)上卻像一個(gè)移動(dòng),在年,谷歌工程師和創(chuàng)造了。此后谷歌就一直致力于讓能給用戶像原生一般的體驗(yàn)。檢查谷歌瀏覽器的和現(xiàn)在重載你的并且打開,到選項(xiàng)去查看面板,確保這個(gè)選項(xiàng)是勾選的。 Web開發(fā)多年來有了顯著的發(fā)展。它允許開發(fā)人員部署網(wǎng)站或Web應(yīng)用程序并在數(shù)分鐘內(nèi)為全球數(shù)百萬人服務(wù)。只需一個(gè)瀏覽器,用戶可以輸入U(xiǎn)RL就可以訪問Web應(yīng)用程序了。隨著 Prog...

    wenshi11019 評(píng)論0 收藏0
  • 進(jìn)式Web應(yīng)用(PWA)入門教程(下)

    摘要:漸進(jìn)式應(yīng)用入門教程上在這一節(jié)中,我們將介紹的原理是什么,它是如何開始工作的。第一步使用漸進(jìn)式應(yīng)用程序需要使用連接。優(yōu)先旋轉(zhuǎn)方向,可選的值有顯示方式無,和原生應(yīng)用一樣,最小的一套控件集或者最古老的使用瀏覽器標(biāo)簽顯示一個(gè)包含所有圖片的數(shù)組。 上篇文章我們對(duì)漸進(jìn)式Web應(yīng)用(PWA)做了一些基本的介紹。 漸進(jìn)式Web應(yīng)用(PWA)入門教程(上) 在這一節(jié)中,我們將介紹PWA的原理是什么,它是...

    NotFound 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<