Trang tĩnh vẫn hoạt động trong khi được xuất bản lại
Trước đây, khi xuất bản lại một trang tĩnh trên Mythex, hệ thống xóa các file đang chạy trước rồi mới tải bản build mới lên, nên trong suốt thời gian tải, một số người truy cập nhận trang 404 hoặc một trang HTML mà các script của nó bị thiếu. Một lần tải lên thất bại còn tệ hơn: trang có thể trống hoàn toàn hoặc nửa cũ nửa mới. Giờ bản build mới được ghi đè lên bản cũ, các trang được ghi sau cùng, và các file thừa bị xóa vài phút sau đó. Một sửa đổi thứ hai khiến việc xuất bản lại hiện ra trong vài giây thay vì một phút — hoặc, với các file như logo, tối đa một ngày.
Trang tĩnh được phục vụ như thế nào
Trang tĩnh là trang chỉ gồm các file: trang HTML, JavaScript, CSS, hình ảnh. Khi bạn xuất bản một trang như vậy trên Mythex, chúng tôi build nó, tải kết quả lên kho lưu trữ đối tượng trong một thư mục dành cho trang của bạn, và phục vụ qua một mạng biên — các máy chủ đặt gần người truy cập, lấy file từ kho lưu trữ và giữ bản sao trong một khoảng thời gian. (Nếu bạn mới làm quen, hướng dẫn của chúng tôi về CDN là gì giải thích ý tưởng này.)
Có hai điều không ổn: thứ tự mà một lần xuất bản lại thay đổi các file, và thời gian giữ các bản sao cũ.
Vấn đề 1: tải lên làm trống trang trước
Một lần xuất bản lại xóa mọi thứ trong thư mục của trang, rồi mới tải bản build mới lên. Trong suốt thời gian tải — 12 giây cho một trang 250 file trong thử nghiệm cục bộ của chúng tôi — một người truy cập có yêu cầu chưa được lưu đệm tại biên sẽ nhận lỗi 404, hoặc một trang HTML mà các script của nó trả về 404.
Một lần tải lên thất bại còn tệ hơn. Thư mục đã trống, và trên một trong hai đường tải lên, index.html mới có thể được ghi trước file bị lỗi. Một lần xuất bản được báo là thất bại vẫn có thể để lại một trang nửa mới đang hoạt động.
Cách sửa: ghi đè, trang sau cùng, dọn dẹp sau
- Đừng xóa trước. Bản build mới được tải lên đè lên bản cũ.
- Tài nguyên trước, trang sau. Một trang nêu tên các script và style mà nó cần, nên các trang được tải lên cuối cùng. Cho đến khi các trang mới lên, người truy cập nhận trang cũ, mà trang cũ nêu tên các tài nguyên cũ, và chúng vẫn còn. Khi các trang mới lên, các tài nguyên mới mà chúng nêu tên đã có sẵn.
- Xóa phần thừa sau. Trước khi tải lên, chúng tôi liệt kê những gì trang đang gồm. Ba phút sau một lần tải lên thành công, bất kỳ thứ gì trong danh sách mà bản build mới không ghi đè sẽ bị xóa. Ba phút dài hơn 60 giây mà một trang có thể được lưu đệm tại biên và trong trình duyệt, nên một người truy cập vẫn giữ trang cũ có thể tìm thấy các tài nguyên mà nó nêu tên.
- Nếu nghi ngờ, không xóa gì. Nếu bước liệt kê trước khi tải lên thất bại, sẽ không có gì bị cắt tỉa. File thừa vô hại, và lần xuất bản tiếp theo sẽ dọn sạch chúng. Xóa mà không biết có gì ở đó là cách một trang rơi vào trạng thái trống.
Một lần tải lên thất bại giờ để lại trang cũ đúng như trước.
Chúng tôi đã kiểm thử điều này từ đầu đến cuối trên máy cục bộ, dùng đúng script tải lên, đúng route tải lên và việc phục vụ từ kho lưu trữ, với người truy cập đến trong trạng thái cache biên lạnh. Với code cũ, 55 trong số 91 lượt truy cập bị hỏng trong lúc xuất bản lại và 61 trong số 92 trong lúc một lần thất bại. Với code mới, 0 lượt bị hỏng trên khoảng 3.500 lượt truy cập, bao gồm cả hai đường tải lên, một lần tải lên thất bại và lần xuất bản sau đó — và đúng những file thừa được dọn đi.
Vấn đề 2: xuất bản lại mất quá lâu mới hiện
Ngay cả khi tải lên thành công, thay đổi vẫn hiện chậm. Biên giữ bản sao của một trang trong 60 giây và của mọi file khác trong một ngày, và cũng nói với trình duyệt làm điều tương tự. Các file có tên cố định — logo.png, một font, bất cứ thứ gì từ thư mục public/ — có thể hiển thị phiên bản cũ đến một ngày sau một lần xuất bản lại.
Cách sửa: bản sao file theo bản build
Khi biên hỏi API của chúng tôi xem một trang nằm ở đâu, câu trả lời giờ bao gồm một dấu hiệu bản build thay đổi mỗi khi một lần xuất bản hoàn tất. Biên lưu bản sao dưới dấu hiệu đó. Một lần xuất bản vì vậy trở thành một tập khóa cache hoàn toàn mới ngay khi tra cứu 30 giây của biên hết hạn. Các bản sao cũ không bao giờ được tìm thấy nữa, nên biên có thể giữ bản sao trong một ngày mà không bao giờ phục vụ một bản đã quá hạn kể từ lần xuất bản đã thay thế nó.
Trình duyệt nhận hai quy tắc khác nhau:
- Đầu ra build có hash — các file như
assets/index-CzLcxDO8.js, có tên thay đổi khi nội dung thay đổi — được cache một năm và đánh dấu immutable. Dưới tên đó, nó không bao giờ bị cũ. - Mọi thứ khác — trang và các file tên cố định như logo — được đánh dấu
no-cache, nghĩa là “kiểm tra trước khi dùng”. Nếu không có gì thay đổi, câu trả lời là một304 Not Modifiednhỏ không có nội dung, vì giờ chúng tôi tôn trọng kiểm traIf-None-Matchcủa trình duyệt.
Phân biệt hai loại này cần cẩn thận: một file được sao từ public/assets/ giữ nguyên tên gốc, và cache assets/logo.png trong một năm sẽ ghim logo cũ trong một năm. Vì vậy một file chỉ được coi là có hash khi nó nằm trong thư mục đầu ra build và tên của nó có một đoạn trông giống hash, không phải một từ thông thường.
Tại máy cục bộ, trang và logo mới hiện 6 giây sau khi lần xuất bản lên sóng. Trước đó là 60 giây cho trang và một ngày cho logo.
Hai sửa đổi nhỏ hơn trong quá trình này
- Trang trống từ yêu cầu HEAD. Yêu cầu
HEADchỉ hỏi header của một trang mà không lấy nội dung. Chúng tôi từng cache các phản hồi rỗng đó, nên người truy cập kế tiếp của trang nhận một trang trống. Phản hồiHEADgiờ không còn được cache. - Một trang thật cho “không có gì ở đây”. Một địa chỉ không có ứng dụng từng nhận một dòng chữ thuần “This published app is offline or the link was not found” kèm mã lỗi 502. Giờ nó nhận một trang đúng nghĩa, “Không có ứng dụng nào ở đây”, với trạng thái 404 và một đường quay lại Mythex cho chủ sở hữu. Tên miền tùy chỉnh chưa biết cũng nhận cùng trang đó.
Chúng tôi rút ra gì
- Thứ tự là một phần của tính đúng đắn. Cùng những file được tải lên theo thứ tự khác nhau là khác biệt giữa một trang hỏng và một trang hoạt động.
- Xóa muộn, và chỉ xóa những gì bạn biết. Cắt tỉa bằng một danh sách lấy trước lần tải lên là an toàn; làm trống một thư mục và hy vọng lần tải lên hoàn tất thì không.
- Cache theo phiên bản, không theo thời gian. Thời gian hết hạn là một phỏng đoán về lúc nội dung thay đổi. Một khóa thay đổi theo bản build là một sự thật.
Liên quan: ứng dụng đã xuất bản của bạn giờ vẫn hoạt động trong khi được xuất bản lại. Thêm về xuất bản trong tài liệu.