PWA介紹及快速上手搭建一個PWA應用

PWA初次體驗

? 前言:本示例不用安裝任何東西

部分資源來自網(wǎng)絡資源及PWA官網(wǎng)羊异,不要把PWA想象的太復雜,跟著示例走一下读慎,你行的。

PWA介紹

一個新的前端技術(shù)槐雾,PWA( 全稱:Progressive Web App )也就是說這是個漸進式的網(wǎng)頁應用程序夭委。

官網(wǎng):https://developers.google.com/web/progressive-web-apps/

是 Google 在 2015 年提出,2016年6月才推廣的項目募强。是結(jié)合了一系列現(xiàn)代Web技術(shù)的組合株灸,在網(wǎng)頁應用中實現(xiàn)和原生應用相近的用戶體驗。

官網(wǎng)上給出 PWA 的宣傳是 :Reliable( 可靠的 )擎值、Fast( 快速的 )慌烧、Engaging( 可參與的 )

Reliable:當用戶從手機主屏幕啟動時,不用考慮網(wǎng)絡的狀態(tài)是如何鸠儿,都可以立刻加載出 PWA屹蚊。

Fast:這一點應該都很熟悉了吧厕氨,站在用戶的角度來考慮,如果一個網(wǎng)頁加載速度有點長的話汹粤,那么我們會放棄瀏覽該網(wǎng)站命斧,所以 PWA 在這一點上做的很好,他的加載速度是很快的玄括。

Engaging: PWA 可以添加在用戶的主屏幕上冯丙,不用從應用商店進行下載,他們通過網(wǎng)絡應用程序 Manifest file 提供類似于 APP 的使用體驗( 在 Android 上可以設置全屏顯示哦遭京,由于 Safari 支持度的問題胃惜,所以在 IOS 上并不可以 ),并且還能進行 ”推送通知” 哪雕。

PWA關(guān)鍵技術(shù)

Service Worker(可以理解為服務工廠)

Manifest(應用清單)

Push Notification(推送通知)

Service Worker

以下用SW來表示

SW 是什么呢船殉?這個是離線緩存文件。我們 PWA 技術(shù)使用的就是它斯嚎!SW 是瀏覽器在后臺獨立于網(wǎng)頁運行的腳本利虫,它打開了通向不需要網(wǎng)頁或用戶交互的功能的大門,因為使用了它堡僻,才會有的那個 Reliable 特性吧糠惫,SW 作用于 瀏覽器于服務器之間,相當于一個代理服務器钉疫。

瀏覽器支持

順便帶一句:目前只能在 HTTPS 環(huán)境下才能使用SW硼讽,因為SW 的權(quán)利比較大,能夠直接截取和返回用戶的請求牲阁,所以要考慮一下安全性問題固阁。

image

事件機制

image

功能(還是比較逆天的)

后臺數(shù)據(jù)的同步

從其他域獲取資源請求

接受計算密集型數(shù)據(jù)的更新,多頁面共享該數(shù)據(jù)

客戶端編譯與依賴管理

后端服務的hook機制

根據(jù)URL模式城菊,自定義模板

性能優(yōu)化

消息推送

定時默認更新

地理圍欄

生命周期

image

Parsed ( 解析成功 ): 首次注冊 SW 時备燃,瀏覽器解決腳本并獲得入口點,如果解析成功凌唬,就可以訪問到 SW 注冊對象并齐,在這一點中我們需要在 HTML 頁面中添加一個判斷,判斷該瀏覽器是否支持 SW 客税。

Installing ( 正在安裝 ):SW 腳本解析完成之后况褪,瀏覽器會嘗試進行安裝,installing 中 install 事件被執(zhí)行霎挟,如果其中有 event.waitUntil ( ) 方法窝剖,則 installing 事件會一直等到該方法中的 Promise 完成之后才會成功麻掸,如果 Promise 被拒絕酥夭,則安裝失敗,SW會進入 Redundant( 廢棄 )狀態(tài)。

Installed / Waiting (安裝成功/等待中):如果安裝成功熬北,SW 將會進入這個狀態(tài)疙描。

Activating ( 正在激活 ):處于 waiting 狀態(tài)的 SW 發(fā)生以下情況,將會進入 activating 狀態(tài)中:

當前已無激活狀態(tài)的 worker 讶隐、 SW腳本中的 self.skipWaiting()方法被調(diào)用 ( ps: self 是 SW 中作用于全局的對象起胰,這個方法根據(jù)英文翻譯過來也能明白什么意思啦,跳過等待狀態(tài) )巫延、用戶已關(guān)閉 SW 作用域下的所有頁面效五,從而釋放了當前處于激活狀態(tài)的 worker、超出指定時間炉峰,從而釋放當前處于激活狀態(tài)的 worker

Activated ( 激活成功 ):該狀態(tài)畏妖,其成功接收了 document 全面控制的激活態(tài) worker 。

Redundant ( 廢棄 ):這個狀態(tài)的出現(xiàn)時有原因的疼阔,如果 installing 事件失敗或者 activating 事件失敗或者新的 SW 替換其成為激活態(tài) worker 戒劫。installing 事件失敗和 activating 事件失敗的信息我們可以在 Chrome 瀏覽器的 DevTools 中查看

一個很不錯的全面介紹sw的教程:https://www.villainhr.com/page/2017/01/08/Service%20Worker%20%E5%85%A8%E9%9D%A2%E8%BF%9B%E9%98%B6

Manifest

Web App Manifest 是一個 W3C 規(guī)范,它定義了一個基于 JSON 的 List 婆廊。Manifest 在 PWA 中的作用有:

?? ? ? ? ? ? ? ? ? 能夠?qū)⒛銥g覽的網(wǎng)頁添加到你的手機屏幕上

?? ? ? ? ? ? ? ? ? 在 Android 上能夠全屏啟動迅细,不顯示地址欄 ( 由于 Iphone 手機的瀏覽器是 Safari ,所以不支持哦)

?? ? ? ? ? ? ? ? ? 控制屏幕 橫屏 / 豎屏 展示

?? ? ? ? ? ? ? ? ? 定義啟動畫面

?? ? ? ? ? ? ? ? ? 可以設置你的應用啟動是從主屏幕啟動還是從 URL 啟動

?? ? ? ? ? ? ? ? ? 可以設置你添加屏幕上的應用程序圖標淘邻、名字茵典、圖標大小

Push Notification

Push 和 Notification 是兩個不同的功能,涉及到兩個 API 列荔。

?? Notification 是瀏覽器發(fā)出的通知消息敬尺。

?? Push 和 Notification 的關(guān)系,Push:服務器端將更新的信息傳遞給 SW 贴浙,Notification: SW 將更新的信息推送給用戶砂吞。

PWA示例

準備

我們先創(chuàng)建一個關(guān)于 PWA 的項目文件夾,

進入文件夾下我們準備一張 120x120的圖片一張崎溃,作為我們的應用程序圖標蜻直。

創(chuàng)建一個 index.html? 文件

創(chuàng)建一個 main.css 文件

創(chuàng)建一個 manifest.json 文件

創(chuàng)建一個 sw.js 文件

image

index.html

<!DOCTYPE html>Hello PWA

Hello PWA

// 檢測瀏覽器是否支持SWif(navigator.serviceWorker !=null){? ? navigator.serviceWorker.register('sw.js')? ? .then(function(registartion){console.log('支持sw:',registartion.scope)? ? })? }

main.css

h3{color:#f00;}

manifest.json

short_name: “ " 用戶主屏幕上的應用名字

display : “standalone"? 設置啟動樣式,讓您的網(wǎng)絡應用隱藏瀏覽器的 URL 地址欄

start_url : “/“ 設置啟動網(wǎng)址袁串,如果不提供的話概而,默認是使用當前頁面

theme_color : “ “? 用來告知瀏覽器用什么顏色來為地址欄等 UI 元素著色

background_color: “ ” 設置啟動頁面的背景顏色

icons:””? 就是添加到主屏幕之后的圖標

{"name":"一個PWA示例","short_name":"PWA示例","start_url":"/index.html","display":"standalone","background_color":"#fff","theme_color":"#3eaf7c","icons": [? ? {"src":"/youhun.jpg","sizes":"120x120","type":"image/png"}? ],}

sw.js

看網(wǎng)上很多人都安裝的hs和ngrok去調(diào)試,在這里為了照顧新手我是直接引用的sw

處理靜態(tài)緩存囱修,首先定義需要緩存的路徑赎瑰,以及需要緩存的靜態(tài)文件的列表。

借助 SW 注冊完成安裝 SW 時破镰,抓取資源寫入緩存中餐曼。使用了一個方法那就是 self.skipWaiting( ) 压储,為了在頁面更新的過程當中,新的 SW 腳本能夠立刻激活和生效源譬。

importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.1.0/workbox-sw.js");varcacheStorageKey ='minimal-pwa-1'varcacheList=['/','index.html','main.css','youhun.jpg']self.addEventListener('install',e =>{? e.waitUntil(? ? caches.open(cacheStorageKey)? ? .then(cache=>cache.addAll(cacheList))? ? .then(()=>self.skipWaiting())? )})

處理動態(tài)緩存集惋,我們監(jiān)聽 fetch 事件,在 caches 中去 match 事件的 request 踩娘,如果 response 不為空的話就返回 response 刮刑,最后返回 fetch 請求,在 fetch 事件中我們可以手動生成 response 返回給頁面养渴。

更新靜態(tài)資源雷绢,緩存的資源會跟隨著版本的更新會過期的,所以會根據(jù)緩存的字符串名稱清除舊緩存理卑。在新安裝的 SW 中通過調(diào)用 self.clients.claim( ) 取得頁面的控制權(quán)习寸,這樣之后打開頁面都會使用版本更新的緩存。舊的 SW 腳本不在控制著頁面之后會被停止傻工,也就是會進入 Redundant 期霞溪。

self.addEventListener('fetch',function(e){? e.respondWith(? ? caches.match(e.request).then(function(response){if(response !=null){returnresponse? ? ? }returnfetch(e.request.url)? ? })? )})self.addEventListener('activate',function(e){? e.waitUntil(//獲取所有cache名稱caches.keys().then(cacheNames=>{returnPromise.all(// 獲取所有不同于當前版本名稱cache下的內(nèi)容cacheNames.filter(cacheNames=>{returncacheNames !== cacheStorageKey? ? ? ? }).map(cacheNames=>{returncaches.delete(cacheNames)? ? ? ? })? ? ? )? ? }).then(()=>{returnself.clients.claim()? ? })? )})

部署

我們可以把當前pwa目錄的所有內(nèi)容都扔進服務器中,或者coding Pages和gitHub Pages也是可以的中捆,當然鸯匹,記得開啟https。在上變介紹過SW的權(quán)利比較大泄伪,為了安全性殴蓬,我們使用https協(xié)議來訪問。

試著訪問一下蟋滴,我們這里用的coding Pages并且綁定了自己的域名

打開 chrom 的調(diào)試工具染厅,打開 application ,點擊 service workers 之后我們會發(fā)現(xiàn) sw.js 腳本已經(jīng)存到了 SW 中 津函。

image

我們打開 Network 刷新頁面一下肖粮,看看,我們的頁面資源來自 SW 而不是其他的地方尔苦,在 Console 中也打印出了我們在 index.html 中判斷的語句涩馆,瀏覽器支持就會打印出這一句話。

image

接下來我們斷網(wǎng)操作允坚,在 Application 中給 Offline 打上對勾就行啦魂那。然后刷新頁面,我們?nèi)匀荒芸吹街暗捻撁娉硐睿蚓褪俏覀冊谏蠄D看到涯雅,他的資源是從 SW 上獲得到的。當我們第一次打開這個頁面的時候展运,Resopnse 對象被存到了 Cache Storage ( 定義在 SW 規(guī)范中 活逆,相關(guān)資料請同學們自行查詢啦 )中轻腺,我們看下圖:

image

通過存放到 Cache Storage 中,我們下次訪問的時候如果是弱網(wǎng)或者斷網(wǎng)的情況下划乖,就可以不走網(wǎng)絡請求,而直接就能將本地緩存的內(nèi)容展示給用戶挤土,優(yōu)化用戶的弱網(wǎng)及斷網(wǎng)體驗琴庵。

這個時候肯定會有同學在想,如果內(nèi)容更新了仰美,那么頁面展示的內(nèi)容是新內(nèi)容呢還是舊內(nèi)容呢迷殿?下面我們操作一下,打開 index.html 文件咖杂,我們在 body 中添加一個 p 標簽 庆寺,然后回到頁面刷新。

image

image

我們看到诉字,頁面上的內(nèi)容并沒有顯示出我剛剛添加的那個 p 標簽懦尝。這說明了,我們拿到的數(shù)據(jù)還是從 Cache Storage 中獲取到的壤圃,Cache Storage中的內(nèi)容并沒有更新陵霉,強制刷新也不行哦,那么我們怎么才能讓我剛剛添加的那個 p 標簽顯示出來呢伍绳。

我們打開 sw.js 腳本文件踊挠,我們修改一下 cacheStorageKey。

image

修改后冲杀,我們再次打開該網(wǎng)址效床,強制刷新下或者關(guān)掉瀏覽器重新打開。

頁面中出現(xiàn)了剛剛添加的P標簽权谁,我們再看一下 Cache Storage 中的緩存名字剩檀,已經(jīng)被修改。

image

總結(jié)

如果是使用coding或者gitHub提供的pages服務旺芽,則需要注意最好綁定下獨立域名谨朝。如果不綁定則注意下文件請求路徑即可。

研究PWA門檻不低甥绿,部署的服務器要求HTTPS字币,ServiceWorker涉及API眾多,需要單獨學習共缕,另外npm中也已經(jīng)有這個包了https://www.npmjs.com/package/web-pwa洗出,玩玩可以,真正部署到項目生產(chǎn)環(huán)境可能坑很多图谷,但有坑填坑翩活,不折騰還叫前端么

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末阱洪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子菠镇,更是在濱河造成了極大的恐慌冗荸,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件利耍,死亡現(xiàn)場離奇詭異蚌本,居然都是意外死亡,警方通過查閱死者的電腦和手機隘梨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門程癌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人轴猎,你說我怎么就攤上這事嵌莉。” “怎么了捻脖?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵锐峭,是天一觀的道長。 經(jīng)常有香客問我可婶,道長只祠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任扰肌,我火速辦了婚禮抛寝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘曙旭。我一直安慰自己盗舰,他們只是感情好,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布桂躏。 她就那樣靜靜地躺著钻趋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剂习。 梳的紋絲不亂的頭發(fā)上蛮位,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天,我揣著相機與錄音鳞绕,去河邊找鬼失仁。 笑死,一個胖子當著我的面吹牛们何,可吹牛的內(nèi)容都是我干的舒憾。 我是一名探鬼主播彬呻,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼哑蔫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了茬射?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤冒签,失蹤者是張志新(化名)和其女友劉穎在抛,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體萧恕,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡刚梭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了廊鸥。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡辖所,死狀恐怖惰说,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缘回,我是刑警寧澤吆视,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站酥宴,受9級特大地震影響啦吧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拙寡,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一授滓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肆糕,春花似錦般堆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至始赎,卻和暖如春和橙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背造垛。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工魔招, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人五辽。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓仆百,卻偏偏與公主長得像,于是被迫代替她去往敵國和親奔脐。 傳聞我的和親對象是個殘疾皇子俄周,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容