Mainline 是一家線上服飾零售商,販售時尚界知名的設計師品牌。這家位於英國的公司委託其內部專家團隊,並與重要合作夥伴建立策略聯盟,為所有人提供順暢的購物體驗。Mainline 也在 100 多個國家/地區,提供量身打造的地區當地網站和應用程式,因此將持續確保電子商務產品提供的功能無法比競爭對手脫穎而出。
挑戰
Mainline Menswear 的目標是配合「行動優先」的願景,推出符合「行動優先」願景的漸進式功能,讓目前的行動裝置專用網站能夠更臻完善,而智慧型手機市場的想法也日漸增加。
解決方案
目標是建構並推出 PWA,以補足 Mainline Menswear 網站的原始行動裝置版,然後將統計資料與目前在 Android 和 iOS 上推出的混合型行動應用程式進行比較。
應用程式推出後,Mainline Menswear 的部分使用者開始使用,他們可以判斷 PWA、應用程式和網頁之間的主要統計資料差異。
Mainline 在將網站轉換為漸進式網頁應用程式時,採用了這個做法,確保他們為網站選用的架構 (Nuxt.js,採用 Vue.js) 能與時俱進,並讓他們充分利用快速變化的網路技術。
結果
139%
PWA 中的單次工作階段頁數 (相較於網頁) 更多。
161%
PWA 與網頁的工作階段持續時間比較。
10%
PWA 的跳出率低於網站
12.5%
PWA 的平均訂單價值高於網站
55%
PWA 的轉換率升幅 (與網站相比)。
243%
PWA 的單次工作階段收益高於網站。
深入探討技術
Mainline Menswear 採用 Nuxt.js 架構整合及轉譯網站,這是單頁應用程式 (SPA)。
產生服務工作者檔案
為了產生服務工作站,Mainline Menswear 透過 nuxt/pwa
Workbox 模組的自訂實作方式新增設定。
他們之所以設計 nuxt/pwa
模組,是為了方便團隊在 Service Worker 檔案中新增更多自訂項目,因為他們在使用標準版時無法執行上述操作,或是檔案發生問題。其中一項最佳化做法就在網站的離線功能方面為主,例如提供預設離線網頁,並在離線時收集分析。
網頁應用程式資訊清單剖析
團隊產生資訊清單,其中含有不同的行動應用程式圖示大小,以及其他網頁應用程式詳細資料 (例如 name
、description
和 theme_color
):
{
"name": "Mainline Menswear",
"short_name": "MMW",
"description": "Shop mens designer clothes with Mainline Menswear. Famous brands including Hugo Boss, Adidas, and Emporio Armani.",
"icons": [
{
"src": "/_nuxt/icons/icon_512.c2336e.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#107cbb"
}
安裝完成後,您可以從主畫面啟動網頁應用程式,而不會受到瀏覽器干擾。如要這麼做,請在網路應用程式資訊清單檔案中新增 display
參數:
{
"display": "standalone"
}
最後,該公司現在只需在資訊清單的 start_url
欄位中附加 utm_source
參數,即可輕鬆追蹤有多少使用者正從主畫面造訪他們的網頁應用程式:
{
"start_url": "/?utm_source=pwa"
}
執行階段快取功能,加快導覽速度
為了提升網頁速度,並為回訪使用者提供更優質的使用者體驗,您必須為網頁應用程式快取。
針對網路快取,有許多不同的做法。團隊會同時使用 HTTP 快取和 Cache API,在用戶端快取資產。
Cache API 可讓 Mainline Menswear 更精細地控管快取資產,以便將複雜的策略套用至各種檔案類型。雖然這一切聽起來複雜,且難以設定及維護,但 Workbox 提供簡單的方式,讓您宣告這類複雜的策略,並減輕維護的負擔。
快取 CSS 和 JS
針對 CSS 和 JS 檔案,團隊選擇使用 StaleWhileRevalidate
Workbox 策略快取這些檔案,並透過快取提供這些檔案。這項策略可讓他們快速提供所有 Nuxt CSS 和 JS 檔案,大幅提升網站效能。同時,系統會在背景將檔案更新為最新版本,以便在下次造訪時使用:
/* sw.js */
workbox.routing.registerRoute(
/\/_nuxt\/.*(?:js|css)$/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'css_js',
}),
'GET',
);
快取 Google 字型
Google 字體快取策略取決於兩種檔案類型:
- 包含
@font-face
宣告的樣式表。 - 基礎字型檔案 (在前述樣式表中要求)。
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
workbox.routing.registerRoute(
/https:\/\/fonts\.googleapis\.com\/*/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'google_fonts_stylesheets',
}),
'GET',
);
// Cache the underlying font files with a cache-first strategy for 1 year.
workbox.routing.registerRoute(
/https:\/\/fonts\.gstatic\.com\/*/,
new workbox.strategies.CacheFirst({
cacheName: 'google_fonts_webfonts',
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200],
}),
new workbox.expiration.ExpirationPlugin({
maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
maxEntries: 30,
}),
],
}),
'GET',
);
快取圖片
在圖片方面,Mainline Menswear 決定採用兩種策略。第一個策略適用於來自 CDN 的所有圖片,通常是產品圖片。他們的網頁圖片很多,因此會注意不要占用太多使用者的裝置儲存空間。因此,他們透過 Workbox 新增了只快取來自 CDN 的圖片策略,並使用 ExpirationPlugin
最多快取 60 張圖片。
要求的第 61 張圖片會取代第 1 (最舊) 的映像檔,這樣任何時間點都只快取超過 60 張產品圖片。
workbox.routing.registerRoute(
({ url, request }) =>
url.origin === 'https://mainline-menswear-res.cloudinary.com' &&
request.destination === 'image',
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'product_images',
plugins: [
new workbox.expiration.ExpirationPlugin({
// Only cache 60 images.
maxEntries: 60,
purgeOnQuotaError: true,
}),
],
}),
);
第二種圖片策略會處理來源要求的其他圖片。這些圖片在整個來源中通常數量很少且很小,但為了安全起見,這些快取圖片的數量也設有 60 張的上限。
workbox.routing.registerRoute(
/\.(?:png|gif|jpg|jpeg|svg|webp)$/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'images',
plugins: [
new workbox.expiration.ExpirationPlugin({
// Only cache 60 images.
maxEntries: 60,
purgeOnQuotaError: true,
}),
],
}),
);
提供離線功能
在 Service Worker 安裝及啟用後,系統會預先快取離線頁面。其方法是為所有離線依附元件建立清單,包括離線 HTML 檔案和離線 SVG 圖示。
const OFFLINE_HTML = '/offline/offline.html';
const PRECACHE = [
{ url: OFFLINE_HTML, revision: '70f044fda3e9647a98f084763ae2c32a' },
{ url: '/offline/offline.svg', revision: 'efe016c546d7ba9f20aefc0afa9fc74a' },
];
接著,預先快取清單會饋送至 Workbox,後者會負責處理所有繁重的工作,包括將網址新增至快取,檢查是否有任何修訂版本不相符的情況,以及使用 CacheFirst
策略更新及提供預先快取的檔案。
workbox.precaching.precacheAndRoute(PRECACHE);
處理離線瀏覽
啟用 Service Worker 並友善載入離線頁面後,即可回應使用者的離線導航要求。雖然 Mainline Menswear 的網路應用程式是 SPA,但只有在網頁重新載入、使用者關閉並重新開啟瀏覽器分頁,或是在離線時從主畫面啟動網路應用程式時,才會顯示離線網頁。
為達成這項目標,Mainline Menswear 使用預先快取的離線網頁,為失敗的 NavigationRoute
要求提供備用方案:
const htmlHandler = new workbox.strategies.NetworkOnly();
const navigationRoute = new workbox.routing.NavigationRoute(({ event }) => {
const request = event.request;
// A NavigationRoute matches navigation requests in the browser, i.e. requests for HTML
return htmlHandler.handle({ event, request }).catch(() => caches.match(OFFLINE_HTML, {
ignoreSearch: true
}));
});
workbox.routing.registerRoute(navigationRoute);
示範
回報成功安裝
除了主畫面啟動追蹤功能 (在網頁應用程式資訊清單中使用 "start_url": "/?utm_source=pwa"
) 之外,網頁應用程式還會監聽 window
的 appinstalled
事件,藉此回報應用程式安裝成功:
window.addEventListener('appinstalled', (evt) => {
ga('send', 'event', 'Install', 'Success');
});
將 PWA 功能新增至網站,可進一步提升消費者的購物體驗,且相較於[平台專屬]應用程式,可更快上市。
開發部門主管 Andy Hoyle
結論
如要進一步瞭解漸進式網頁應用程式及其建構方式,請前往 web.dev 的漸進式網頁應用程式專區。
如要進一步瞭解更多漸進式網頁應用程式個案研究,請瀏覽個案研究專區。