Yêu bộ nhớ đệm của bạn ❤️

Người dùng tải trang web của bạn lần thứ hai sẽ sử dụng bộ nhớ đệm HTTP, vì vậy, hãy đảm bảo bộ nhớ đệm đó hoạt động tốt.

Bài đăng này là phần bổ sung cho video Yêu bộ nhớ đệm, một phần của Nội dung mở rộng tại Hội nghị nhà phát triển Chrome 2020. Hãy nhớ xem video này:

Khi người dùng tải trang web của bạn lần thứ hai, trình duyệt của họ sẽ sử dụng các tài nguyên bên trong bộ nhớ đệm HTTP để giúp tải nhanh hơn. Tuy nhiên, các tiêu chuẩn lưu vào bộ nhớ đệm trên web có từ năm 1999 và được xác định khá rộng rãi. Việc xác định xem một tệp (chẳng hạn như CSS hoặc hình ảnh) có thể được tìm nạp lại từ mạng hay tải từ bộ nhớ đệm của bạn là một chút khoa học không chính xác.

Trong bài đăng này, tôi sẽ trình bày một cách hợp lý và hiện đại để lưu vào bộ nhớ đệm – một cách thực sự không lưu vào bộ nhớ đệm. Tuy nhiên, đó chỉ là tuỳ chọn mặc định và tất nhiên nó chi tiết hơn thay vì chỉ "tắt". Hãy đọc tiếp!

Bàn thắng

Khi một trang web được tải lần thứ 2, bạn có hai mục tiêu:

  1. Đảm bảo rằng người dùng của bạn nhận được phiên bản mới nhất hiện có – nếu bạn đã thay đổi nội dung nào đó, nội dung đó sẽ được phản ánh nhanh chóng
  2. Thực hiện bước 1 trong khi tìm nạp càng ít từ mạng càng tốt

Theo nghĩa rộng nhất, bạn chỉ muốn gửi thay đổi nhỏ nhất cho khách hàng khi họ tải lại trang web của bạn. Việc sắp xếp cấu trúc trang web để đảm bảo việc phân phối mọi thay đổi một cách hiệu quả nhất cũng là một thách thức (xem thêm về vấn đề này ở bên dưới và trong video).

Mặc dù vậy, bạn cũng có một số nút khác khi cân nhắc việc lưu vào bộ nhớ đệm. Có lẽ bạn đã quyết định cho phép bộ nhớ đệm HTTP của trình duyệt lưu giữ trang web của bạn trong một thời gian dài để không cần phải có yêu cầu mạng nào phân phát trang này. Hoặc bạn đã tạo một trình chạy dịch vụ sẽ phân phát một trang web hoàn toàn khi không có mạng trước khi kiểm tra xem trang web đó có được cập nhật hay không. Đây là một lựa chọn cực kỳ hợp lệ – và được dùng cho nhiều trải nghiệm web giống như ứng dụng có chế độ ngoại tuyến – nhưng web không nhất thiết phải ở trạng thái chỉ có bộ nhớ đệm hay thậm chí là hoàn toàn chỉ có mạng.

Thông tin khái quát

Là nhà phát triển web, chúng ta đều quen với việc có "bộ nhớ đệm cũ". Nhưng chúng tôi biết, gần như theo bản năng, các công cụ có sẵn để giải quyết việc này: "làm mới hoàn toàn" hoặc mở cửa sổ ẩn danh hoặc sử dụng một số công cụ cho nhà phát triển trên trình duyệt để xóa dữ liệu của trang web.

Những người dùng thường xuyên trên mạng không có được sự sang trọng như vậy. Vì vậy, mặc dù chúng tôi có một số mục tiêu cốt lõi là đảm bảo người dùng có trải nghiệm tuyệt vời trong lần tải thứ hai, nhưng điều quan trọng là phải đảm bảo họ không bị gián đoạn hoặc bị tắc nghẽn. (Hãy xem video nếu bạn muốn nghe tôi nói về việc chúng tôi suýt làm hỏng trang web web.dev/live!)

Để hiểu rõ hơn, một lý do phổ biến gây ra "bộ nhớ đệm cũ" thực sự là chế độ mặc định lưu vào bộ nhớ đệm từ thời kỳ 1999. Phương thức này dựa vào tiêu đề Last-Modified:

Sơ đồ cho thấy thời lượng lưu các thành phần khác nhau vào bộ nhớ đệm của trình duyệt của người dùng
Các thành phần được tạo tại các thời điểm khác nhau (màu xám) sẽ được lưu vào bộ nhớ đệm trong các thời điểm khác nhau, vì vậy, lần tải thứ hai có thể kết hợp các thành phần mới và đã lưu vào bộ nhớ đệm

Mỗi tệp bạn tải sẽ được giữ lại thêm 10% thời gian hoạt động hiện tại, như trình duyệt của bạn thấy. Ví dụ: nếu index.html được tạo cách đây một tháng, thì trình duyệt sẽ lưu tệp này vào bộ nhớ đệm trong khoảng ba ngày nữa.

Đây là một ý tưởng tốt vào thời điểm đó, nhưng do bản chất tích hợp chặt chẽ của các trang web hiện nay, hành vi mặc định này có nghĩa là có thể người dùng sẽ có các tệp được thiết kế cho nhiều bản phát hành trang web (ví dụ: JS từ bản phát hành thứ Ba và CSS từ bản phát hành thứ Sáu), tất cả là do các tệp đó không được cập nhật chính xác cùng một lúc.

Đường dẫn được chiếu sáng tốt

Chế độ mặc định hiện đại để lưu vào bộ nhớ đệm là không lưu vào bộ nhớ đệm và sử dụng CDN để đưa nội dung của bạn đến gần người dùng hơn. Mỗi khi người dùng tải trang web của bạn, họ sẽ truy cập vào mạng để xem trang web đó có được cập nhật hay không. Yêu cầu này sẽ có độ trễ thấp vì sẽ do CDN cung cấp theo khu vực địa lý gần từng người dùng cuối.

Bạn có thể định cấu hình máy chủ lưu trữ web để phản hồi các yêu cầu web bằng tiêu đề này:

Cache-Control: max-age=0,must-revalidate,public

Về cơ bản, điều này có nghĩa là tệp không hợp lệ trong bất kỳ thời điểm nào và bạn phải xác thực tệp đó từ mạng trước khi có thể sử dụng lại (nếu không, tệp đó chỉ là "đề xuất").

Quá trình xác thực này tương đối rẻ về số byte được chuyển – nếu một tệp hình ảnh lớn không thay đổi, trình duyệt của bạn sẽ nhận được một phản hồi 304 nhỏ – nhưng sẽ mất độ trễ vì người dùng vẫn phải truy cập vào mạng để tìm hiểu. Đây cũng là nhược điểm chính của phương pháp này. Phương thức này có thể hoạt động rất tốt đối với những người có kết nối nhanh ở các nước phát triển và nơi CDN mà bạn chọn có phạm vi phủ sóng rộng, nhưng không dành cho những người có thể đang sử dụng kết nối di động chậm hơn hoặc sử dụng cơ sở hạ tầng kém.

Dù sao, đây là một phương pháp hiện đại là mặc định trên một CDN phổ biến, Netlify, nhưng có thể được định cấu hình trên hầu hết mọi CDN. Đối với tính năng Lưu trữ Firebase, bạn có thể đưa tiêu đề này vào phần lưu trữ của tệp firebase.json:

"headers": [
  // Be sure to put this last, to not override other headers
  {
    "source": "**",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=0,must-revalidate,public"
    }
  }
]

Vì vậy, mặc dù tôi vẫn đề xuất đây là giá trị mặc định hợp lý, nhưng đó chỉ là giá trị mặc định! Hãy đọc tiếp để tìm hiểu cách thực hiện và nâng cấp các chế độ mặc định.

URL có vân tay số

Bằng cách đưa hàm băm của nội dung tệp vào tên của các thành phần, hình ảnh, v.v. được phân phát trên trang web của bạn, bạn có thể đảm bảo rằng các tệp này sẽ luôn có nội dung duy nhất. Ví dụ: các tệp có tên sitecode.af12de.js. Khi máy chủ phản hồi các yêu cầu về các tệp này, bạn có thể hướng dẫn trình duyệt của người dùng cuối lưu các tệp đó vào bộ nhớ đệm trong thời gian dài một cách an toàn bằng cách định cấu hình các tệp đó bằng tiêu đề sau:

Cache-Control: max-age=31536000,immutable

Giá trị này là một năm, tính bằng giây. Và theo thông số kỹ thuật, giá trị này tương đương với "vĩnh viễn".

Điều quan trọng là bạn không nên tạo các hàm băm này theo cách thủ công – quá nhiều công việc thủ công! Bạn có thể sử dụng các công cụ như Webpack, Rollup, v.v. để giúp bạn giải quyết vấn đề này. Hãy nhớ đọc thêm về các vấn đề này trong Báo cáo công cụ.

Hãy nhớ rằng không chỉ JavaScript mới có thể hưởng lợi từ URL có vân tay số; các thành phần như biểu tượng, CSS và các tệp dữ liệu bất biến khác cũng có thể được đặt tên theo cách này. (Và nhớ xem video ở trên để tìm hiểu thêm một chút về tính năng phân tách mã. Tính năng này giúp bạn gửi ít mã hơn mỗi khi trang web thay đổi.)

Bất kể trang web của bạn lưu vào bộ nhớ đệm theo cách nào, những loại tệp có vân tay số này đều vô cùng có giá trị đối với mọi trang web mà bạn có thể xây dựng. Hầu hết các trang web sẽ không thay đổi trong mỗi bản phát hành.

Tất nhiên, chúng ta không thể đổi tên các trang "dễ dùng", dành cho người dùng theo cách này: đổi tên tệp index.html thành index.abcd12.html – điều này là không khả thi, bạn không thể yêu cầu người dùng truy cập vào một URL mới mỗi khi họ tải trang web của bạn! Không thể đổi tên và lưu vào bộ nhớ đệm các URL "thân thiện" này theo cách này. Điều này sẽ dẫn tôi đến một cơ sở.

Giải pháp trung gian

Rõ ràng là có thể tìm được một giải pháp trung gian khi nói đến việc lưu vào bộ nhớ đệm. Tôi đã trình bày hai tuỳ chọn cực đoan; bộ nhớ đệm không bao giờ hoặc bộ nhớ đệm vĩnh viễn. Và sẽ có một số tệp mà bạn có thể muốn lưu vào bộ nhớ đệm trong một thời gian, chẳng hạn như các URL "dễ nhớ" mà tôi đề cập ở trên.

Nếu bạn muốn lưu các URL "dễ đọc" này và HTML của các URL đó vào bộ nhớ đệm, bạn nên cân nhắc xem các URL đó có những phần phụ thuộc nào, cách lưu các URL đó vào bộ nhớ đệm và việc lưu các URL đó vào bộ nhớ đệm trong một khoảng thời gian có thể ảnh hưởng đến bạn như thế nào. Hãy xem một trang HTML có chứa hình ảnh như sau:

<img src="/images/foo.jpeg" loading="lazy" />

Nếu bạn cập nhật hoặc thay đổi trang web bằng cách xoá hoặc thay đổi hình ảnh tải lười này, thì những người dùng xem phiên bản HTML đã lưu vào bộ nhớ đệm có thể thấy hình ảnh không chính xác hoặc bị thiếu – vì họ vẫn lưu /images/foo.jpeg ban đầu vào bộ nhớ đệm khi truy cập lại trang web của bạn.

Nếu bạn cẩn thận, điều này có thể không ảnh hưởng đến bạn. Nhưng nói chung, điều quan trọng là bạn phải nhớ rằng trang web của bạn (khi người dùng cuối lưu vào bộ nhớ đệm) không chỉ tồn tại trên máy chủ của bạn. Thay vào đó, tệp này có thể tồn tại ở dạng các phần trong bộ nhớ đệm của trình duyệt của người dùng cuối.

Nhìn chung, hầu hết các hướng dẫn về việc lưu vào bộ nhớ đệm sẽ nói về loại chế độ cài đặt này – bạn có muốn lưu vào bộ nhớ đệm trong một giờ, vài giờ, v.v. không? Để thiết lập loại bộ nhớ đệm này, hãy sử dụng tiêu đề như sau (lưu vào bộ nhớ đệm trong 3600 giây hoặc 1 giờ):

Cache-Control: max-age=3600,immutable,public

Một điểm cuối cùng. Nếu bạn đang tạo nội dung kịp thời mà người dùng thường chỉ truy cập một lần (chẳng hạn như bài báo tin tức), thì theo tôi, bạn không bao giờ nên lưu các nội dung này vào bộ nhớ đệm và nên sử dụng chế độ mặc định hợp lý ở trên. Tôi cho rằng chúng ta thường đánh giá cao hơn giá trị của việc lưu vào bộ nhớ đệm so với mong muốn của người dùng luôn xem được nội dung mới nhất và hay nhất, chẳng hạn như nội dung cập nhật quan trọng về một bản tin hoặc sự kiện hiện tại.

Tuỳ chọn không phải HTML

Ngoài HTML, một số tuỳ chọn khác cho các tệp nằm ở giữa bao gồm:

  • Nhìn chung, hãy tìm những thành phần không ảnh hưởng đến người khác

    • Ví dụ: tránh dùng CSS vì điều này làm thay đổi cách HTML được hiển thị
  • Hình ảnh lớn được dùng trong các bài viết kịp thời

    • Người dùng có thể sẽ không truy cập vào một bài viết nhiều hơn một vài lần, vì vậy, đừng lưu ảnh hoặc hình ảnh chính vào bộ nhớ đệm mãi mãi và lãng phí bộ nhớ
  • Một tài sản thể hiện một nội dung có giá trị vòng đời

    • Dữ liệu JSON về thời tiết có thể chỉ được phát hành mỗi giờ, vì vậy, bạn có thể lưu kết quả trước đó vào bộ nhớ đệm trong một giờ – kết quả này sẽ không thay đổi trong cửa sổ của bạn
    • Các bản dựng của dự án nguồn mở có thể bị giới hạn tốc độ, vì vậy, hãy lưu hình ảnh trạng thái bản dựng vào bộ nhớ đệm cho đến khi trạng thái có thể thay đổi

Tóm tắt

Khi người dùng tải trang web của bạn lần thứ hai, bạn đã có một sự tin tưởng – họ muốn quay lại và xem thêm những gì bạn cung cấp. Tại thời điểm này, bạn không chỉ cần giảm thời gian tải mà còn có một loạt các tuỳ chọn để đảm bảo rằng trình duyệt của bạn chỉ thực hiện những việc cần thiết để mang lại trải nghiệm nhanh chóng và mới nhất.

Lưu vào bộ nhớ đệm không phải là một khái niệm mới trên web, nhưng có lẽ bạn cần có một chế độ mặc định hợp lý. Hãy cân nhắc sử dụng một chế độ mặc định và chọn sử dụng các chiến lược lưu vào bộ nhớ đệm hiệu quả hơn khi cần. Cảm ơn bạn đã đọc!

Xem thêm

Để biết hướng dẫn chung về bộ nhớ đệm HTTP, hãy xem bài viết Tránh các yêu cầu mạng không cần thiết bằng Bộ nhớ đệm HTTP.