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

資訊專欄INFORMATION COLUMN

[譯]介紹一下漸進式 Web App(離線) - Part 1

wenshi11019 / 974人閱讀

摘要:基本上是使用現(xiàn)代技術(shù)構(gòu)建的網(wǎng)站但是體驗上卻像一個移動,在年,谷歌工程師和創(chuàng)造了。此后谷歌就一直致力于讓能給用戶像原生一般的體驗。檢查谷歌瀏覽器的和現(xiàn)在重載你的并且打開,到選項去查看面板,確保這個選項是勾選的。

Web開發(fā)多年來有了顯著的發(fā)展。它允許開發(fā)人員部署網(wǎng)站或Web應(yīng)用程序并在數(shù)分鐘內(nèi)為全球數(shù)百萬人服務(wù)。只需一個瀏覽器,用戶可以輸入URL就可以訪問Web應(yīng)用程序了。隨著 Progressive Web Apps的到來,開發(fā)人員可以使用現(xiàn)代Web技術(shù)向用戶提供很好體驗的應(yīng)用程序。在這篇文章中,你會學(xué)習(xí)到如何構(gòu)建一個離線的漸進式 web 應(yīng)用程序(Progressive Web Apps),下面就叫 PWA 啦。

首先介紹一下什么是 PWA

雖然很多文章已經(jīng)說過了,已經(jīng)理解的童鞋請?zhí)^這個步驟。PWA基本上是使用現(xiàn)代Web技術(shù)構(gòu)建的網(wǎng)站,但是體驗上卻像一個移動 app,在2015年,谷歌工程師Alex Russell和Frances Berriman創(chuàng)造了“ Progressive Web Apps”。此后谷歌就一直致力于讓 PWA能給用戶像原生 app一般的體驗。一個典型的PWA的應(yīng)該是這樣的:

1、開始在Web瀏覽器的地址欄中訪問

2、有顯示添加到設(shè)備的主屏幕選項

3、逐步開始展示諸如離線使用、推送通知和后臺同步等應(yīng)用程序?qū)傩浴?/p>

到目前為止,移動APP可以做很多Web App不能真正做的事情。PWA,一個web app嘗試去做移動app已經(jīng)很長時間了。它結(jié)合最好的 web技術(shù)的和最好的app技術(shù),可以在慢速網(wǎng)絡(luò)連接上快速加載,離線瀏覽,推送消息,并在Web屏幕上加載Web應(yīng)用程序入口。

到現(xiàn)在,安卓上最心版本的Chrome瀏覽器,支持在桌面上快速打開你的 web app 了,這一切都感謝 PWA,如下圖

WPA 的特性

這類新的Web應(yīng)用程序具有定義它們存在的特性。沒有很難的知識點,下面這些都是 PWA具有的一些特性:

Responsive(響應(yīng)式):Ui可以適配多個終端,桌面,手機,平板等等

App-like(像app):當與一個PWA交互時,它應(yīng)該感覺像一個原生的應(yīng)用程序。

Connectivity Independent(連接獨立): 它能離線瀏覽(通過 Service Workers) 或者在低網(wǎng)速上也能瀏覽

Re-engageable(重新連接):通過推送通知等功能,用戶應(yīng)該能夠持續(xù)地參與和重用應(yīng)用程序。

Installable(安裝):用戶可以添加在主屏幕并且從那里啟動它他們就可以重新應(yīng)用程序了。

Discoverable(可發(fā)現(xiàn)的):用戶通過搜索應(yīng)被識別發(fā)現(xiàn)的

Fresh(最新數(shù)據(jù)):當用戶連接到網(wǎng)絡(luò)時,應(yīng)該能夠在應(yīng)用程序中提供新的內(nèi)容。

Safe(安全):該通過HTTPS提供服務(wù),防止內(nèi)容篡改和中間人攻擊。

Progressive(漸進式):不管瀏覽器的選擇如何,它應(yīng)該對每個用戶都有效。

Linkable(可鏈接):通過URL分享給別人。

PWA的一些生產(chǎn)用例

Flipkart Lite: FlipKart 是印度最大的電商之一。如下圖


AliExpress:AliExpress 是個非常受歡迎的全球在線零售市場,通過實踐 PWA之后,訪問量和瀏覽數(shù)都成倍增加這里不做詳細講解。如下圖


Service Workers

Service Workers是可編程代理的一個script腳本運行在你瀏覽器的后臺,它具有攔截、處理HTTP請求的能力,也能以各種方式對他們作出響應(yīng)。它有響應(yīng)網(wǎng)絡(luò)請求、推送通知、連接更改等等的功能。Service Workers不能訪問DOM,但它可以利用獲取和緩存API。您可以Service Workers緩存所有靜態(tài)資源,這將自動減少網(wǎng)絡(luò)請求并提高性能。 Service worker 可以顯示一個 app應(yīng)用殼,通知用戶,他們與互聯(lián)網(wǎng)斷開了并且提供一個頁面供用戶在離線時進行交互、瀏覽。

一個Service worker文件,例如sw.js需要像這樣放置在根目錄中:

在你的PWA中開始service workers,如果你的應(yīng)用程序的JS文件是app.js,你需要去注冊service workers在你的app.js文件,下面的代碼就是注冊你的service workers。

  if ("serviceWorker" in navigator) {
    navigator.serviceWorker
             .register("./sw.js")
             .then(function() { console.log("Service Worker Registered"); });
  }

上面的代碼檢查瀏覽器是否支持service workers。如果支持,就開始注冊service workers,一旦service workers注冊了,我們就開始體驗用戶第一次訪問頁面時service workers的生命周期。

service workers的生命周期

Install:在用戶第一次訪問頁面時觸發(fā)安裝事件。在這個階段中,service workers被安裝在瀏覽器中。在安裝過程中,您可以將Web app的所有靜態(tài)資產(chǎn)緩存下來。如下面代碼所示:

// Install Service Worker
self.addEventListener("install", function(event) {

    console.log("Service Worker: Installing....");

    event.waitUntil(

        // Open the Cache
        caches.open(cacheName).then(function(cache) {
            console.log("Service Worker: Caching App Shell at the moment......");

            // Add Files to the Cache
            return cache.addAll(filesToCache);
        })
    );
});
filesToCache變量代表的所有文件要緩存數(shù)組

cachename指給緩存存儲的名稱

Activate:當service worker啟動時,此事件將被觸發(fā)。

// Fired when the Service Worker starts up
self.addEventListener("activate", function(event) {

    console.log("Service Worker: Activating....");

    event.waitUntil(
        caches.keys().then(function(cacheNames) {
            return Promise.all(cacheNames.map(function(key) {
                if( key !== cacheName) {
                    console.log("Service Worker: Removing Old Cache", key);
                    return caches.delete(key);
                }
            }));
        })
    );
    return self.clients.claim();
});

在這里, service worker每當應(yīng)用殼(app shell)文件更改時都更新其緩存。

Fetch:此事件作用與于從服務(wù)器端的數(shù)據(jù)緩存到 app殼中。caches.match()解析了觸發(fā)Web請求的事件,并檢查它是否在緩存中獲得數(shù)據(jù)。然后,它要么響應(yīng)于緩存版本的數(shù)據(jù),要么用fetch從網(wǎng)絡(luò)中獲取數(shù)據(jù)。用 e.respondWith()方法來響應(yīng)返回到Web頁面。

self.addEventListener("fetch", function(event) {

    console.log("Service Worker: Fetch", event.request.url);

    console.log("Url", event.request.url);

    event.respondWith(
        caches.match(event.request).then(function(response) {
            return response || fetch(event.request);
        })
    );
});
在寫代碼的時候。我們需要注意一下Chrome, Opera、Firefox是支持service workers  的,但是Safari 和 Edge 還沒有兼容到service workers

Service Worker Specification 和 primer 都是關(guān)于Service Workers的一下非常有用的學(xué)習(xí)資料。

Application Shell(應(yīng)用殼)

在文章的前面,我曾多次提到過應(yīng)用殼app shell。應(yīng)用程序殼是用最小的HTML,CSS和JavaScript驅(qū)動應(yīng)用程序的用戶界面。一個PWA確保應(yīng)用殼被緩存,以對應(yīng)app多次快速訪問和快速加載。

下面我們將逐步寫一個 PWA例子

我們將構(gòu)建一個簡單的PWA。這個app只跟蹤來自特定開源項目的最新提交。作為一個 PWA,他應(yīng)該具具有:

離線應(yīng)用,用戶應(yīng)該能夠在沒有Internet連接的情況下查看最新提交。

應(yīng)用程序應(yīng)立即加載重復(fù)訪問

打開按鈕通知按鈕后,用戶將獲得對最新提交到開放源代碼項目的通知。

可安裝(添加到主屏幕)

有一個Web應(yīng)用程序清單

光說不做瞎扯淡,開始吧!

創(chuàng)建index.htmllatest.html文件在你的代碼文件夾里面。

index.html



  
  
  
  Commits PWA
  


    
PWA - Home

Stay Up to Date with R-I-L

latest.html



  
  
  
  Commits PWA
  


    
PWA - Commits

Latest Commits!

創(chuàng)建一個 css 文件夾,并且在這個文件下載創(chuàng)建一個style.css文件(可以點擊這里查看),創(chuàng)建一個js文件夾,并在這個文件下創(chuàng)建app.js, menu.js, offline.js, latest.jstoast.js

js/offline.js
(function () {
  "use strict";

  var header = document.querySelector("header");
  var menuHeader = document.querySelector(".menu__header");

  //After DOM Loaded
  document.addEventListener("DOMContentLoaded", function(event) {
    //On initial load to check connectivity
    if (!navigator.onLine) {
      updateNetworkStatus();
    }

    window.addEventListener("online", updateNetworkStatus, false);
    window.addEventListener("offline", updateNetworkStatus, false);
  });

  //To update network status
  function updateNetworkStatus() {
    if (navigator.onLine) {
      header.classList.remove("app__offline");
      menuHeader.style.background = "#1E88E5"; 
    }
    else {
      toast("You are now offline..");
      header.classList.add("app__offline");
      menuHeader.style.background = "#9E9E9E";
    }
  }
})();

上面的代碼幫助用戶在 ui視覺上區(qū)分離線和在線狀態(tài)。

js/menu.js
(function () {
  "use strict";

  var menuIconElement = document.querySelector(".header__icon");
  var menuElement = document.querySelector(".menu");
  var menuOverlayElement = document.querySelector(".menu__overlay");

  //Menu click event
  menuIconElement.addEventListener("click", showMenu, false);
  menuOverlayElement.addEventListener("click", hideMenu, false);
  menuElement.addEventListener("transitionend", onTransitionEnd, false);

   //To show menu
  function showMenu() {
    menuElement.style.transform = "translateX(0)";
    menuElement.classList.add("menu--show");
    menuOverlayElement.classList.add("menu__overlay--show");
  }

  //To hide menu
  function hideMenu() {
    menuElement.style.transform = "translateX(-110%)";
    menuElement.classList.remove("menu--show");
    menuOverlayElement.classList.remove("menu__overlay--show");
    menuElement.addEventListener("transitionend", onTransitionEnd, false);
  }

  var touchStartPoint, touchMovePoint;

  /*Swipe from edge to open menu*/

  //`TouchStart` event to find where user start the touch
  document.body.addEventListener("touchstart", function(event) {
    touchStartPoint = event.changedTouches[0].pageX;
    touchMovePoint = touchStartPoint;
  }, false);

  //`TouchMove` event to determine user touch movement
  document.body.addEventListener("touchmove", function(event) {
    touchMovePoint = event.touches[0].pageX;
    if (touchStartPoint < 10 && touchMovePoint > 30) {          
      menuElement.style.transform = "translateX(0)";
    }
  }, false);

  function onTransitionEnd() {
    if (touchStartPoint < 10) {
      menuElement.style.transform = "translateX(0)";
      menuOverlayElement.classList.add("menu__overlay--show");
      menuElement.removeEventListener("transitionend", onTransitionEnd, false); 
    }
  }
})();

上面的代碼作用于菜單省略號按鈕的動畫。

js/toast.js
(function (exports) {
  "use strict";

  var toastContainer = document.querySelector(".toast__container");
 
  //To show notification
  function toast(msg, options) {
    if (!msg) return;

    options = options || 3000;

    var toastMsg = document.createElement("div");
    
    toastMsg.className = "toast__msg";
    toastMsg.textContent = msg;

    toastContainer.appendChild(toastMsg);

    //Show toast for 3secs and hide it
    setTimeout(function () {
      toastMsg.classList.add("toast__msg--hide");
    }, options);

    //Remove the element after hiding
    toastMsg.addEventListener("transitionend", function (event) {
      event.target.parentNode.removeChild(event.target);
    });
  }

  exports.toast = toast; //Make this method available in global
})(typeof window === "undefined" ? module.exports : window);

上面的代碼是是一個 tost 的提示信息框

latest.jsapp.js 現(xiàn)在還是空的。

現(xiàn)在,使用本地服務(wù)器啟動你的應(yīng)用程序,例如 http-server模塊可以幫組你啟動本地服務(wù),您的Web應(yīng)用程序應(yīng)該如下所示:

Side menu

Index Page

Latest Page

Application Shell

您的應(yīng)用殼也在上面突出顯示。現(xiàn)在尚未實現(xiàn)加載動態(tài)內(nèi)容,下一步,我們需要從 Github"s API獲取最新的提交。

獲取動態(tài)內(nèi)容

打開js/latest.js增加下面的代碼

(function() {
  "use strict";

  var app = {
    spinner: document.querySelector(".loader")
  };

  var container = document.querySelector(".container");


  // Get Commit Data from Github API
  function fetchCommits() {
    var url = "https://api.github.com/repos/unicodeveloper/resources-i-like/commits";

    fetch(url)
    .then(function(fetchResponse){ 
      return fetchResponse.json();
    })
    .then(function(response) {

        var commitData = {
            "first": {
              message: response[0].commit.message,
              author: response[0].commit.author.name,
              time: response[0].commit.author.date,
              link: response[0].html_url
            },
            "second": {
              message: response[1].commit.message,
              author: response[1].commit.author.name,
              time: response[1].commit.author.date,
              link: response[1].html_url
            },
            "third": {
              message: response[2].commit.message,
              author: response[2].commit.author.name,
              time: response[2].commit.author.date,
              link: response[2].html_url
            },
            "fourth": {
              message: response[3].commit.message,
              author: response[3].commit.author.name,
              time: response[3].commit.author.date,
              link: response[3].html_url
            },
            "fifth": {
              message: response[4].commit.message,
              author: response[4].commit.author.name,
              time: response[4].commit.author.date,
              link: response[4].html_url
            }
        };

        container.querySelector(".first").innerHTML = 
        "

Message: " + response[0].commit.message + "

" + "

Author: " + response[0].commit.author.name + "

" + "

Time committed: " + (new Date(response[0].commit.author.date)).toUTCString() + "

" + "

" + "Click me to see more!" + "

"; container.querySelector(".second").innerHTML = "

Message: " + response[1].commit.message + "

" + "

Author: " + response[1].commit.author.name + "

" + "

Time committed: " + (new Date(response[1].commit.author.date)).toUTCString() + "

" + "

" + "Click me to see more!" + "

"; container.querySelector(".third").innerHTML = "

Message: " + response[2].commit.message + "

" + "

Author: " + response[2].commit.author.name + "

" + "

Time committed: " + (new Date(response[2].commit.author.date)).toUTCString() + "

" + "

" + "Click me to see more!" + "

"; container.querySelector(".fourth").innerHTML = "

Message: " + response[3].commit.message + "

" + "

Author: " + response[3].commit.author.name + "

" + "

Time committed: " + (new Date(response[3].commit.author.date)).toUTCString() + "

" + "

" + "Click me to see more!" + "

"; container.querySelector(".fifth").innerHTML = "

Message: " + response[4].commit.message + "

" + "

Author: " + response[4].commit.author.name + "

" + "

Time committed: " + (new Date(response[4].commit.author.date)).toUTCString() + "

" + "

" + "Click me to see more!" + "

"; app.spinner.setAttribute("hidden", true); //hide spinner }) .catch(function (error) { console.error(error); }); }; fetchCommits(); })();

此外在你的latest.html引入latest.js

增加 loading 在你的latest.html

....

latest.js你可以觀察到,我們從GitHub的API獲取到數(shù)據(jù)并將其附加到DOM中來,現(xiàn)在獲取后的頁面長這樣子了。

Latest.html 頁面

通過Service Workers預(yù)加載 app shell

為了確保我們的app快速加載和離線工作,我們需要緩存app shell 通過 service worker

首先,在根目錄中創(chuàng)建一個 service worker文件。它的名字sw.js

第二,打開app.js文件和添加這段代碼來實現(xiàn)service worker注冊使用

app.js
  if ("serviceWorker" in navigator) {
     navigator.serviceWorker
             .register("./sw.js")
             .then(function() { console.log("Service Worker Registered"); });
  }

打開sw.js文件并添加這段代碼

sw.js
var cacheName = "pwa-commits-v3";

var filesToCache = [
    "./",
    "./css/style.css",
    "./images/books.png",
    "./images/Home.svg",
    "./images/ic_refresh_white_24px.svg",
    "./images/profile.png",
    "./images/push-off.png",
    "./images/push-on.png",
    "./js/app.js",
    "./js/menu.js",
    "./js/offline.js",
    "./js/toast.js"
];

// Install Service Worker
self.addEventListener("install", function(event) {

    console.log("Service Worker: Installing....");

    event.waitUntil(

        // Open the Cache
        caches.open(cacheName).then(function(cache) {
            console.log("Service Worker: Caching App Shell at the moment......");

            // Add Files to the Cache
            return cache.addAll(filesToCache);
        })
    );
});


// Fired when the Service Worker starts up
self.addEventListener("activate", function(event) {

    console.log("Service Worker: Activating....");

    event.waitUntil(
        caches.keys().then(function(cacheNames) {
            return Promise.all(cacheNames.map(function(key) {
                if( key !== cacheName) {
                    console.log("Service Worker: Removing Old Cache", key);
                    return caches.delete(key);
                }
            }));
        })
    );
    return self.clients.claim();
});


self.addEventListener("fetch", function(event) {

    console.log("Service Worker: Fetch", event.request.url);

    console.log("Url", event.request.url);

    event.respondWith(
        caches.match(event.request).then(function(response) {
            return response || fetch(event.request);
        })
    );
});

就像我在這篇文章的前面部分所解釋的,我們所有的靜態(tài)資源都放到filesToCache數(shù)組里面,當service worker被安裝時,它在瀏覽器中打開緩存并且數(shù)組里面所有文件都被緩存到pwa-commits-v3這個緩存里面。一旦 service worker已經(jīng)安裝,install事件就會觸發(fā)。此階段確保您的service worker在任何應(yīng)用殼文件更改時更新其緩存。fetch事件階段應(yīng)用殼從緩存中獲取數(shù)據(jù)。
注意:為了更容易和更好的方式預(yù)先高速緩存你的資源。檢查谷歌瀏覽器的 sw-toolboxsw-precachelibraries

現(xiàn)在重載你的 web app 并且打開 DevTools,到Application 選項去查看Service Worker面板,確保Update on reload這個選項是勾選的。如下圖

現(xiàn)在,重新加載Web頁面并檢查它。有離線瀏覽么?

Index Page Offline

Yaaay!!! 首頁終于離線也是可以瀏覽了,那么latest頁面是不是顯示最新的提交呢?

Latest Page Offline

Yaaay!!!latest已是離線服務(wù)。但是等一下!數(shù)據(jù)在哪里?提交在哪里?哎呀!我們的 app試圖請求Github API當用戶與Internet斷開連接時,它失敗了。

Data Fetch Failure, Chrome DevTools

我們該怎么辦?處理這個場景有不同的方法。其中一個選項是告訴service worker提供離線頁面。另一種選擇是在第一次加載時緩存提交數(shù)據(jù),在后續(xù)請求中加載本地保存的數(shù)據(jù),然后在用戶連接時獲取最新的數(shù)據(jù)。提交的數(shù)據(jù)可以存儲在IndexedDBlocal Storage

好了,我們現(xiàn)在就此結(jié)束!

附上:

原文地址: https://auth0.com/blog/introduction-to-progressive-apps-part-one/

項目代碼地址:https://github.com/unicodeveloper/pwa-commits

博客文章:https://blog.naice.me/articles/5a31d20a78c3ad318b837f59

如果有那個地方翻譯出錯或者失誤,請各位大神不吝賜教,小弟感激不盡

期待下一篇: 介紹一下漸進式 Web App(即時加載) - Part 2

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

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

相關(guān)文章

  • []介紹一下進式 Web App(即時加載) - Part 2

    摘要:在上一篇,介紹一下漸進式離線的文章中,我們討論了典型的應(yīng)該是什么樣子的并且同時也介紹了。暴露了一個異步,以避免阻塞的加載。但一些研究表明,在某些情況下,它是阻塞的。打開并且添加如下代碼清除緩存并重新加載。 在上一篇,介紹一下漸進式 Web App(離線) - Part 1的文章中,我們討論了典型的pwa應(yīng)該是什么樣子的并且同時也介紹了 server worker。到目前為止,我們已經(jīng)緩...

    doodlewind 評論0 收藏0
  • []介紹一下進式 Web App(即時加載) - Part 2

    摘要:在上一篇,介紹一下漸進式離線的文章中,我們討論了典型的應(yīng)該是什么樣子的并且同時也介紹了。暴露了一個異步,以避免阻塞的加載。但一些研究表明,在某些情況下,它是阻塞的。打開并且添加如下代碼清除緩存并重新加載。 在上一篇,介紹一下漸進式 Web App(離線) - Part 1的文章中,我們討論了典型的pwa應(yīng)該是什么樣子的并且同時也介紹了 server worker。到目前為止,我們已經(jīng)緩...

    godlong_X 評論0 收藏0
  • []介紹一下進式 Web App(即時加載) - Part 2

    摘要:在上一篇,介紹一下漸進式離線的文章中,我們討論了典型的應(yīng)該是什么樣子的并且同時也介紹了。暴露了一個異步,以避免阻塞的加載。但一些研究表明,在某些情況下,它是阻塞的。打開并且添加如下代碼清除緩存并重新加載。 在上一篇,介紹一下漸進式 Web App(離線) - Part 1的文章中,我們討論了典型的pwa應(yīng)該是什么樣子的并且同時也介紹了 server worker。到目前為止,我們已經(jīng)緩...

    YJNldm 評論0 收藏0
  • []介紹一下進式 Web App(離線) - Part 1

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

    Wildcard 評論0 收藏0
  • []介紹一下進式 Web App(離線) - Part 1

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

    gaara 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<