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ả địnhpath/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.