KIếN THứC WEBSITE › PERFORMANCE

Service Worker cache — 5 bước implement offline cho WordPress

Service Worker cache — 5 bước implement offline cho WordPress 2026

Service Worker là file JavaScript chạy nền giữa trình duyệt và mạng — cache tài nguyên theo chiến lược tùy chọn, cho phép trang hoạt động khi mất mạng. Bài hướng dẫn 5 bước triển khai Service Worker cache cho WordPress 2026: đăng ký, chọn chiến lược, quản lý cập nhật, debug, và mẫu offline-ready cho shop.

Service Worker là gì — khả năng và phạm vi

service worker cache — Service Worker là gì — khả năng và phạm vi
Service Worker là gì — khả năng và phạm vi

Service Worker là file JS đăng ký với trình duyệt, chạy trên luồng riêng (không liên quan giao diện), và can thiệp vào mọi yêu cầu mạng từ trang.

Trình duyệt lưu phản hồi qua Service Worker theo chiến lược do lập trình viên định nghĩa. Khác hoàn toàn với cache HTTP thông thường do máy chủ quyết định.

3 khả năng chính

  • Cache offline: phục vụ tài nguyên từ cache khi mạng gặp sự cố. Trang vẫn hoạt động được với nội dung đã lưu.
  • Chiến lược cache tùy biến: cache-first, network-first, stale-while-revalidate — mỗi loại tài nguyên một chiến lược phù hợp.
  • Push notification và background sync: thông báo người dùng khi đóng tab, đồng bộ dữ liệu khi mạng khôi phục.

Mức độ hỗ trợ trình duyệt 2026

Service Worker được hỗ trợ trên 96%+ trình duyệt toàn cầu — Chrome 40+, Firefox 44+, Safari 11.1+. Người dùng trình duyệt không hỗ trợ vẫn truy cập trang bình thường (graceful degradation).

Service Worker yêu cầu HTTPS hoặc localhost (cho môi trường phát triển). WordPress trên hosting HTTP không thể dùng tính năng này.

Bước 1 — Đăng ký Service Worker

Bước 1 — Đăng ký Service Worker
Sơ đồ minh hoạ — Bước 1 — Đăng ký Service Worker

Trang chủ đăng ký SW qua navigator.serviceWorker.register(). File SW phải cùng origin và được phục vụ qua HTTPS.

Mã đăng ký

// main.js (theme JS)
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js')
      .then(reg => console.log('SW registered:', reg.scope))
      .catch(err => console.error('SW registration failed:', err));
  });
}

Vòng đời Service Worker

  1. install: SW tải lần đầu, kích hoạt sự kiện “install”. Đây là lúc pre-cache tài nguyên quan trọng.
  2. activate: SW nhận quyền kiểm soát, kích hoạt sự kiện “activate”. Dọn dẹp cache phiên bản cũ tại đây.
  3. fetch: mỗi yêu cầu từ trang kích hoạt sự kiện “fetch”. SW can thiệp, phục vụ từ cache hoặc chuyển thẳng đến mạng.

Phạm vi kiểm soát của SW

SW chỉ kiểm soát các URL trong phạm vi (scope) của nó. Đặt file /sw.js ở thư mục gốc để kiểm soát toàn bộ trang.

File /blog/sw.js chỉ kiểm soát các URL bắt đầu bằng /blog/. Cần cẩn thận khi đặt SW trong thư mục con.

Bước 2 — Chọn chiến lược cache

Bước 2 — Chọn chiến lược cache
Bước 2 — Chọn chiến lược cache

Có 4 chiến lược chính. Chọn theo đặc điểm từng loại tài nguyên — tài nguyên tĩnh ưu tiên cache, API dữ liệu ưu tiên mạng.

Chiến lược 1: Cache-first

// sw.js
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cached => {
      return cached || fetch(event.request).then(resp => {
        return caches.open('v1').then(cache => {
          cache.put(event.request, resp.clone());
          return resp;
        });
      });
    })
  );
});

// Dùng cho: CSS/JS/font có hash — không bao giờ thay đổi.

Chiến lược 2: Network-first

// sw.js
self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request)
      .then(resp => {
        const clone = resp.clone();
        caches.open('v1').then(cache => cache.put(event.request, clone));
        return resp;
      })
      .catch(() => caches.match(event.request))
  );
});

// Dùng cho: trang HTML, API JSON động. Mạng gặp sự cố → fallback từ cache.

Chiến lược 3: Stale-while-revalidate

// sw.js
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.open('v1').then(cache => {
      return cache.match(event.request).then(cached => {
        const fetched = fetch(event.request).then(resp => {
          cache.put(event.request, resp.clone());
          return resp;
        });
        return cached || fetched;
      });
    })
  );
});

// Dùng cho: ảnh, tài nguyên OK phục vụ bản cũ ngay, cập nhật ngầm.

Bảng chọn chiến lược theo loại tài nguyên

Loại tài nguyên Chiến lược Lý do
CSS/JS có hash Cache-first Nội dung không bao giờ thay đổi
Trang HTML Network-first Cần nội dung mới nhất, cache là dự phòng
Ảnh sản phẩm Stale-while-revalidate Tốc độ tải quan trọng, cập nhật ngầm chấp nhận được
API sản phẩm Stale-while-revalidate Hiển thị ngay, làm mới nền
Giỏ hàng/thanh toán Bypass hoàn toàn Dữ liệu cá nhân, không được cache

Bước 3 — Quản lý vòng đời cập nhật

SW cập nhật khi file sw.js thay đổi nội dung. Trình duyệt tự phát hiện, cài phiên bản mới, kích hoạt khi tab được đóng và mở lại.

Kích hoạt cập nhật ngay lập tức

// sw.js
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('v2').then(cache =>
      cache.addAll(['/critical.css', '/main.js', '/logo.svg'])
    )
  );
  self.skipWaiting();  // Bỏ qua giai đoạn chờ
});

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(keys => Promise.all(
      keys.filter(k => k !== 'v2').map(k => caches.delete(k))
    ))
  );
  self.clients.claim();  // Nhận quyền kiểm soát ngay
});

Chiến lược đặt tên phiên bản cache

Đặt tên cache theo phiên bản (v1, v2, v3) và xóa phiên bản cũ trong sự kiện activate. Không xóa phiên bản cũ sẽ khiến cache phình to theo thời gian.

Khi deploy bản mới, tăng số phiên bản trong sw.js. Trình duyệt sẽ phát hiện thay đổi và cài SW mới trong nền.

Bước 3-4 — Quản lý cập nhật và debug

SW chạy nền, không có console trực tiếp. DevTools có panel riêng cho SW tại tab Application.

Quy trình debug

  1. Mở DevTools (F12) → tab “Application”.
  2. Thanh bên → “Service Workers”.
  3. Xem trạng thái: activated / waiting / installing.
  4. Tích “Update on reload” để buộc cập nhật SW mỗi lần tải lại (chỉ dùng khi phát triển).
  5. Tích “Bypass for network” để bỏ qua SW, kiểm tra hành vi mạng thuần túy.
  6. Tab “Cache Storage” → xem tên cache và các entry đã lưu.
  7. Console của SW riêng: console.log trong sw.js xuất hiện ở đây.

Lỗi phổ biến khi dùng Service Worker

  • Cache không bao giờ cập nhật: quên dọn phiên bản cũ trong activate — trình duyệt phục vụ cache lỗi thời mãi mãi.
  • Trang lỗi bị cache: deploy bản có lỗi, SW cache lại — người dùng thấy lỗi ngay cả sau khi sửa. Thêm cơ chế unregister khẩn cấp.
  • HTTPS bắt buộc: SW không hoạt động trên HTTP thường. WordPress dev trên XAMPP với HTTP không test được.
  • Phạm vi scope sai: SW chỉ kiểm soát URL cùng cấp hoặc sâu hơn vị trí file.

Bước 5 — Mẫu offline-ready cho shop WordPress

Shop offline-ready là khi người dùng vẫn xem được sản phẩm và trang quan trọng dù mạng gặp sự cố. Quan trọng với người dùng di động ở vùng mạng yếu.

Dùng plugin SuperPWA

  • Plugin miễn phí, thiết lập PWA cho WordPress chỉ vài bước.
  • Tự tạo manifest.json và sw.js cơ bản.
  • Cache tài nguyên tĩnh và các trang đã truy cập gần đây.
  • Thêm nút “Add to Home Screen” cho người dùng di động.

Mẫu SW tùy biến cho shop

  • Pre-cache trang chủ và 5-10 trang sản phẩm quan trọng nhất (sự kiện install).
  • Network-first cho trang HTML — luôn lấy nội dung mới khi có mạng.
  • Cache-first cho ảnh, font, CSS/JS có hash.
  • Stale-while-revalidate cho danh sách sản phẩm API.
  • Trang fallback /offline.html khi mạng gặp sự cố và không có cache.

Kết hợp Service Worker với cache HTTP

Service Worker và cache HTTP header không thay thế nhau — chúng hoạt động ở 2 lớp khác nhau. Cache header (Cache-Control, ETag) điều khiển cache trình duyệt và CDN.

SW điều khiển Cache API riêng của trình duyệt.

Kết hợp tốt nhất: cache HTTP set đúng cho CDN (xem hướng dẫn Cloudflare). SW lo phần offline và chiến lược cache nâng cao phía người dùng.

Service Worker và Core Web Vitals

SW ảnh hưởng đến LCP và INP khi cấu hình sai. Cache-first cho HTML có thể phục vụ nội dung cũ quá lâu.

Network-first cho tài nguyên tĩnh lớn làm LCP chậm không cần thiết.

Đọc thêm tại LCP — cách đo và tối ưuINP thay thế FID 2024 để hiểu chiến lược cache ảnh hưởng đến chỉ số này thế nào.

Bài liên quan

Câu hỏi thường gặp

Service Worker có ảnh hưởng đến SEO không?

Không nếu dùng network-first cho HTML. Googlebot fetch trực tiếp từ mạng — không dùng SW của trình duyệt.

Tuy nhiên, nếu cache-first cho HTML dẫn đến nội dung cũ, người dùng thật sẽ thấy trang lỗi thời.

Quy tắc an toàn: luôn dùng network-first cho trang HTML, cache-first chỉ cho tài nguyên tĩnh có hash.

WordPress mặc định có Service Worker không?

Không. Cần cài plugin (SuperPWA, PWA for WP) hoặc viết SW tùy biến.

Một số theme premium (Astra Pro, GeneratePress Premium) có addon PWA nhưng không phổ biến.

Nếu đang dùng Next.js headless, thư viện next-pwa tích hợp SW tự động với ít cấu hình hơn.

SW có cache giỏ hàng riêng từng người dùng được không?

Không nên. Giỏ hàng gắn với phiên đăng nhập — cache có thể rò rỉ dữ liệu giữa các người dùng nếu không xử lý cẩn thận.

Cấu hình SW bỏ qua hoàn toàn các path /cart/, /checkout/, /my-account/.

Trong sự kiện fetch, kiểm tra URL và gọi event.respondWith(fetch(event.request)) trực tiếp cho các path nhạy cảm.

Đóng tab, SW có tiếp tục chạy không?

SW có thể chạy nền ngắn (~30 giây sau khi đóng tab trên di động). Push notification và background sync hoạt động khi đóng tab.

SW không phải tiến trình thường trú — trình duyệt tắt SW khi không cần để tiết kiệm pin.

Không nên thiết kế tính năng quan trọng dựa vào việc SW chạy mãi sau khi đóng tab.

Unregister Service Worker khi gặp sự cố khẩn cấp như thế nào?

Thêm một endpoint hoặc trang admin để unregister SW: navigator.serviceWorker.getRegistrations().then(regs => regs.forEach(r => r.unregister())). Hoặc trong DevTools → Application → Service Workers → click “Unregister”.

Cách dự phòng: deploy sw.js trống (chỉ có self.addEventListener(‘install’, …)) — SW mới sẽ không cache gì, phiên bản cũ bị thay thế.

Cần kiểm tra toàn bộ chuỗi cache từ Service Worker đến CDN edge? Web22 tư vấn audit tối ưu Core Web Vitals để đảm bảo mọi lớp cache hoạt động đúng.