溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

發(fā)布時(shí)間:2021-05-11 09:54:17 來(lái)源:億速云 閱讀:225 作者:小新 欄目:開(kāi)發(fā)技術(shù)

小編給大家分享一下怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

要求

要開(kāi)始學(xué)習(xí)本教程,您必須安裝以下軟件:

  • node 8.9 版本及以上 (https: // nodejs.org/en/download/).     Yarn(https://yarnpkg.com)     Git.

作為本教程初始的工程,你可以clone以下Github庫(kù):

git clone https://github.com/petereijgermans11/progressive-web-app

然后,到以下目錄中  

cd pwa-article / pwa-app-manifest-init

通過(guò)以下命令安裝依賴(lài)并啟動(dòng)工程

npm i && npm start

通過(guò)以下地址打開(kāi)應(yīng)用:http:// localhost:8080

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

應(yīng)用的網(wǎng)址

有許多方法可以訪問(wèn)我的本地主機(jī):為了從遠(yuǎn)程訪問(wèn)發(fā)布在你機(jī)器上的8080端口的地址。為此,您可以使用ngrok。請(qǐng)參閱:https://ngrok.com/

使用以下命令安裝ngrok:

npm install -g ngrok

在終端中運(yùn)行以下命令。該命令為您生成一個(gè)可供外部訪問(wèn)的URL。

ngrok http 8080

然后在Chrome中的移動(dòng)設(shè)備上瀏覽至生成的網(wǎng)址。

PWA需要的技術(shù)組件是什么?

PWA有三個(gè)重要的技術(shù)組件協(xié)調(diào)工作,包括:

Manifest清單文件,Service Worker和在https下運(yùn)行。

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

Manifest清單文件

清單文件是一個(gè)JSON配置文件,其中包含了PWA的基礎(chǔ)信息,例如應(yīng)用的icon,Web應(yīng)用程序名稱(chēng)及背景顏色。如果瀏覽器檢測(cè)到網(wǎng)站存在PWA清單文件,Chrome會(huì)自動(dòng)出現(xiàn)“添加到主屏幕”按鈕。如果用戶點(diǎn)擊同意,該圖標(biāo)將被添加到主屏幕,并且將安裝PWA。

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

創(chuàng)建一個(gè)Manifest.json

PWA的Manifest.json文件如下所示:

JSON格式

{
  "name": "Progressive Selfies",
  "short_name": "PWA Selfies",
  "icons": [
    {
      "src": "/src/images/icons/app-icon-192x192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "/src/images/icons/app-icon-512x512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": "/index.html",
  "scope": ".",
  "display": "standalone",
  "background_color": "#fff",
  "theme_color": "#3f51b5"
}

告訴瀏覽器你應(yīng)用的清單

在與index.html文件相同的級(jí)別的目錄中創(chuàng)建Manifest.json文件。清單文件創(chuàng)建后,將清單文件引用鏈接添加到index.html中。

<link rel=”manifest” href=”/manifest.json”>

Manifest 屬性介紹

Manifest有很多配置屬性,接下來(lái)我們會(huì)對(duì)其中的屬性做一個(gè)簡(jiǎn)單的介紹

  • name、short_name:指定Web應(yīng)用的名稱(chēng),short_name是該應(yīng)用的簡(jiǎn)稱(chēng),當(dāng)沒(méi)有足夠空間展示應(yīng)用的name屬性時(shí),系統(tǒng)就會(huì)使用short_name 。 

  • display:display屬性指定Web應(yīng)用的顯示模式,它有四個(gè)值可供配置:fullscreen、standalone、minimal-ui和browser,但一般常用的屬性就是fullscreen和standalone。    fullscreen:全屏顯示    standalone:這種模式下打開(kāi)的應(yīng)用不會(huì)出現(xiàn)瀏覽器的地址欄,所以因此看起來(lái)更像是一個(gè)原生應(yīng)用    minimal-ui、browser:和使用瀏覽器訪問(wèn)區(qū)別不大。 

  • orientation:控制Web應(yīng)用的顯示的方向及禁止手機(jī)轉(zhuǎn)屏。 

  • icons、background_color:icon用于指定應(yīng)用圖標(biāo),background_color是應(yīng)用加載完成前的背景色,通過(guò)設(shè)置這兩個(gè)屬性,可組合成應(yīng)用的Splash Screen。 

  • theme_color:定義應(yīng)用程序的默認(rèn)主題顏色。 

  • description:設(shè)置應(yīng)用的一段描述內(nèi)容。

以上是pwa 清單文件屬性的一些說(shuō)明,我們通過(guò)將設(shè)置完成的清單文件并將其放置在與index.html文件同級(jí)的目錄中即可完成清單文件的添加。

打開(kāi)Chrome開(kāi)發(fā)者工具 – Application - Manifest,查看添加的清單文件是否加載完成,如果沒(méi)有下圖的信息,我們可以通過(guò)重新啟動(dòng)服務(wù)器npm start來(lái)重新加載。

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

什么是Service Worker?

Service Worker(SW) 是一段JavaScript,它作為瀏覽器和網(wǎng)絡(luò)服務(wù)器間的代理。Service Worker可以在基于瀏覽器的 web 應(yīng)用中實(shí)現(xiàn)如離線緩存、消息推送、靜默更新等 native 應(yīng)用常見(jiàn)的功能,以給 web 應(yīng)用提供更好更豐富的使用體驗(yàn)。

另外,這個(gè)API還允許利用緩存來(lái)支持離線體驗(yàn),從而使開(kāi)發(fā)人員可以完全控制用戶的使用體驗(yàn)

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

Service Worker生命周期

對(duì)于Service Worker,基本設(shè)置的步驟如下:

  • 首先應(yīng)注冊(cè)SW,如果SW已注冊(cè),瀏覽器會(huì)根據(jù)于安裝事件自動(dòng)開(kāi)始安裝。

  • 安裝SW后,它將收到激活事件。此激活事件可用于清理SW早期版本的中使用的資源。

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

實(shí)際操作應(yīng)該首先創(chuàng)建一個(gè)和index.html同級(jí),名為sw.js的空文件。然后再index.html文件中,添加一個(gè)base標(biāo)簽,如下:

<base href="/" rel="external nofollow" >

最后,在src/js/app.js中添加以下代碼注冊(cè)SW。此代碼將在頁(yè)面 “加載”過(guò)程中被激活。

你可以打開(kāi)Chrome DevTools – Application - Service Worker 中檢查SW是否已經(jīng)啟用。

window.addEventListener('load', () => {
    const base = document.querySelector('base');
    let baseUrl = base && base.href || '';
    if (!baseUrl.endsWith('/')) {
        baseUrl = `${baseUrl}/`;
    } 
   
    if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register(`${baseUrl}sw.js`)
            .then( registration => {
            // Registration was successful
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        })
        .catch(err => {
            // registration failed :(
            console.log('ServiceWorker registration failed: ', err);
        });
    }
});

以上這段代碼主要的作用是檢查SW的API在window對(duì)象的navigator屬性中是否可用。window對(duì)象代表瀏覽器窗口。如果SW在navigator中可用,則在頁(yè)面加載時(shí)立即注冊(cè)SW。

雖然注冊(cè)一個(gè)SW很簡(jiǎn)單,但在有些情況下我們依然會(huì)遇到無(wú)法注冊(cè)Service Worker的問(wèn)題,我們來(lái)簡(jiǎn)單看看無(wú)法注冊(cè)SW的原因都有什么并如何解決:

  • 您的應(yīng)用程序無(wú)法在HTTPS下運(yùn)行。在開(kāi)發(fā)過(guò)程中,你可以通過(guò)localhost使用SW。但如果將其部署在網(wǎng)站上時(shí),則需要啟用HTTPS。

  • SW的路徑不正確。

沒(méi)有勾選Update on reload?!?/p>

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

Service Worker 事件

除了install和activate事件外,其他事件還有message、fetch、sync和push事件。

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

將以下代碼添加到你的SW中以監(jiān)聽(tīng)生命周期事件(安裝和激活):

self.addEventListener('install', event => {
    console.log('[Service Worker] Installing Service Worker ...', event);
    event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', event => {
    console.log('[Service Worker] Activating Service Worker ...', event);
    return self.clients.claim();
});

install回調(diào)調(diào)用skipWaiting()函數(shù)來(lái)觸發(fā)activate事件,并告訴Service Worker立即開(kāi)始工作,而無(wú)需等待用戶瀏覽或重新加載頁(yè)面。

skipWaiting()函數(shù)強(qiáng)制等待中的Service Worker成為活動(dòng)的Service Worker。self.skipWaiting()函數(shù)也可以和self.clients.claim()函數(shù)一起使用,以確保對(duì)底層Service Worker的更新立即生效。

在這種情況下,self-property 代表窗口對(duì)象(即你的瀏覽器窗口)。

添加到主屏幕按鈕

"添加到主屏幕按鈕" 允許用戶在其設(shè)備上安裝PWA。為了真正用這個(gè)按鈕安裝PWA,你必須在SW中定義一個(gè)fetch事件處理程序。讓我們?cè)趕w.js中解決這個(gè)問(wèn)題。

self.addEventListener('fetch', event => {
    console.log('[Service Worker] Fetching something ....', event);
    // This fixes a weird bug in Chrome when you open the Developer Tools
    if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
        return;
    }
    event.respondWith(fetch(event.request));
});

Service Worker緩存

Service Worker的強(qiáng)大之處在于其攔截HTTP請(qǐng)求的能力。在這一步中,我們使用這個(gè)選項(xiàng)來(lái)攔截HTTP請(qǐng)求和響應(yīng),直接從緩存為用戶提供閃電般快速的響應(yīng)。

在Service Worker安裝期間進(jìn)行預(yù)緩存

當(dāng)用戶第一次訪問(wèn)你的網(wǎng)站時(shí),SW會(huì)開(kāi)始自行安裝。在這個(gè)安裝階段,你可以將PWA使用的所有頁(yè)面、腳本和樣式文件下載并緩存起來(lái),以下是完成這項(xiàng)工作的sw.js文件代碼:

const CACHE_STATIC_NAME = 'static';
const URLS_TO_PRECACHE = [
    '/',
    'index.html',
    'src/js/app.js',
    'src/js/feed.js',
    'src/lib/material.min.js',
    'src/css/app.css',
    'src/css/feed.css',
    'src/images/main-image.jpg',
    'https://fonts.googleapis.com/css?family=Roboto:400,700',
    'https://fonts.googleapis.com/icon?family=Material+Icons',
];
self.addEventListener('install', event => {
    console.log('[Service Worker] Installing Service Worker ...', event);
    event.waitUntil(
        caches.open(CACHE_STATIC_NAME)
            .then(cache => {
                console.log('[Service Worker] Precaching App Shell');
                cache.addAll(URLS_TO_PRECACHE);
            })
            .then(() => {
                console.log('[ServiceWorker] Skip waiting on install');
                return self.skipWaiting();
            })
    );
});

這段代碼使用安裝事件,并在安裝階段添加了一個(gè)URLS_TO_PRECACHE數(shù)組。一旦調(diào)用開(kāi)啟緩存函數(shù)(caches.open),你就可以使用cache.addAll()函數(shù)來(lái)緩存數(shù)組中的文件。通過(guò)event.waitUntil()方法使用JavaScript promise來(lái)知道安裝需要多長(zhǎng)時(shí)間以及是否成功。

安裝事件會(huì)調(diào)用self.skipWaiting()直接激活SW。如果所有文件都已被成功緩存,SW就會(huì)被安裝。但如果其中一個(gè)文件無(wú)法下載,則安裝步驟將會(huì)失敗。在Chrome開(kāi)發(fā)者工具中,你可以檢查緩存(在Cache Storage中)是否被URLS_TO_PRECACHE數(shù)組中的靜態(tài)文件填充。

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

但是,如果你查看Network選項(xiàng)卡,文件仍然是通過(guò)網(wǎng)絡(luò)獲取的。原因是雖然緩存已經(jīng)準(zhǔn)備就緒了,但我們并沒(méi)有從緩存中讀取引用資源。所以為了完成這部分工作,我們首先要監(jiān)聽(tīng)?wèi)?yīng)用的fetch事件,然后攔截并從緩存中獲取資源,讓我們看看下面的代碼吧:

self.addEventListener('fetch', event => {
    console.log('[Service Worker] Fetching something ....', event);
    event.respondWith(
        caches.match(event.request)
            .then(response => {
                if (response) {
                    console.log(response);
                    return response;
                }
                return fetch(event.request);
            })
    );
});

我們使用caches.match()函數(shù)檢查傳入的URL是否與當(dāng)前緩存中可能存在的資源匹配。如果匹配,我們就返回該緩存資源,但如果該資源不存在于緩存中,我們就像正常情況下一樣繼續(xù)獲取請(qǐng)求的資源。

在Service Worker安裝并激活后,刷新頁(yè)面并再次檢查網(wǎng)絡(luò)選項(xiàng)卡。現(xiàn)在,Service Worker將攔截HTTP請(qǐng)求,并從緩存中即時(shí)加載相應(yīng)的資源,而不是向服務(wù)器發(fā)出網(wǎng)絡(luò)請(qǐng)求。

現(xiàn)在,如果我們?cè)诰W(wǎng)絡(luò)選項(xiàng)卡中設(shè)置離線模式,我們的應(yīng)用也依然能正常訪問(wèn)。

后臺(tái)傳輸

Background Fetch API是SW的后臺(tái)功能,它允許用戶在后臺(tái)下載大文件、視頻和音樂(lè)等資源。在獲取/傳輸過(guò)程中,你的用戶即便關(guān)閉標(biāo)簽,乃至關(guān)閉整個(gè)瀏覽器,也不會(huì)清除傳輸任務(wù)。當(dāng)用戶再次打開(kāi)瀏覽器后,傳輸過(guò)程將恢復(fù)。這個(gè)API也可以將傳輸?shù)倪M(jìn)度可以顯示給用戶,用戶可以取消或暫停這個(gè)過(guò)程。

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

默認(rèn)情況下,后臺(tái)傳輸功能是不可用的,你必須通過(guò)url(chrome://flags/#enable-experimental-web-platform-features)允許chrome的“Experimental Web Platform features”選項(xiàng)

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

以下是如何實(shí)現(xiàn)此類(lèi)后臺(tái)傳輸?shù)氖纠?/p>

在你的index.html文件中添加ID為“ bgFetchButton”的按鈕

<button id="bgFetchButton">Store assets locally</button>

然后,在加載事件處理程序中的app.js中添加用于執(zhí)行后臺(tái)傳輸?shù)拇a

window.addEventListener(‘load', () => {
...
       bgFetchButton = document.querySelector(‘#bgFetchButton');
       bgFetchButton.addEventListener(‘click', async event => {
         try {
            const registration = await navigator.serviceWorker.ready;
            registration.backgroundFetch.fetch(‘my-fetch', [new              Request(`${baseUrl}src/images/main-image-lg.jpg`)]);
         } catch (err) {
            console.error(err);
         }
     });
...
});

上面的代碼在以下條件下開(kāi)始執(zhí)行后臺(tái)傳輸:

  • 用戶點(diǎn)擊ID為bgFetchButton的按鈕

  • SW已注冊(cè)

后臺(tái)傳輸必須在異步函數(shù)中執(zhí)行,因?yàn)閭鬏斶^(guò)程不能阻塞用戶界面。

傳輸完成后放入緩存

self.addEventListener(‘backgroundfetchsuccess', event => {
  console.log(‘[Service Worker]: Background Fetch Success', event.registration);   event.waitUntil(
   (async function() {
     try {
     // Iterating the records to populate the cache
       const cache = await caches.open(event.registration.id); const records =          await event.registration.matchAll(); const promises = records.map(async          record => {
         const response = await record.responseReady;
         await cache.put(record.request, response);
       });
       await Promise.all(promises);
     } catch (err) {
       console.log(‘[Service Worker]: Caching error');
     }
   })()
  );
});

這段代碼由以下步驟組成:

  • 當(dāng)Background Fetch傳輸完成,你的SW將收到Background Fetch成功事件。

  • 創(chuàng)建并打開(kāi)一個(gè)與registration.id同名的新緩存。

  • 通過(guò)registration.matchAll()獲取所有記錄并遍歷。

最后,通過(guò)Promise.all(),執(zhí)行所有的承諾。

怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA

以上是“怎么開(kāi)發(fā)一個(gè)漸進(jìn)式Web應(yīng)用程序PWA”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI