網路上實作向的資料比較少,更多的是概念以及非常基礎的service worker相關教學,因此將測試及推論的結果做紀錄.
demo:https://parker-nuxt-lab.vercel.app/frontend-api-cach-test
漸進式網頁(Progressive Web Apps,又稱PWA),Google於2016年提出的概念,主要希望能讓網頁能夠更接近app,甚至能夠像是app一樣安裝在裝置上,並且從各方資料來看,完整的PWA除了能安裝於裝置上以外,也應符合RWD及Service Workers相關規範,因此一個良好的PWA應該要提供HTTPS的安全連線,並且只要是能用瀏覽器的任何裝置都能使用,同時可以安裝到裝置上,還要可以在無網路狀態下完全或有限的操作網頁才行.

PWA中最常被提及的概念就是透過Service Worker將網站的資源先行請求後快取在瀏覽器上,讓使用者在切換頁面的時候能夠更快速的取得資源,api的資源也可以,不過經過測試加上查找資料的結果,只能快取HTTP GET的資料,原因是Service Worker的 cache api 只能快取符合資料幂等性的資料,而大多數情況下只有HTTP GET是符合資料幂等性,雖然也有少數資料顯示可以客制化HTTP POST做快取,不過目前仍找不到有效的範本,Google PWA的框架技術 Workbox 的介紹頁面疑似曾經有相關的介紹,不過相關的連結紀錄都已失效,或許需要熟透PWA及Service Worker知識及技術才能更近一步做調整,不過根據 ServiceWorker github 上的 issue ,或許在將來相關規範成熟也可以直接存入GET以外的請求資料.

由於若要再不依賴任何框架工具的前提下,符合PWA的特性需要深入研究 快取政策 及 Service Worker 更新策略 等相關知識,為求方便入門,本文透過 workbox-build 生成 Workbox 的方式實作PWA,先確定正常建製後的效果為何,才更方便檢驗手刻的版本是否正常
workbox-build 是 Google發布並維護的專屬於 Service Worker 用的打包轉譯工具,由於 Service Worker 最終執行於瀏覽器主程序外,因此 PWA 的 Service Worker 開發完畢後,並不會有任何入口使打包工具去取出並進行打包轉譯,除非直接以不需轉譯的方式轉寫並放置對應的公開位置,不然仍無法正常執行,而 workbox-build 正能解決此問題,並且能更進一步進行minify化,達到進一步效能優化的效果.
workbox-build 在 Nuxt上有出專屬的插件:@vite-pwa/nuxt ,可以直接在 nuxt.config.js 裡透過 pwa 傳入 json物件的方式做設定,導入範例:
export default defineNuxtConfig({
// ... 省略
modules: [
// ... 省略
'@vite-pwa/nuxt'
],
pwa: {
// PWA相關設定
},
// ...省略
});
PWA的設定參數概要:
export default defineNuxtConfig({
// ... 省略
pwa: {
injectRegister: 'script-defer',
manifest: {
name: 'Parker的Nuxt實驗室',
short_name: 'Nuxt Lab',
lang: 'zh-tw',
icons: [
{
src: '/img/ico/apple-touch-icon.png',
sizes: '180x180',
type: 'image/png',
purpose: 'maskable'
},
{
src: '/img/ico/web-app-manifest-192x192.png',
sizes: '192x192',
type: 'image/png',
purpose: 'maskable'
},
{
src: '/img/ico/web-app-manifest-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'maskable'
},
{
src: '/img/ico/web-app-manifest-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any',
},
{
src: '/img/ico/favicon.ico',
sizes: '48x48',
type: 'image/png',
purpose: 'monochrome'
}
],
theme_color: '#2c64e3',
background_color: '#2c64e3',
display: 'standalone'
},
workbox: {
runtimeCaching: [
{
urlPattern: /^https:\\/\\/fonts\\.googleapis\\.com\\/.*/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'google-fonts-cache',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365 // <== 365 days
},
cacheableResponse: {
statuses: [0, 200]
}
}
},
{
urlPattern: /^https:\\/\\/fonts\\.gstatic\\.com\\/.*/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'gstatic-fonts-cache',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365 // <== 365 days
},
cacheableResponse: {
statuses: [0, 200]
},
}
}
],
maximumFileSizeToCacheInBytes: 1024 * 1024 * 22, // 22MB
globPatterns: ['**/*'],
navigateFallback: null,
}
},
// ...省略
});
PWA效果預覽:

可以看到在開發者工具的網路頁籤中,在初次載入就跑了很多次資源呼叫,這就是PWA的Service Workers正在做快取,而第二次再載入時就能看到已經被快取的資源,其大小欄位會顯示 (Service Workers) 的字樣,這時如果再次切到應用程式頁籤中,選擇 Service Workers 選項,就能看到目前的Service Workers的運行狀態,這時可以嘗試斷開網路,部分不依賴即時網路訊號的功能能夠正常運行,這樣PWA的基本功能就都有包含到了.
參考資料: