Trình chạy dịch vụ mới hơn, theo mặc định

Tóm tắt

Kể từ Chrome 68, các yêu cầu HTTP kiểm tra bản cập nhật tập lệnh trình chạy dịch vụ sẽ không bộ nhớ đệm HTTP sẽ thực hiện lâu hơn theo mặc định. Giải pháp này giải quyết một điểm yếu thường gặp của nhà phát triển, trong đó việc vô tình đặt tiêu đề Cache-Control vào tập lệnh trình chạy dịch vụ của bạn có thể dẫn đến các bản cập nhật bị trì hoãn.

Nếu bạn đã chọn không sử dụng chức năng lưu tệp HTTP vào bộ nhớ đệm cho tập lệnh /service-worker.js bằng cách phân phát tập lệnh đó với Cache-Control: max-age=0, thì bạn sẽ không thấy bất kỳ thay đổi nào do giá trị mặc định mới hành vi.

Ngoài ra, kể từ Chrome 78, phép so sánh byte với byte sẽ là đã áp dụng cho các tập lệnh được tải trong một trình chạy dịch vụ qua importScripts(). Bất kỳ thay đổi nào được thực hiện đối với tập lệnh đã nhập sẽ kích hoạt lệnh quy trình cập nhật trình chạy dịch vụ, giống như một thay đổi đối với trình chạy dịch vụ cấp cao nhất.

Thông tin khái quát

Mỗi khi bạn điều hướng đến một trang mới thuộc phạm vi của trình chạy dịch vụ, hãy gọi registration.update() một cách rõ ràng từ JavaScript hoặc khi một trình chạy dịch vụ bị "đánh thức" thông qua sự kiện push hoặc sync, trình duyệt song song, sẽ yêu cầu tài nguyên JavaScript ban đầu được chuyển vào navigator.serviceWorker.register() để tìm nội dung cập nhật cho tập lệnh trình chạy dịch vụ.

Theo mục đích của bài viết này, giả sử URL của bài viết là /service-worker.js và chứa một lệnh gọi đến importScripts(), mã này sẽ tải mã bổ sung chạy bên trong service worker:

// Inside our /service-worker.js file:
importScripts('path/to/import.js');

// Other top-level code goes here.

Điều gì sẽ thay đổi?

Trước Chrome 68, yêu cầu cập nhật /service-worker.js sẽ được thực hiện qua bộ nhớ đệm HTTP (như hầu hết các lần tìm nạp đều như vậy). Tức là nếu tập lệnh ban đầu được gửi bằng Cache-Control: max-age=600, thì các nội dung cập nhật trong vòng 600 giây (10 phút) sẽ không được đưa vào mạng. người dùng có thể không nhận được phiên bản mới nhất của trình chạy dịch vụ. Tuy nhiên, nếu max-age là lớn hơn 86400 (24 giờ), thì mã này sẽ được xử lý như thể đó là 86400, để tránh người dùng bị mắc kẹt bằng một phiên bản cụ thể vĩnh viễn.

Kể từ phiên bản 68, bộ nhớ đệm HTTP sẽ bị bỏ qua khi yêu cầu cập nhật cho trình chạy dịch vụ tập lệnh, vì vậy các ứng dụng web hiện tại có thể thấy tần suất yêu cầu các ứng dụng tập lệnh trình chạy dịch vụ. Các yêu cầu cho importScripts sẽ vẫn chuyển qua bộ nhớ đệm HTTP. Nhưng đây là chỉ tùy chọn mặc định—một tùy chọn đăng ký mới, updateViaCache có sẵn để cung cấp quyền kiểm soát hành vi này.

updateViaCache

Giờ đây, nhà phát triển có thể truyền một tuỳ chọn mới khi gọi navigator.serviceWorker.register(): tham số updateViaCache. Hàm này nhận một trong ba giá trị: 'imports', 'all' hoặc 'none'.

Các giá trị này xác định xem có phải bộ nhớ đệm HTTP tiêu chuẩn của trình duyệt hay không và cách thức hoạt động sẽ có hiệu lực khi đưa ra yêu cầu HTTP để kiểm tra các tài nguyên đã cập nhật của trình chạy dịch vụ.

  • Khi bạn đặt thành 'imports', bộ nhớ đệm HTTP sẽ không bao giờ được tham khảo khi kiểm tra bản cập nhật cho /service-worker.js tập lệnh. Tuy nhiên, hệ thống sẽ tham khảo ý kiến khi tìm nạp bất kỳ tập lệnh nào đã nhập (trong ví dụ của chúng tôi là path/to/import.js). Đây là tuỳ chọn mặc định và khớp với hành vi bắt đầu trong Chrome 68.

  • Khi bạn đặt thành 'all', bộ nhớ đệm HTTP sẽ được tham khảo khi đưa ra yêu cầu cho cả tập lệnh /service-worker.js cấp cao nhất cũng như bất kỳ tập lệnh nào được nhập bên trong dịch vụ trình thực thi, chẳng hạn như path/to/import.js. Tùy chọn này tương ứng với hành vi trước đó trong Chrome, trước Chrome 68.

  • Khi bạn đặt thành 'none', bộ nhớ đệm HTTP sẽ không được tham khảo khi đưa ra yêu cầu đối với /service-worker.js cấp cao nhất hoặc cho bất kỳ tập lệnh được nhập nào, chẳng hạn như tập lệnh giả định path/to/import.js.

Ví dụ: Mã sau đây sẽ đăng ký một trình chạy dịch vụ và đảm bảo rằng bộ nhớ đệm HTTP được chưa từng được tham khảo khi kiểm tra bản cập nhật cho tập lệnh /service-worker.js hoặc cho bất kỳ các tập lệnh được tham chiếu qua importScripts() bên trong /service-worker.js:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js', {
    updateViaCache: 'none',
    // Optionally, set 'scope' here, if needed.
  });
}

Kiểm tra bản cập nhật cho các tập lệnh đã nhập

Trước Chrome 78, mọi tập lệnh trình chạy dịch vụ đều tải qua importScripts() sẽ chỉ được truy xuất một lần (trước tiên sẽ kiểm tra bộ nhớ đệm HTTP hoặc thông qua mạng, tuỳ thuộc vào cấu hình updateViaCache). Sau tên đầu tiên đó truy xuất, nó sẽ được trình duyệt lưu trữ nội bộ và không bao giờ tìm nạp lại.

Cách duy nhất để buộc một trình chạy dịch vụ đã cài đặt nhận các thay đổi đối với tập lệnh đã nhập để thay đổi URL của tập lệnh, thường bằng cách thêm vào giá trị bán kính (ví dụ: importScripts('https://example.com/v1.1.0/index.js')) hoặc bằng cách bao gồm hàm băm của nội dung (ví dụ: importScripts('https://example.com/index.abcd1234.js')). Đáp tác dụng phụ của việc thay đổi URL đã nhập là trình chạy dịch vụ cấp cao nhất nội dung của tập lệnh thay đổi, do đó sẽ kích hoạt quy trình cập nhật trình chạy dịch vụ.

Kể từ Chrome 78, mỗi khi thực hiện kiểm tra bản cập nhật ở cấp cao nhất tệp trình chạy dịch vụ, các bước kiểm tra sẽ được thực hiện cùng lúc để xác định xem hoặc nội dung của bất kỳ tập lệnh được nhập nào đã thay đổi. Tuỳ thuộc vào Cache-Control tiêu đề đã được sử dụng, các bước kiểm tra tập lệnh đã nhập này có thể được thực hiện bằng bộ nhớ đệm HTTP nếu updateViaCache được đặt thành 'all' hoặc 'imports' (tức là giá trị mặc định) hoặc các lần kiểm tra có thể đi thẳng vào mạng nếu updateViaCache được đặt thành 'none'.

Nếu quá trình kiểm tra cập nhật cho tập lệnh đã nhập dẫn đến sự chênh lệch theo từng byte so với nội dung đã được trình chạy dịch vụ lưu trữ trước đó, thì điều này sẽ do đó kích hoạt quy trình cập nhật trình chạy dịch vụ đầy đủ, ngay cả khi dịch vụ cấp cao nhất tệp worker không thay đổi.

Hành vi của Chrome 78 khớp với hành vi mà Firefox implemented vài năm trước, trên Firefox 56. Safari đã triển khai hành vi này dưới dạng tốt.

Nhà phát triển cần làm gì?

Nếu bạn đã chọn không sử dụng chức năng lưu vào bộ nhớ đệm HTTP cho tập lệnh /service-worker.js một cách hiệu quả bằng cách phân phát tập lệnh đó với Cache-Control: max-age=0 (hoặc một giá trị tương tự), thì bạn sẽ không thấy bất kỳ thay đổi nào do hành vi mặc định mới.

Nếu bạn phân phát tập lệnh /service-worker.js có bật tính năng lưu vào bộ nhớ đệm HTTP, thì tức là bạn có chủ ý hoặc vì đây chỉ là mặc định cho môi trường lưu trữ của bạn, bạn có thể bắt đầu thấy các yêu cầu HTTP bổ sung cho /service-worker.js được thực hiện tăng lên máy chủ của bạn – đây là những yêu cầu được bộ nhớ đệm HTTP thực hiện. Nếu bạn muốn tiếp tục cho phép giá trị tiêu đề Cache-Control tác động đến độ mới của nội dung /service-worker.js, bạn cần bắt đầu đặt updateViaCache: 'all' rõ ràng khi đăng ký nhân viên dịch vụ của bạn.

Vì có thể vẫn còn lượng người dùng dài trên các phiên bản trình duyệt cũ, bạn vẫn nên tiếp tục đặt tiêu đề HTTP Cache-Control: max-age=0 trên các tập lệnh trình chạy dịch vụ, mặc dù các trình duyệt mới có thể bỏ qua các lỗi đó.

Nhà phát triển có thể sử dụng cơ hội này để quyết định xem họ có muốn chọn rõ ràng việc nhập các tập lệnh ra khỏi bộ nhớ đệm HTTP ngay bây giờ và thêm updateViaCache: 'none' vào trình chạy dịch vụ nếu thích hợp.

Phân phối tập lệnh đã nhập

Kể từ Chrome 78, nhà phát triển có thể nhận thấy nhiều yêu cầu HTTP hơn cho các tài nguyên được tải qua importScripts(), vì các tài nguyên này giờ đây sẽ được kiểm tra bản cập nhật.

Nếu bạn muốn tránh lưu lượng truy cập HTTP bổ sung này, hãy đặt các URL Tiêu đề Cache-Control khi phân phát các tập lệnh có chứa semver hoặc hàm băm trong URL của chúng và dựa vào hành vi updateViaCache mặc định của 'imports'.

Ngoài ra, nếu bạn muốn các tập lệnh đã nhập được kiểm tra xem có thường xuyên không các bản cập nhật, hãy đảm bảo bạn phân phát quảng cáo đó với Cache-Control: max-age=0, hoặc bạn sử dụng updateViaCache: 'none'.

Tài liệu đọc thêm

"Vòng đời của trình chạy dịch vụ" và "Các phương pháp hay nhất về việc lưu vào bộ nhớ đệm và max-age gotchas", của cả Jake Archibald, đều được đề xuất đọc cho tất cả các nhà phát triển muốn triển khai bất cứ thứ gì trên web.