Tìm hiểu preload, prefetch và preconnect, cũng như cách tích hợp chúng vào WordPress

Hôm nay chúng ta sẽ cùng tìm hiểu các biện pháp hiện đang được dùng để gợi ý và đưa ra chỉ thị cho tài nguyên (resource hints and directives)- đây có thể là cách hiệu quả khác để cải thiện tốc độ website hoặc ứng dụng web.

Bạn có thể đã nghe nói đến preload, prefetch preconnect rồi, nhưng chúng ta muốn hiểu sâu hơn về sự khác biệt giữa chúng cũng như việc bạn có thể tận dụng lợi ích từ chúng như thế nào.

Một trong các lợi ích đó là chúng cho phép người phát triển website tối ưu hóa phân phối các tài nguyên (optimize delivery of resource), giảm các vòng lặp khứ hồi (round trips), và tìm nạp các nguồn tài nguyên để phân phối nội dung nhanh hơn khi người dùng duyệt web.

Preload

Preload là một tiêu chuẩn web mới giúp bạn có được nhiều thẩm quyền hơn với một tài nguyên cụ thể được tìm nạp (fetched) trong phiên duyệt web hiện tại (current navigation). Đây là bản cập nhật của phiên bản tìm nạp trước nguồn phụ- cái không còn được dùng đến nữa vào tháng Giêng năm 2016. Chỉ thị này có thể được định nghĩa bằng thẻ <link>, ví dụ như <link rel=’preload’>. Nhìn chung, tốt nhất là bạn preload các tài nguyên quan trọng nhất, chẳng hạn như ảnh, CSS, JavaScript, và các file dùng làm font. Điều này không nên nhầm lẫn với preloading của trình duyệt trong đó chỉ các tài nguyên trong HTML là được tải trước. Chỉ thị preload thực sự khắc phục giới hạn này và cho phép các nguồn tài nguyên được khởi tạo thông qua CSS và JavaScript được preload/tải trước và xác định khi nào từng tài nguyên nên được áp dụng.

Preload khác với prefetch ở khía cạnh là preload tập trung vào việc tìm nạp tài nguyên cho phiên làm việc hiện tại (current navigation). Prefetch tập trung vào việc tìm nạp tài nguyên cho phiên duyệt web kế tiếp (next navigation). Một điều quan trọng nữa cần lưu ý là preload không chặn/block sự kiện onload.

Lợi ích của preload

Một số lợi ích của chỉ thị preload bao gồm:

  • Cho phép trình duyệt thiết lập mức độ ưu tiên tài nguyên (resource priority) vì thế cho phép nhà lập trình web tối ưu hóa phân phối các tài nguyên cụ thể.
  • Cung cấp cho trình duyệt khả năng xác định kiểu loại của tài nguyên, vì thế nó có thể cho biết cùng một kiểu tài nguyên có được tái sử dụng trong tương lai hay không.
  • Trình duyệt có thể xác định xem yêu cầu có tuân thủ chính sách bảo mật về nội dung hay không bằng cách tham chiếu đến định nghĩa được xác định trong thuộc tính as.
  • Trình duyệt có thể gửi các tiêu để accept phù hợp dựa trên kiểu tài nguyên. (chẳng hạn như image/webp)

Ví dụ

Dưới đây là một ví dụ rất cơ bản về tải trước/preloading hình ảnh.

<link rel="preload" href="image.png">

Còn bên dưới đây là ví dụ về preloading fonts. Lưu ý: Nếu bạn preloading các liên kết với việc cho phép CORS bật trên tài nguyên thì bạn cũng phải bao gồm thuộc tính crossorigin.

<link rel="preload" href="https://kiencang.net/fonts/font.woff" as="font" crossorigin>

Dưới đây là ví dụ về preloading một file CSS thông qua sử dụng mã đánh dấu/markup hoặc JavaScript.

<!-- Via markup -->
<link rel="preload" href="/css/mystyles.css" as="style">
<!-- Via JavaScript -->
<script>
    var res = document.createElement("link");
    res.rel = "preload";
    res.as = "style";
    res.href = "css/mystyles.css";
    document.head.appendChild(res);
</script>

Trình duyệt hỗ trợ preload

Preload được thêm vào từ phiên bản Chrome 50 trong tháng Sáu năm 2016, nó cũng được hỗ trợ trong Opera 37 và các phiên bản cao hơn. Hiện nó vẫn chưa được Mozilla FireFox tích hợp, trong khi đó thì Microsoft Edge, Safari và iOS Safari đều đã thêm chức năng này.

Về trình duyệt hỗ trợ, bạn có thể tham khảo các trình duyệt đang hỗ trợ tính năng nào đó theo thời gian thực (các bảng trong bài có thể lỗi thời khi bạn đọc bài viết này) bằng cách click vào đường link bên dưới mỗi ảnh. Nó sử dụng trang web caniuse.com để kiểm tra.

Có 4 màu sắc bạn cần phải để ý:

định nghĩa màu sắc
Định nghĩa màu sắc
  • Supported: Được hỗ trợ
  • Not supported: Không được hỗ trợ
  • Partial support: Hỗ trợ một phần
  • Support unknow: Không có thông tin, hỗ trợ không được biết rõ

Bạn nên hướng sự quan tâm đến các trình duyệt lớn nhất gồm:

  • Chrome
  • Safari
  • Firefox
  • Edge
  • Opera
  • IE

Và tất nhiên là cả các phiên bản trên di động của chúng trên các nền tảng nó hay được dùng như iOS Safari, Chrome for Android, Firefox for Android, Opera mini.

Ở góc bên phải trên cùng, bạn sẽ thấy tỷ lệ người dùng được hỗ trợ, ví dụ đây là tỷ lệ người dùng được hỗ trợ tính năng preload:

Số lượng người dùng được hỗ trợ tính năng nào đó

Trong đó có 84,26% là được hỗ trợ đầy đủ; 2,08% là được hỗ trợ một phần. Tổng cộng có 86,34% là được hỗ trợ.

Tuy nhiên suy cho cùng đây là con số trung bình, để biết chính xác hơn với website cụ thể của bạn, bạn cần phải biết thống kê riêng về tỷ lệ trình duyệt dùng để truy cập website của bạn. Chẳng hạn đây là một website tôi (người dịch) quản lý, với 4 trình duyệt đầu tiên chiếm đến xấp xỉ 96% (thực tế chỉ còn 3 trình duyệt, vì cái số bốn và cái số một gần như tương tự).

Prefetch

Prefetch là các gợi ý tài nguyên có mức độ ưu tiên thấp cho phép trình duyệt tìm nạp các nguồn tài nguyên trong chế độ nền (background) vào thời gian rảnh rỗi (idle time), mà có thể người dùng sẽ sử dụng tiếp sau này. Tài nguyên được tìm nạp sẽ được lưu trong bộ nhớ cache của trình duyệt. Khi một trang hoàn tất quá trình tải, nó bắt đầu tải các tài nguyên bổ sung và nếu người dùng click vào liên kết đã được tìm nạp (prefetched link), nó sẽ tải nội dung gần như ngay lập tức (instanly). Có ba kiểu tìm nạp, đó là link, DNS và prerendering, chúng ta sẽ đi vào chi tiết từng cái bên dưới.

mô hình của prefetch
Mô hình của prefetch

1. Link prefetching

Như được đề cập phía trên, các liên kết được tìm nạp trước cho phép trình duyệt tìm nạp các tài nguyên và lưu trữ chúng trong cache, với giả định là người dùng sẽ yêu cầu chúng sau khi xem trang trong phiên hiện tại. Trình duyệt tìm kiếm các liên kết prefetch trong HTML hoặc HTTP header link, chẳng hạn như:

  • HTML: <link rel="prefetch" href="/uploads/images/pic.png">
  • HTTP Header: Link: </uploads/images/pic.png>; rel=prefetch

Kỹ thuật này có tiềm năng tăng tốc trang web có nhiều tính tương tác, nhưng không phải lúc nào nó cũng hiệu quả. Với một số trang, vấn đề là rất khó để đoán được người dùng sẽ làm gì ở thao tác kế tiếp. Với một số trang khác, dữ liệu có thể bị mất mát nếu quá trình tìm nạp diễn ra quá sớm. Điều cũng rất quan trọng là cẩn thận đừng tìm nạp các file quá sớm, vì khi ấy bạn có thể làm chậm chính trang mà người dùng đang đang xem!

– Google Developers

Link prefetch được hỗ trợ bởi hầu hết các trình duyệt hiện đại ngoại trừ Safari, iOS Safari, và Opera Mini. Chrome và FireFox cũng sẽ hiển thị các tài nguyên đã được tìm nạp trong panel network nếu bạn thử kiểm tra.

các trình duyệt hỗ trợ prefetch
Các trình duyệt hỗ trợ link prefetch

Bạn có thể dễ dàng tích hợp tính năng link prefetching vào WordPress bằng plugin như Flying Pages. Tuy nhiên cần lưu ý là link prefetching tiêu tốn đáng kể tài nguyên máy chủ, nên trên các host yếu hoặc/và các mạng quá yếu có thể sẽ không phù hợp do gây quá tải.

Link Prefetch hoạt động tốt nhất khi nó kết hợp với mô hình dự đoán truy cập kế tiếp được trích xuất từ công cụ phân tích website như Google Analytics.

2. DNS prefetching

DNS prefetching cho phép trình duyệt thực hiện tìm kiếm DNS trên trang dưới chế độ nền trong khi người dùng duyệt web. Điều này giúp tối thiểu hóa độ trễ vì tìm kiếm DNS đã có sẵn khi người dùng click vào liên kết. DNS prefetching có thể được thêm vào một URL cụ thể bằng cách thêm tag rel=’dns-prefetch’ vào thuộc tính liên kết (link). Chúng tôi đề xuất sử dụng thuộc tính này cho các thứ như Google fonts, Google analytics và CDN của bạn.

Các yêu cầu DNS rất nhỏ nếu xét trên khía cạnh băng thông/bandwidth, nhưng độ trễ/latency có thể khá cao, đặc biệt trên mạng di động. Bằng cách tìm nạp trước các kết quả DNS, độ trễ có thể giảm xuống đáng kể vào thời điểm nhất định, chẳng hạn khi người dùng click vào liên kết. Trong một số trường hợp, độ trễ có thể giảm đến một giây.

– Mozilla Developer Network

Nó cũng hữu ích cho các tài nguyên ẩn bên dưới chuyển hướng. Xem ví dụ dưới đây. Bạn cần để ý là trong thuộc tính href, bạn không cần thêm http hay https, vì dns-fetch chỉ dùng để tìm nạp trước DNS, không liên quan đến chuyện hình thành sớm kết nối bảo mật như preconnect.

<!-- Prefetch DNS for external assets -->
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//www.google-analytics.com">
<link rel="dns-prefetch" href="//cdn.domain.com">

Điều khá thú vị là Google Chrome làm điều tương tự khi bạn gõ vào thanh địa chỉ với việc giải quyết trước DNS và preconnect TCP.

DNS prefetch cũng được hỗ trợ bởi hầu hết các trình duyệt hiện đại ngoại trừ Opera Mini.

3. Prerendering

Prerendering cũng rất giống với prefetching ở chỗ nó thu thập các nguồn tài nguyên mà người dùng có thể điều hướng đến từ trang họ đang xem. Điểm khác biệt là prerendering thực sự render toàn bộ trang trong chế độ nền, tất cả các thành phần của tài liệu. Dưới đây là một ví dụ.

<link rel="prerender" href="https://kiencang.net">

Gợi ý prerender có thể được sử dụng bởi ứng dụng để cho biết điều hướng HTML có khả năng tiếp theo (next likely HTML navigation target): tác nhân người dùng sẽ tìm nạp và xử lý tài nguyên đã chỉ định dưới dạng phản hồi HTML. Để tìm nạp các loại nội dung khác với các tiêu đề yêu cầu phù hợp, hoặc nếu tiền xử lý HTML là điều không mong muốn, ứng dụng có thể sử dụng gợi ý prefetch.

W3C

Bạn cần cẩn thận hơn với prerendering vì các yêu cầu tài nguyên nặng nhọc có thể gây lãng phí băng thông, đặc biệt là trên thiết bị di động. Cũng cần lưu ý là bạn không thể kiểm tra thuộc tính này với Chrome DevTools, thay vào đó, bạn có thể kiểm tra một trang có được prerender hay chưa bằng cách vào chrome://net-internals/#prerender. Bạn cũng có thể tự kiểm tra bằng cách vào đường link http://prerender-test.appspot.com/

Prerender được hỗ trợ bởi một số trình duyệt, ngoại trừ Firefox, Safari, iOS Safari, Opera Mini và trình duyệt mặc định của Android.

Bên cạnh việc gia tăng sử dụng tài nguyên, có một số nhược điểm khác khi bạn sử dụng prefetching, chẳng hạn như những chi trích liên quan đến tính riêng tư.

  • Các con số thống kê có thể bị thổi phồng, mặc dù Google nói rằng họ đã chặn các thẻ thống kê trong chế độ prefetching.
  • Người dùng có thể gặp rủi ro bảo mật hơn khi tải xuống nhiều trang hơn, hoặc từ các trang không được yêu cầu.
  • Người dùng có thể vi phạm các thỏa thuận sử dụng đã được chấp nhận của mạng hoặc tổ chức của họ nếu prefetching tìm nạp trước các nội dung họ không có thẩm quyền.

Preconnect

Thuộc tính gợi ý tài nguyên cuối cùng mà tôi muốn bàn đến là preconnect. Preconnect cho phép trình duyệt thiết lập kết nối sớm trước khi yêu cầu HTTP thực sự được gửi đến server. Điều này bao gồm tìm kiếm DNS, đàm phán TLS, TCP handshakes. Nhờ thế loại bỏ được độ trễ của vòng lặp và tiết kiệm thời gian cho người dùng.

Preconnect là công cụ quan trọng trong các tiện ích tối ưu của bạn…nó có thể loại bỏ nhiều chi phí vòng lặp khỏi đường dẫn yêu cầu của bạn – trong một số trường hợp độ trễ của yêu cầu có thể được giảm hàng trăm, thậm chí là hàng ngàn mili giây (1 giây = 1000 mili giây).

Ilya Grigorik
Tốc độ tải trang khi có và không có preconnect
Tốc độ tải trang khi có và không có preconnect. Thuộc tính này giúp tiết kiệm thời gian nhờ việc DNS / TCP / TLS được thực hiện song song cùng lúc trên nhiều tài nguyên của bên thứ ba thay vì phải thực hiện lần lượt

Preconnect có thể được thêm trực tiếp vào thẻ <link> như là một thuộc tính trong HTML. Nó cũng có thể được phân phối thông qua header Link HTTP hoặc có thể được JavaScript gọi dựa trên hành động của người dùng. Dưới đây là một ví dụ về việc cho phép preconnect cho URL của CDN.

<link href="https://cdn.domain.com" rel="preconnect" crossorigin>

Bên dưới là một ví dụ về việc sử dụng preconnect cho Google Fonts. Bằng cách thêm gợi ý preconnect cho fonts.gstatic.com, nó bắt đầu yêu cầu song song với yêu cầu CSS, cho phép yêu cầu font được gửi đi ngay lập tức. Trong kịch bản cụ thể này, preconnect loại bỏ ba RTTs khỏi tuyến hiển thị quan trọngloại bỏ hơn 0,5 giây độ trễ. Bạn có thể xem chi tiết bài viết của Iya Grigorik về cách loại bỏ RTTs bằng preconnect.

Preconnect giúp giảm thời gian tải trang
Preconnect giúp giảm thời gian tải trang, nguồn ảnh của Ilya Grigorik

Sử dụng preconnect một cách có hiệu quả và có tính toán sẽ không chỉ giúp tối ưu hóa website của bạn mà còn giúp bạn sử dụng dưới mức tài nguyên. Preconnect được hỗ trợ bởi một số trình duyệt hiện đại ngoại trừ IE và Opera Mini.

Tổng kết

Hy vọng là giờ bạn đã hiểu hơn một chút về preload, prefetch và preconnect là gì và làm thế nào bạn có thể sử dụng chúng để tăng tốc phân phối nội dung và các thành phần quan trọng bằng cách sử dụng các thuộc tính này một cách có chiến lược. Sẽ rất thú vị khi thấy chỉ thị preload nhận được nhiều hỗ trợ hơn sau vài tháng tới và các nhà lập trình web bắt đầu chấp nhận nó nhiều hơn.

Bạn nghĩ gì về những gợi ý tài nguyên này? Bạn đã thử với tất cả chúng chưa? Nếu có, tôi muốn nghe bạn kể về chúng trong phần bình luận.

(Dịch từ bài viết Resource Hints – What is Preload, Prefetch, and Preconnect? của tác giả Brian Jackson, KeyCDN)

Hướng dẫn tích hợp vào WordPress

Phần này người dịch sẽ hướng dẫn các bạn tích hợp các thuộc tính preconnect, prefetch và preload vào WordPress- hệ quản trị web phổ biến nhất hiện nay.

Công cụ về cơ bản, bạn chỉ cần 3 thứ:

Bước 1: Phân tích tài nguyên

Truy cập công cụ pingdom phía trên, lấy một bài viết phổ biến của website (bài viết có lưu lượng truy cập cao và có cùng định dạng với nhiều bài viết khác- thường là bài post trên trang), rồi bắt đầu kiểm tra.

Dùng pingdom để kiểm tra

Khi tiến hành xong, bạn kéo xuống phía dưới để biết dung lượng tài nguyên được sử dụng (content size by domain) cũng như số lượng kết nối của nó (request by domain), cả bên trong, lẫn bên ngoài website:

Phần này cho bạn biết về tổng thể website đang lấy tài nguyên ở đâu với dung lượng bao nhiêu, và xếp theo thứ tự từ lớn đến bé, từ nhiều đến ít, nhưng nó không cho biết chi tiết các file cụ thể. Để rõ hơn bạn kéo xuống bên dưới một chút:

phân tích cụ thể từng tài nguyên

Bạn có thể nhấn mũi tên > để xem tiếp các file khác, hoặc nhập luôn toàn bộ số lượng requests vào ô Entries per page để biết tổng thể (ở đây là 39 requests, tôi biết được con số này nhờ nhìn vào góc dưới cùng bên tay trái).

Kết hợp 2 thông tin này bạn sẽ biết phải làm gì:

  • preconnect để thực hiện kết nối sớm với host ngoài host gốc của bạn (host gốc của bạn thì không cần preconnect). Ở trên ta có thể thấy đó là những miền như: https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js, https://www.googletagservices.com, https://googleads.g.doubleclick.net, https://secure.gravatar.com / các host bên ngoài với số lượng kết nối nhiều nên cân nhắc preconnect
  • preload thường được dùng để load trước các file quan trọng như font sử dụng cho website, trong trường hợp của tôi vì website không sử dụng @font-face mà chỉ sử dụng font mặc định trên máy tính nên tôi tạm thời không cần quan tâm đến nó / preload có thể được áp dụng cho cả file quan trọng bên trong lẫn bên ngoài host gốc như JS, CSS, ảnh
  • dns-prefetch thường được dùng để tìm kiếm trước DNS của các dịch vụ như Google Analytics, Facebook hoặc CDN của bạn
  • preconnect tốt hơn dns-prefetch vì nó còn thực hiện kết nối bảo mật nữa, nhưng preconnect chỉ nên thực hiện cho các tài nguyên bên ngoài quan trọng, còn những cái không quá quan trọng chỉ nên dùng dns-prefetch. Thêm nữa dns-prefetch là một dự phòng tốt cho các trình duyệt không hỗ trợ preconnect.

Bước 2: Sử dụng plugin Autoptimize để thêm preconnect và preload

Bạn vào Autoptimize > Extra > Preconnect to 3rd party hoặc Preload specific requests để tiến hành thêm:

thêm preconnect và preload vào plugin Autoptimize

Có hai thứ bạn cần lưu ý ở đây:

  • Với preconnect: các tên miền cần cách nhau bởi dấu phẩy (,) và phải đủ https hoặc http
  • Với preload: bạn cần cẩn trọng, vì cái này không chỉ thực hiện kết nối sớm mà còn ưu tiên tải file này về trước càng sớm càng tốt, nên nếu bạn áp dụng cho những file không quan trọng mà lại có dung lượng lớn, bạn sẽ làm chậm website (trái ngược hoàn toàn với mục tiêu ban đầu!). Thế nào là file quan trọng thì đôi khi còn tùy quan điểm của website. Chẳng hạn một đoạn mã JS từ Google Adsense nếu được ưu tiên tải trước sẽ giúp quảng cáo hiển thị nhanh hơn, website nào đặt trọng tâm về khía cạnh kinh tế sẽ ưu tiên tải file này (không có ý đánh giá), còn website nào cho rằng nội dung vẫn cần ưu tiên hơn sẽ không preload nó…Tương tự các file preload cũng cần cách nhau bởi dấu phẩy và có đầy đủ đường dẫn

Bước 3: Sử dụng Insert Headers and Footers để thêm dns-prefetch

Vì Autoptimze không hỗ trợ dns-prefetch nên bạn cần sử dụng plugin tôi vừa đề cập ở trên. Ví dụ:

header dns-prefetch

Bạn lưu ý là đoạn mã dns-prefetch ở trên phải được đặt trong phần Header và trước các đoạn mã mà bạn muốn kết nối trước. Ngoài ra không cần thêm http hay https trước tên miền cần tìm nạp DNS (vì nó không có nhiệm vụ thiết lập kết nối bảo mật, ở đây nó chỉ thực hiện tìm kiếm DNS mà thôi).

Vì dns-prefetch chỉ thực hiện tìm kiếm DNS nên nó sẽ không hiệu quả bằng preconnect, vì preconnect còn thực hiện thao tác kết nối https nếu tài nguyên bên thứ ba có sử dụng kết nối bảo mật (và nói chung tài nguyên bên thứ ba thường sử dụng kết nối bảo mật).

Vậy thì tại sao người ta vẫn sử dụng dns-prefetch?

Lý do có thể là vì ngày xưa dns-prefetch được nhiều trình duyệt hỗ trợ hơn preconnect (tuy nhiên hiện nay mức độ hỗ trợ preconnect đã rất cao, tất cả các trình duyệt phổ biến nhất cùng nhiều phiên bản trên di động của chúng đã hỗ trợ preconnect rồi, nên tính tương thích của nó là điều bạn không cần lo lắng).

Ngoài lý do trên thì tôi vẫn không rõ vì sao đôi khi người ta vẫn thích dùng dns-prefetch hơn.

Sau khi hoàn thành và nhấn lưu mọi thứ, bạn tiến hành kiểm tra mã nguồn của website (lưu ý xóa cache hoặc/và tải lại trang cần kiểm tra vài lần), nếu thấy các thuộc tính ‘pre’ được áp dụng lên tài nguyên như bạn mong muốn thì bạn đã thành công rồi.

Sắp tới tôi sẽ tìm hiểu thêm có plugin nào chuyên sâu làm các nhiệm vụ pre này hay không. Bởi vì Autoptimize nó vẫn có điểm yếu là không tùy biến được với từng bài viết cụ thể, chẳng hạn với các bài viết có video YouTube tôi sẽ muốn preconnect tới YouTube và một số nguồn phụ khác liên quan đến nó, trong khi các bài viết khác không sử dụng video thì hoàn toàn không cần. Hiện Autoptimize áp dụng lên tất cả các bài viết, và gây lãng phí trên những trang không dùng.

P/S 1: tôi vừa phát hiện plugin Pre* Party Resource Hints chuyên dùng để thực hiện các kết nối trước này. Ưu điểm là nó có cả prefetch, preconnect, preload lẫn dns-prefetch với đầy đủ các tùy chọn. Tuy nhiên thì nó hiện vẫn không có tính năng tùy chỉnh trên từng trang.

P/S 2: cuối cùng tôi cũng tìm được plugin có tên SOGO có khả năng tùy biến header, footer trên từng trang.

2 thoughts on “Tìm hiểu preload, prefetch và preconnect, cũng như cách tích hợp chúng vào WordPress”

  1. Chào bác. Em thấy trong Astra Pro có tính năng Custom Layout – nó cho phép thêm wp_head… theo từng post, page, chuyên mục… Khi đó em ko cần đến plugin SOGO như bác nói ở trên thì có được ko nhỉ?

    Reply
    • Úi trời, tôi cũng dùng Astra mà không biết tính năng này đấy…Bạn nói đúng rồi, miễn là bạn can thiệp được header cấp độ post thì không cần plugin kiểu như SOGO nữa.

      Reply

Leave a Comment