Mainline Menswear ที่ใช้ PWA และมีอัตรา Conversion เพิ่มขึ้น 55%

Mainline เป็นผู้ค้าปลีกเสื้อผ้าออนไลน์ที่จำหน่ายแบรนด์ดีไซเนอร์ชื่อดังในวงการแฟชั่น บริษัทในสหราชอาณาจักรไว้วางใจให้ทีมผู้เชี่ยวชาญภายในทำงานร่วมกันอย่างมีกลยุทธ์กับพาร์ทเนอร์ที่สำคัญ เพื่อมอบประสบการณ์การช็อปปิ้งที่ราบรื่นให้แก่ทุกคน ด้วยการแสดงตัวตนในตลาดในกว่า 100 ประเทศผ่านเว็บไซต์และแอป 7 เขตแดนที่สร้างแบบกำหนดเอง Mainline จะยังคงดูแลให้ข้อเสนออีคอมเมิร์ซนั้นแข่งขันกับคู่แข่งได้

ชาเลนจ์

เป้าหมายของ Mainline Menswear คือการเสริมเว็บไซต์ปัจจุบันที่เพิ่มประสิทธิภาพสำหรับอุปกรณ์เคลื่อนที่ด้วยฟีเจอร์ที่ก้าวหน้าซึ่งเป็นไปตามวิสัยทัศน์ที่ "อุปกรณ์เคลื่อนที่เป็นอันดับแรก" ของบริษัท โดยมุ่งเน้นที่การออกแบบและฟังก์ชันการทำงานที่เหมาะกับอุปกรณ์เคลื่อนที่ โดยคำนึงถึงตลาดสมาร์ทโฟนที่กำลังเติบโตขึ้นเรื่อยๆ

โซลูชัน

วัตถุประสงค์คือการสร้างและเปิดตัว PWA ที่ช่วยเสริมเว็บไซต์ Mainline Menswear เวอร์ชันเดิมที่เหมาะกับอุปกรณ์เคลื่อนที่ จากนั้นเปรียบเทียบสถิติกับแอปบนอุปกรณ์เคลื่อนที่แบบผสมซึ่งขณะนี้มีให้บริการบน Android และ iOS

เมื่อเปิดตัวแอปและมีผู้ใช้งาน Mainline Menswear ไม่กี่กลุ่ม พวกเขาก็ระบุความแตกต่างของสถิติที่สำคัญระหว่าง PWA, แอป และเว็บได้

วิธีการที่ Mainline ใช้ในการแปลงเว็บไซต์ไปเป็น PWA คือเพื่อให้มั่นใจว่าเฟรมเวิร์กที่บริษัทเลือกสำหรับเว็บไซต์ของตน (Nuxt.js การใช้ Vue.js) จะประสบความสำเร็จในระยะยาว และช่วยให้ลูกค้าได้รับประโยชน์จากเทคโนโลยีเว็บที่ก้าวหน้าอย่างรวดเร็ว

ผลลัพธ์

139%

จำนวนหน้าต่อเซสชันใน PWA มากขึ้นเมื่อเทียบกับเว็บ

161%

ระยะเวลาเซสชันที่นานขึ้นใน PWA เมื่อเทียบกับเว็บ

10%

อัตราตีกลับใน PWA ที่ต่ำลงเมื่อเทียบกับเว็บ

12.5%

มูลค่าการสั่งซื้อเฉลี่ยใน PWA สูงกว่าเมื่อเทียบกับเว็บ

55%

อัตรา Conversion ใน PWA สูงกว่าเมื่อเทียบกับเว็บ

243%

รายได้ต่อเซสชันใน PWA สูงกว่าเมื่อเทียบกับเว็บ

ข้อมูลเจาะลึกทางเทคนิค

Mainline Menswear ใช้เฟรมเวิร์ก Nuxt.js เพื่อรวมและแสดงผลเว็บไซต์ของตน ซึ่งเป็นแอปพลิเคชันหน้าเว็บเดียว (SPA)

กำลังสร้างไฟล์ Service Worker

สำหรับการสร้างโปรแกรมทำงานของบริการ Mainline Menswear ได้เพิ่มการกำหนดค่าผ่านการใช้งานโมดูล Workbox ของ nuxt/pwa แบบกำหนดเองด้วย

เหตุผลที่แยกโมดูล nuxt/pwa ออกคือการอนุญาตให้ทีมเพิ่มการปรับแต่งเพิ่มเติมลงในไฟล์ Service Worker ที่เดิมไม่สามารถทำได้หรือมีปัญหาเมื่อใช้เวอร์ชันมาตรฐาน การเพิ่มประสิทธิภาพดังกล่าวอย่างหนึ่งอยู่ที่ฟังก์ชันการทำงานแบบออฟไลน์ของเว็บไซต์ เช่น การแสดงหน้าเว็บออฟไลน์เริ่มต้นและรวบรวมการวิเคราะห์ขณะออฟไลน์

โครงสร้างของไฟล์ Manifest ของเว็บแอป

ทีมได้สร้างไฟล์ Manifest ที่มีไอคอนสำหรับไอคอนแอปบนอุปกรณ์เคลื่อนที่ขนาดต่างๆ และรายละเอียดอื่นๆ ของเว็บแอป เช่น 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 ในไฟล์ Manifest ของเว็บแอป:

{
  "display": "standalone"
}

สุดท้ายแต่ไม่ท้ายสุด ตอนนี้บริษัทสามารถติดตามจำนวนผู้ใช้ที่เข้าชมเว็บแอปจากหน้าจอหลักได้ง่ายๆ เพียงใส่พารามิเตอร์ utm_source ต่อท้ายช่อง start_url ของไฟล์ Manifest ดังนี้

{
  "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 Fonts จะขึ้นอยู่กับไฟล์ 2 ประเภทดังนี้

  • สไตล์ชีตที่มีการประกาศ @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 ตัดสินใจใช้กลยุทธ์ 2 อย่าง กลยุทธ์แรกใช้กับรูปภาพทั้งหมดที่มาจาก CDN ซึ่งมักเป็นรูปภาพผลิตภัณฑ์ หน้าเว็บของผู้ใช้มีรูปภาพมากเกินไป จึงระวังไม่ให้ใช้พื้นที่เก็บข้อมูลอุปกรณ์ของผู้ใช้มากเกินไป โดยทาง Workbox ได้เพิ่มกลยุทธ์ที่จะแคชรูปภาพที่มาจาก CDN ของตนเองเท่านั้นที่มีรูปภาพสูงสุด 60 ภาพโดยใช้ ExpirationPlugin

รูปภาพที่ 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,
      }),
    ],
  }),
);

กลยุทธ์รูปภาพที่ 2 จะจัดการรูปภาพที่เหลือซึ่งต้นทางขอ รูปภาพเหล่านี้มักจะมีจำนวนน้อยมากและเล็กมากๆ ทั่วทั้งต้นทาง แต่รูปภาพดังกล่าวยังปลอดภัยอยู่ จำนวนรูปภาพที่แคชไว้เหล่านี้จะจำกัดไว้ที่ 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 ซึ่งทำได้โดยการสร้างรายการทรัพยากร Dependency ออฟไลน์ทั้งหมด ได้แก่ ไฟล์ HTML ออฟไลน์และไอคอน SVG ออฟไลน์

const OFFLINE_HTML = '/offline/offline.html';
const PRECACHE = [
  { url: OFFLINE_HTML, revision: '70f044fda3e9647a98f084763ae2c32a' },
  { url: '/offline/offline.svg', revision: 'efe016c546d7ba9f20aefc0afa9fc74a' },
];

จากนั้นระบบจะป้อนรายการแคชล่วงหน้าไปยัง Workbox เพื่อจัดการกับการลดภาระงานทั้งหมดของการเพิ่ม URL ลงในแคช ตรวจหาการแก้ไขที่ไม่ตรงกัน การอัปเดต และแสดงไฟล์ที่แคชไว้ล่วงหน้าด้วยกลยุทธ์ 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);

ข้อมูลประชากร

ตัวอย่างหน้าออฟไลน์ตามที่แสดงใน www.mainlinemenswear.co.uk

กำลังรายงานการติดตั้งที่สำเร็จ

นอกเหนือจากการติดตามการเปิดหน้าจอหลัก (มี "start_url": "/?utm_source=pwa" ในไฟล์ Manifest ของเว็บแอปพลิเคชันแล้ว) เว็บแอปยังรายงานการติดตั้งแอปที่ประสบความสำเร็จด้วยการฟังเหตุการณ์ appinstalled ในวันที่ window ด้วย

window.addEventListener('appinstalled', (evt) => {
  ga('send', 'event', 'Install', 'Success');
});

การเพิ่มความสามารถของ PWA ลงในเว็บไซต์จะช่วยยกระดับประสบการณ์การช็อปปิ้งกับคุณให้ดียิ่งขึ้น และจะออกสู่ตลาดได้เร็วกว่าแอป [เฉพาะแพลตฟอร์ม]

Andy Hoyle หัวหน้าฝ่ายพัฒนา

บทสรุป

ดูข้อมูลเพิ่มเติมเกี่ยวกับ Progressive Web App และวิธีสร้างได้ที่ส่วน Progressive Web App ใน web.dev

หากต้องการอ่านกรณีศึกษาของ Progressive Web App ให้ไปที่ส่วนกรณีศึกษา