Mainline là nhà bán lẻ quần áo trực tuyến cung cấp các thương hiệu thiết kế lớn nhất trong ngành thời trang. Công ty ở Vương quốc Anh này tin tưởng đội ngũ chuyên gia nội bộ, kết hợp chiến lược với các đối tác chính để mang đến trải nghiệm mua sắm suôn sẻ cho tất cả mọi người. Với sự hiện diện trên thị trường tại hơn 100 quốc gia thông qua 7 trang web theo lãnh thổ được xây dựng tuỳ chỉnh và một ứng dụng, Mainline sẽ tiếp tục đảm bảo rằng dịch vụ thương mại điện tử của họ có thể cạnh tranh với các đối thủ.
Thách thức
Mục tiêu của Mainline Menswear là bổ sung cho trang web được tối ưu hoá cho thiết bị di động hiện tại bằng các tính năng tiến bộ, tuân thủ tầm nhìn "ưu tiên thiết bị di động", tập trung vào thiết kế và chức năng thân thiện với thiết bị di động, đồng thời chú ý đến thị trường điện thoại thông minh đang phát triển.
Giải pháp
Mục tiêu là xây dựng và khởi chạy một ứng dụng web tiến bộ (PWA) bổ sung cho phiên bản thân thiện với thiết bị di động ban đầu của trang web Mainline Menswear, sau đó so sánh số liệu thống kê với ứng dụng di động kết hợp hiện có trên Android và iOS.
Sau khi ứng dụng ra mắt và được một số ít người dùng Mainline Menswear sử dụng, họ có thể xác định sự khác biệt về số liệu thống kê chính giữa PWA, ứng dụng và Web.
Phương pháp mà Mainline sử dụng khi chuyển đổi trang web của họ thành PWA là đảm bảo rằng khung mà họ chọn cho trang web (Nuxt.js, sử dụng Vue.js) sẽ phù hợp với tương lai và cho phép họ tận dụng công nghệ web đang phát triển nhanh chóng.
Kết quả
139%
Số trang nhiều hơn mỗi phiên trong PWA so với web.
161%
Thời lượng phiên dài hơn trong PWA so với web.
10%
Tỷ lệ thoát thấp hơn trong PWA so với trên web
12,5%
Giá trị trung bình của đơn đặt hàng trong PWA cao hơn so với trên web
55%
Tỷ lệ chuyển đổi cao hơn trong PWA so với web.
243%
Doanh thu trên mỗi phiên cao hơn trong PWA so với web.
Tìm hiểu chuyên sâu về kỹ thuật
Mainline Menswear đang sử dụng khung Nuxt.js để gói và hiển thị trang web của họ. Đây là một ứng dụng trang đơn (SPA).
Tạo tệp trình chạy dịch vụ
Để tạo trình chạy dịch vụ, Mainline Menswear đã thêm cấu hình thông qua hoạt động triển khai tuỳ chỉnh của mô-đun Hộp làm việc nuxt/pwa
.
Lý do họ phân nhánh mô-đun nuxt/pwa
là để cho phép nhóm thêm nhiều tuỳ chỉnh hơn vào tệp worker dịch vụ mà họ không thể hoặc gặp vấn đề khi sử dụng phiên bản chuẩn.
Một trong những hoạt động tối ưu hoá đó là liên quan đến chức năng ngoại tuyến của trang web, chẳng hạn như phân phát trang ngoại tuyến mặc định và thu thập số liệu phân tích khi không có kết nối mạng.
Phân tích tệp kê khai ứng dụng web
Nhóm đã tạo một tệp kê khai có biểu tượng cho nhiều kích thước biểu tượng ứng dụng di động và các thông tin chi tiết khác về ứng dụng web như name
, description
và 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"
}
Sau khi cài đặt, bạn có thể chạy ứng dụng web từ màn hình chính mà không cần trình duyệt. Bạn có thể thực hiện việc này bằng cách thêm thông số display
vào tệp kê khai ứng dụng web:
{
"display": "standalone"
}
Cuối cùng nhưng không kém phần quan trọng, công ty hiện có thể dễ dàng theo dõi số lượng người dùng truy cập vào ứng dụng web của họ từ màn hình chính bằng cách chỉ cần thêm tham số utm_source
vào trường start_url
của tệp kê khai:
{
"start_url": "/?utm_source=pwa"
}
Lưu vào bộ nhớ đệm trong thời gian chạy để điều hướng nhanh hơn
Việc lưu vào bộ nhớ đệm cho ứng dụng web là điều bắt buộc để tối ưu hoá tốc độ trang và mang lại trải nghiệm tốt hơn cho người dùng cũ.
Có khá nhiều phương pháp khác nhau để lưu vào bộ nhớ đệm trên web. Nhóm đang sử dụng kết hợp bộ nhớ đệm HTTP và API bộ nhớ đệm để lưu các thành phần vào bộ nhớ đệm ở phía máy khách.
API Bộ nhớ đệm giúp Mainline Menswear kiểm soát tốt hơn các tài sản đã lưu vào bộ nhớ đệm, cho phép áp dụng các chiến lược phức tạp cho từng loại tệp. Mặc dù tất cả những tính năng này nghe có vẻ phức tạp và khó thiết lập cũng như khó bảo trì, nhưng Workbox cung cấp cho họ một cách dễ dàng để khai báo các chiến lược phức tạp như vậy, giúp giảm bớt công sức bảo trì.
Lưu CSS và JS vào bộ nhớ đệm
Đối với các tệp CSS và JS, nhóm đã chọn lưu các tệp này vào bộ nhớ đệm và phân phát các tệp đó qua bộ nhớ đệm bằng cách sử dụng chiến lược Workbox StaleWhileRevalidate
. Chiến lược này cho phép họ phân phát nhanh tất cả tệp CSS và JS của Nuxt, giúp tăng đáng kể hiệu suất của trang web.
Đồng thời, các tệp đang được cập nhật ở chế độ nền lên phiên bản mới nhất cho lần truy cập tiếp theo:
/* sw.js */
workbox.routing.registerRoute(
/\/_nuxt\/.*(?:js|css)$/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'css_js',
}),
'GET',
);
Lưu phông chữ Google vào bộ nhớ đệm
Chiến lược để lưu Google Fonts vào bộ nhớ đệm phụ thuộc vào hai loại tệp:
- Tệp định kiểu chứa các phần khai báo
@font-face
. - Các tệp phông chữ cơ bản (được yêu cầu trong biểu định kiểu đã đề cập ở trên).
// 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',
);
Lưu hình ảnh vào bộ nhớ đệm
Đối với hình ảnh, Mainline Menswear quyết định sử dụng hai chiến lược. Chiến lược đầu tiên áp dụng cho tất cả hình ảnh đến từ CDN của họ, thường là hình ảnh sản phẩm. Trang của họ chứa nhiều hình ảnh nên họ ý thức được việc không chiếm quá nhiều bộ nhớ thiết bị của người dùng. Vì vậy, thông qua Workbox, họ đã thêm một chiến lược lưu hình ảnh vào bộ nhớ đệm chỉ từ CDN của họ với tối đa 60 hình ảnh bằng cách sử dụng ExpirationPlugin
.
Hình ảnh thứ 61 (mới nhất) được yêu cầu sẽ thay thế hình ảnh thứ 1 (cũ nhất) để không có quá 60 hình ảnh sản phẩm được lưu vào bộ nhớ đệm tại bất kỳ thời điểm nào.
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,
}),
],
}),
);
Chiến lược hình ảnh thứ hai xử lý phần còn lại của hình ảnh mà nguồn gốc yêu cầu. Những hình ảnh này thường rất ít và nhỏ trên toàn bộ nguồn gốc, nhưng để đảm bảo an toàn, số lượng hình ảnh được lưu vào bộ nhớ đệm này cũng bị giới hạn ở mức 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,
}),
],
}),
);
Cung cấp chức năng ngoại tuyến
Trang ngoại tuyến được lưu vào bộ nhớ đệm trước ngay sau khi trình chạy dịch vụ được cài đặt và kích hoạt. Chúng thực hiện việc này bằng cách tạo một danh sách tất cả các phần phụ thuộc ngoại tuyến: tệp HTML ngoại tuyến và biểu tượng SVG ngoại tuyến.
const OFFLINE_HTML = '/offline/offline.html';
const PRECACHE = [
{ url: OFFLINE_HTML, revision: '70f044fda3e9647a98f084763ae2c32a' },
{ url: '/offline/offline.svg', revision: 'efe016c546d7ba9f20aefc0afa9fc74a' },
];
Sau đó, danh sách lưu vào bộ nhớ đệm trước được đưa vào Workbox. Workbox sẽ xử lý mọi công việc nặng nhọc liên quan đến việc thêm các URL vào bộ nhớ đệm, kiểm tra xem có bất kỳ bản sửa đổi nào không khớp hay không, cập nhật và phân phát các tệp được lưu vào bộ nhớ đệm trước bằng chiến lược CacheFirst
.
workbox.precaching.precacheAndRoute(PRECACHE);
Xử lý thao tác điều hướng khi không có mạng
Sau khi trình chạy dịch vụ kích hoạt và trang ngoại tuyến được lưu trước trong bộ nhớ đệm, trình chạy dịch vụ này sẽ được dùng để phản hồi các yêu cầu điều hướng ngoại tuyến của người dùng. Mặc dù ứng dụng web của Mainline Menswear là một SPA, nhưng trang ngoại tuyến chỉ hiển thị sau khi trang tải lại, người dùng đóng và mở lại thẻ trình duyệt hoặc khi ứng dụng web được khởi chạy từ màn hình chính khi không có kết nối mạng.
Để đạt được điều này, Mainline Menswear đã cung cấp phương án dự phòng cho các yêu cầu NavigationRoute
không thành công bằng trang ngoại tuyến được lưu vào bộ nhớ đệm trước:
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);
Bản minh hoạ
Báo cáo lượt cài đặt thành công
Ngoài tính năng theo dõi lượt khởi chạy trên màn hình chính (với "start_url": "/?utm_source=pwa"
trong tệp kê khai ứng dụng web), ứng dụng web cũng báo cáo các lượt cài đặt ứng dụng thành công bằng cách theo dõi sự kiện appinstalled
trên window
:
window.addEventListener('appinstalled', (evt) => {
ga('send', 'event', 'Install', 'Success');
});
Việc thêm các tính năng PWA vào trang web sẽ giúp cải thiện trải nghiệm mua sắm của khách hàng với bạn và giúp bạn tiếp thị nhanh hơn so với ứng dụng [dành riêng cho nền tảng].
Andy Hoyle, Trưởng bộ phận phát triển
Kết luận
Để tìm hiểu thêm về ứng dụng web tiến bộ và cách tạo ứng dụng này, hãy truy cập vào mục Ứng dụng web tiến bộ trên web.dev.
Để đọc thêm các nghiên cứu điển hình về Ứng dụng web tiến bộ, hãy duyệt đến phần nghiên cứu điển hình.