Preload, Prefetch, Preconnect (ok)

https://boreddev.tech/bai-viet/preload-prefetch-preconnect-la-gi/

Preload, Prefetch, Preconnect là gì? Sao chúng có thể cải tiến hiệu năng web performance 1 cách đáng kể?

03/12/2018 BÀI HỌC

Vào thời điểm hiện tại, các trình duyệt browser hiện đại như Chrome, Safari, hay cả như Edge đã tích hợp sẵn các công nghệ giúp cải thiện hiệu năng web performance lên 1 cách đáng kể, giúp nâng cao trải nghiệm người dùng trên website của bạn ngay ở phía client side.

Khi nhắc đến việc cải tiến hiệu năng web performance, bạn thường nghĩ ngay tới các kỹ thuật caching phức tạp, sẽ phải thực hiện tối ưu ở phía server side, phải chỉnh sửa nhiều đoạn source code ở nhiều lớp layer, hay nhiều module khác nhau, để lồng ghép xử lý caching rối rắm vào đó. Đôi khi giải pháp tối ưu thật sự lại rất đơn giản, khi bạn biết về nó thì hóa ra lại không có gì to tát hay phức tạp cả, đặc biệt là các tối ưu hóa ở phía client side: bạn chỉ cần render thêm 1 vài thẻ tags hay thẻ metadata ở lớp view layer là đủ để browser hiểu và tự động tối ưu hóa hiệu năng cho web của bạn.

preload, prefetch, preconnect thực chất là các chỉ thị thông báo cho browser các chỉ dẫn xử lý, biểu hiện 1 thẻ <link/> có rel=”preload” (hoặc prefetch, preconnect) mà ta sẽ render thêm ở view layer hoặc thông qua HTTP headers, mục đích của chúng dùng để thông báo cho browser biết cách tối ưu việc tìm nạp các tài nguyên resources (images, js, css, font, …) từ server, dùng giảm thời gian xử lý network khứ hồi round trips, tận dụng thời gian người dùng đang đọc thông tin trên trang page để tìm nạp trước các nguồn tài nguyên resources của website.

Preload

Preload(tải trước theo trình tự ưu tiên) là chỉ thị cho bạn nhiều quyền kiểm soát hơn về trình tự ưu tiên tìm nạp tài nguyên resources cụ thể trong trình duyệt browser, đối với điều hướng hiện tại. Chỉ dẫn preload được định nghĩa trong 1 thẻ <link rel=”preload”>. Thông thường chỉ dẫn này dùng để nạp trước các tài nguyên có độ ưu tiên quan trọng như images, CSS, JS và font files, muốn được nạp sẵn trước khi browser thực hiện rendering. Do đó đảm bảo các nguồn tài nguyên resources luôn được nạp sẵn, và hầu như không block quá trình render của trang page, do đó sẽ cải thiện hiệu năng tải trang page.

Lưu ý preload khác biệt hoàn toàn với prefetch (tìm nạp tải trước), vì nó tập trung vào điều hướng hiện tại của người dùng, dùng để nạp trước các tài nguyên resources được thiết lập có độ ưu tiên cao, còn prefetch tập trung vào tìm nạp trước tài nguyên resources cho điều hướng tiếp theo mà người dùng có khả năng truy cập tới(các nguồn tài nguyên này có độ ưu tiên thấp hơn). Điểm đặc biệt cần chú ý tại đây là preload không block sự kiện onload event.

Lợi ích của preload

Các lợi ích của chỉ thị preload như sau:

  • Cho phép trình duyệt browser thiết lập độ ưu tiên nạp tài nguyên resource.

  • Cho phép trình duyệt browser khả năng xác định được loại tài nguyên resource type do đó nó có thể cho biết liệu cùng một tài nguyên có thể được tái sử dụng trong tương lai hay không.

  • Trình duyệt browser có thể xác định xem yêu cầu request có tuân thủ chính sách bảo mật nội dung content security policy hay không bằng cách tham chiếu những gì được xác định trong thuộc tính as.

  • Trình duyệt browser có thể gửi kèm theo các accept headers thích hợp dựa vào loại tài nguyên resource type (ví dụ như image/webp)

Cách sử dụng preload

Dưới đây là ví dụ về cách nạp trước preloading 1 image.

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

Tiếp là ví dụ về nạp trước preloading fonts. Chú ý: nếu bạn nạp trước các links với tài nguyên resources ở domain khác thì bạn cần thêm vào thuộc tính crossorigin.

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

Tiếp là ví dụ về preloading 1 stylesheet bằng cách sử dụng thẻ hay được tạo động bởi JS.

<!-- 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>

Bạn có thể sử dụng thuộc tính as để chỉ thị cho trình duyệt browser loại type của content cần ưu tiên nạp trước :

  • Thiết lập trình tự ưu tiên nạp resource chính xác hơn.

  • Có gắng tái sử dụng lại cùng 1 resource đối với các requests ở tương lai nếu có thể.

  • Cho phép áp dụng chính sách bảo mật nội dung content security policyđối với resource.

  • Thiết lập đúng Accept request headers khi thực hiện yêu cầu nạp resource.

Có rất nhiều loại content types có thể được preloaded, cũng như có nhiều loại các giá trị của thuộc tính as như sau:

  • audio: Audio file.

  • document : 1 HTML document được nhúng bên trong <frame> hay <iframe>.

  • embed : 1 resource được nhúng bên trong <embed>.

  • fetch : loại resource có thể được nạp bởi fetch hay XHR request giống như ArrayBuffer hay JSON file.

  • font : Font file.

  • image : Image file.

  • object : 1 resource được nhúng bên trong <embed>.

  • script : JavaScript file.

  • style : Stylesheet.

  • track : WebVTT file.

  • worker : 1 JavaScript web worker hay shared worker.

  • video : Video file.

Khả năng hỗ trợ chỉ thị preload của các trình duyệt browser

Preload được hỗ trợ từ phiên bản Chrome 50 bắt đầu từ tháng 4 năm 2016(https://www.chromestatus.com/feature/5757468554559488) và cũng được hỗ trợ từ Opera 37+(http://caniuse.com/#search=preload). Và nó vẫn chưa được xác nhận sẽ được hỗ trợ trong Mozilla FirefoxMicrosoft Edge.Mức độ hỗ trợ preload của các trình duyệt browser.

Để tìm hiểu thêm và rõ ràng hơn về chỉ thị preload, bạn có thể đọc tại đây: https://www.keycdn.com/support/preload-directive

Prefetch

1. Link Prefetching

link prefetching cho phép trình duyệt browser tìm nạp trước tài nguyên resources, và lưu trữ chúng trong cache. Trình duyệt browser sẽ tìm nạp các links nằm trong HTML hoặc trong HTTP header như sau:

  • 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 nhiều trang web có độ tương tác cao, nhưng sẽ không phải luôn mang lại hiệu quả với mọi trang web. Đối với 1 vài trang web, rất khó để xác định được người dùng có thể truy cập tới trang page nào tiếp theo. Đối với 1 vài trang web khác, dữ liệu có thể sẽ trở nên chẳng thú vị gì nếu được nạp sẵn trước đó. Bạn cũng nên cẩn thận để không tìm nạp trước các files quá sớm hoặc bạn có thể làm chậm trang mà người dùng đã xem. — Google Developers”

2. DNS Prefetching

Cơ chếDNS prefetching cho phép browser thực hiện tìm nạp ngầm DNS ngay trên page trong khi người dùng đang duyệt trang. Điều này làm tối thiểu hóa độ trễ tìm nạp DNS, DNS luôn có sẵn khi người dùng ấn vào 1 link.

“Yêu cầu DNS requests sử dụng lượng băng thông cực kỳ nhỏ, nhưng độ trễ khi tìm nạp DNS lại tương đối cao, đặc biệt nhất là trên kết nối mobile networks. Bằng cách tìm nạp trước các kết quả DNS, độ trễ có thể giảm đáng kể vào một số trường hợp nhất định, chẳng hạn như khi người dùng nhấp vào liên kết link. Trong một sốtrường hợp, độ trễ có thể giảm tới một giây. — Mozilla Developer Network

Ví dụ về cách sử dụng DNS prefetching:

<!-- 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="//opensource.keycdn.com"> <link rel="dns-prefetch" href="//cdn.domain.com">

Bạn cũng có thể sử dụng module có sẵn như Pagespeed filter insert_dns_prefetch để tự động tạo ra các thẻ <link rel=”dns-prefetch”> trong header cho mọi domains.

3. Prerendering

Prerendering(hiện thị trước) cũng khá tương đồng với prefetching(tìm nạp trước) là sẽ nạp trước toàn bộ tập hợp các resources trong trang page mà người dùng có thể truy cập tới tiếp theo. Điểm khác biệt là prerendering thực chất sẽ nạp ngầm trước toàn bộ trang page, bao gồm các tài nguyên có trong 1 document. Xét ví dụ sau:

<link rel="prerender" href="https://www.keycdn.com">

“Cơ chế hiện thị trước prerender có thể được điều khiển bởi ứng dụng của bạn để xác định xem chuyển hướng tới trang HTML nào tiếp theo được thực hiện: Trình duyệt sẽ nạp và xử lý nguồn tài nguyên được định trước để nạp giống như 1 phản hồi HTML response. Để nạp về các loại nội dung khác với request headers thích hợp hay nếu tài nguyên không phải HTML, thì ứng dụng có thể sử dụng cơ chế prefetch — W3C

Có 1 vài nhược điểm khi sử dụng cơ chế này, ví dụ như các chỉ trích liên quan tới quyền riêng tư.

  • Thống kê truy cập web có thể bị thổi phồng so với thực tế.

  • Người dùng có thể gặp nhiều rủi ro về bảo mật hơn khi phải thục hiện tải về nhiều pages hơn, hay tải các resource đến từ các sites không mong muốn truy cập tới.

  • Người dùng có thể vi pháp chính sách sử dụng của chính network hay tổ chức của họ nếu tìm nạp trước các nội dung không được cấp phép.

Để hiểu hơn bạn đoc tại đây: prefetching.

Preconnect

Preconnect(khởi tạo kết nối trước) cho phép trình duyệt browser thiết lập các kết nối connections sớm trước cả khi 1 HTTP request thực sự được gửi tới server. Các kêt nối loại này bao gồm: DNS lookups, TLS negotiations, TCP handshakes. Kỹ thuật này giảm thiểu độ trễ khứ hồi roundtrip và tiết kiệm thời gian cho người dùng.

“Preconnect là 1 công cụ quan trọng trong bộ công cụ tối ưu của bạn …Nó có thể giảm thiểu chi phí khứ hồi roundtrips của request — trong 1 vài trường hợp, nó có thể giảm độ trễ của request xuống hàng trăm hay thậm chí hàng nghìn milliseconds — Ilya Grigorik

1 preconnect có thể được thêm vào 1 cách trực tiếp trong 1 thuộc tính của thẻ link trong HTML. Nó cũng có thể được thiết lập thông qua HTTP header hoặc có thể được tạo động bởi JS. Dưới là ví dụ bật preconnect cho 1 CDN URL.

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

Tại trường hợp không sử dụng preconnect, browser sau khi nạp toàn bộ HTML rồi mới biết nó cần thêm tài nguyên CSS resource nằm trong fonts.googleapis.com. Sau khi tải xong tài nguyên CSS này, browser lại mới biết trang page cần 2 fonts nữa, và nó bắt đầu khởi tạo để nạp 2 fonts này từ fonts.gstatic.com – trước hết, browser vẫn cần thực hiện lại các bước DNS, TCP, và TLS handshakes ngay cả khi kết nối socket đã có sẵn cho các requests đa kênh trên kết nối HTTP/2.

<link href='https://fonts.gstatic.com' rel='preconnect' crossorigin>
<link href='https://fonts.googleapis.com/css?family=Roboto+Slab:700|Open+Sans' rel='stylesheet'>

Với trường hợp, khi ta thêm vào chỉ thị preconnect để chỉ dẫn cho browser, trang page sẽ cần nạp tài nguyên resources từ fonts.gstatic.com. Như kết quả ở trên, browser đã thiết lập kết nối socket song song với yêu cầu CSS request, và hoàng thành yêu cầu nạp tài nguyên trước hạn, cho phép font requests được gửi đi gần như lập tức.

Để hiểu hơn bạn đoc tại đây: preconnect.

Last updated