使用 Workbox 创建 PWA 应用
關(guān)注?前端瓶子君,回復(fù)“交流”
加入我們一起學(xué)習(xí),天天進(jìn)步
來源:悖論?
https://juejin.cn/post/6895306314747281421
前言
最近公司項(xiàng)目迭代逐漸放緩,下班時(shí)間逐漸變早,所以本著漸進(jìn)增加的理念,在下班后,將公司項(xiàng)目進(jìn)行了一下PWA改造
為何要改造成PWA
用戶需求。我們的用戶有許多電腦小白,不想記網(wǎng)址,又不會使用瀏覽器的收藏功能。以前使用的同類軟件都有桌面版,有一種覺得桌面版比網(wǎng)頁版可靠,使用簡單的錯(cuò)覺,曾多次在釘釘售后群里反映,如何將網(wǎng)頁保存至桌面,方便他下次直接在桌面打開
PWA是漸進(jìn)式的,如果用戶的瀏覽器不支持ServiceWorker等構(gòu)建PWA所需的API,并不會對其造成使用上的影響,并且通過埋點(diǎn)平臺獲知,我們用戶Chrome瀏覽器數(shù)量占到80%左右
離線緩存,可安裝,可攔截fetch等功能,對我個(gè)人有一定的吸引力,希望學(xué)習(xí)使用
開始改造
為了快速改造成PWA, 我這里選擇使用了谷歌推出的PWA工具庫workbox, 并且結(jié)合webpack創(chuàng)建serviceWorker文件
安裝依賴
npm?install?--save-dev?workbox-webpack-plugin npm?install?--save?workbox-core?workbox-routing?workbox-strategies?workbox-precaching?workbox-expiration?workbox-cacheable-responseworkbox-webpack-plugin里提供了兩種插件,GenerateSW以及InjectManifest。
GenerateSW
GenerateSW插件可以通過配置直接編譯生成對應(yīng)的serviceWorker文件,不需要我們直接編寫serviceWorker文件。使用方式大致如下:
import?{?InjectManifest?}?from?'workbox-webpack-plugin';new?GenerateSW({skipWaiting:?true,clientsClaim:?true,mode:?'development',runtimeCaching:?[{urlPattern:?/^https?\:\/\/.+?\.alicdn.com\/.+$/,handler:?'StaleWhileRevalidate'},], });通過GenerateSW編譯生成serviceWorker文件雖然簡單,但不夠靈活,所以實(shí)際上我使用了另一個(gè)InjectManifestPlugin插件
InjectManifest
InjectManifest主要做了兩件事
將webpack編譯生成的資源文件清單,以變量self.__WB_MANIFEST的形式注入到我們提供的serviceWorker模板文件中
編譯我們提供的模板文件,生成目標(biāo)serviceWorker文件
使用方式大致如下:
const?{?InjectManifest?}?=?require('workbox-webpack-plugin'); new?InjectManifest({swSrc:?path.resolve('src/sw.js'),swDest:?path.resolve(BUILD_DEST,?'sw.js'), }),編寫serviceWorker模板文件
預(yù)緩存靜態(tài)資源
預(yù)緩存會在serviceWork激活后,立即請求并緩存所有預(yù)緩存清單中的文件, 之后下載請求同一資源時(shí),會使用緩存優(yōu)先策略,優(yōu)先使用已經(jīng)預(yù)緩存的資源
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);路由請求緩存
這里有一個(gè)需要注意的點(diǎn),alicdn靜態(tài)資源與我司網(wǎng)頁域名不是同域名,存在跨域,當(dāng)請求靜態(tài)資源的時(shí)候,會返回不透明響應(yīng)(opaque response); 當(dāng)我們使用Cache-First策略緩存不透明響應(yīng)時(shí),workbox會提示我們不要使用這個(gè)策略來緩存不透明響應(yīng),因?yàn)椴煌该黜憫?yīng)對JavaScript來說是一個(gè)黑盒,無法獲取到正確的status code, headers, body, 所以我們緩存中的資源是不可靠的;并且當(dāng)我們緩存不透明響應(yīng)時(shí),緩存所占有的空間遠(yuǎn)大于實(shí)際資源的大小,容易造成DOMException: Quota exceeded.?所以需要處理下不透明響應(yīng)的緩存
不透明響應(yīng)變成透明響應(yīng)
既然不透明響應(yīng)會造成問題,那只要把不透明響應(yīng)變成透明響應(yīng),那就應(yīng)該沒問題了。
經(jīng)過查看,我發(fā)現(xiàn)alicdn的響應(yīng)頭會返回access-control-allow-origin: *, 后端是支持cors跨域資源共享的。既然如此,只要當(dāng)我們請求靜態(tài)資源的時(shí)候,讓請求走cors應(yīng)該就可以了。于是,我嘗試在其中一個(gè)img標(biāo)簽中,啟用cors
不透明響應(yīng)成功變成透明響應(yīng)。但如果給所有<img /><script /><link />標(biāo)簽添加crossorigin, 這工作量也太大了。有沒有統(tǒng)一處理的方法呢?有。可以通過攔截fetch請求來統(tǒng)一處理, 在使用workbox的場景下,可以通過設(shè)置緩存策略類中fetchOptions來實(shí)現(xiàn)
registerRoute(/^https?\:\/\/.*?\.alicdn.com\/.+?\.(css|js|png|jpg|jpeg|svg|gif|webp)$/,new?CacheFirst({cacheName:?'alicdn-cache',plugins:?[new?CacheableResponsePlugin({statuses:?[200]}),new?ExpirationPlugin({maxEntries:?300,maxAgeSeconds:?7?*?24?*?60?*?60,}),],//?添加如下fetch?optionsfetchOptions:?{mode:?'cors',credentials:?'omit',},}), );創(chuàng)建manifest.json文件
通過manifest配置文件,可以指定pwa應(yīng)用的圖標(biāo),初始頁面,背景色,主題色,顯示模式等內(nèi)容
//?manifest.json {???"name":?"xxx","short_name":?"xxx","icons":?[{"src":?"/static/images/favicon@144x144.png","sizes":?"144x144","type":?"image/png"}],"start_url":?"/index.html","display":?"standalone","background_color":?"#000","theme_color":?"#000" }<link?rel="manifest"?href="/manifest.json">結(jié)語
最后,我們的PWA應(yīng)用改造就完成了。PWA技術(shù)是一系列技術(shù)的集合,這里,我只用到了serviceWorker, manifest,push/notification等沒有涉及到,如果日后有這個(gè)必要,再增加相應(yīng)功能
延伸擴(kuò)展
什么是不透明響應(yīng)(opaque response)
簡單的說,不透明響應(yīng)就是當(dāng)我們使用fetch,并且設(shè)置no-cors,來請求跨域資源時(shí)獲取到的響應(yīng)
fetch('https://www.baidu.com/img/flexible/logo/pc/result@2.png',?{mode:?'no-cors' }).then(response?=>?{return?console.log(response) }).catch(error?=>?{return?console.log(error) });打印的結(jié)果為
Response?{body:?nullbodyUsed:?falseheaders:?{},ok:?falseredirected:?falsestatus:?0statusText:?""type:?"opaque"url:?"" }從Response中,我們可以發(fā)現(xiàn)不透明響應(yīng)
status為0,而非200等http status code
statusText為空
headers也為空
body也為空
總之,我們(JavaScript)獲取不到這個(gè)Response中的內(nèi)容
最后
歡迎關(guān)注「前端瓶子君」,回復(fù)「交流」加入前端交流群!
歡迎關(guān)注「前端瓶子君」,回復(fù)「算法」自動(dòng)加入,從0到1構(gòu)建完整的數(shù)據(jù)結(jié)構(gòu)與算法體系!
另外,每周還有手寫源碼題,瓶子君也會解答喲!
》》面試官也在看的算法資料《《
“在看和轉(zhuǎn)發(fā)”就是最大的支持
總結(jié)
以上是生活随笔為你收集整理的使用 Workbox 创建 PWA 应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。