Lớp học lập trình: Tải trước các thành phần quan trọng để cải thiện tốc độ tải

Trong lớp học lập trình này, hiệu suất của trang web sau đây sẽ được cải thiện bằng cách tải trước và tìm nạp trước một số tài nguyên:

Ảnh chụp màn hình ứng dụng

Đo

Trước tiên, hãy đo lường hiệu suất của trang web trước khi thêm bất kỳ hoạt động tối ưu hoá nào.

  • Để xem trước trang web, hãy nhấn vào View App (Xem ứng dụng), sau đó nhấn vào Fullscreen toàn màn hình (Toàn màn hình).

Chạy bài kiểm tra hiệu suất của Lighthouse (Lighthouse > Tuỳ chọn > Hiệu suất) trên phiên bản trực tiếp của Glitch (xem thêm Khám phá các cơ hội về hiệu suất với Lighthouse).

Lighthouse hiển thị hoạt động kiểm tra không thành công sau đây đối với một tài nguyên được tìm nạp muộn:

Lighthouse: Kiểm tra việc tải trước các yêu cầu chính
  • Nhấn tổ hợp phím "Control+Shift+J" (hoặc "Command+Option+J" trên máy Mac) để mở Công cụ cho nhà phát triển.
  • Nhấp vào thẻ Mạng.
Bảng điều khiển mạng có tài nguyên phát hiện muộn

Tệp main.css không được tìm nạp bằng phần tử Đường liên kết (<link>) nằm trong tài liệu HTML, mà được tìm nạp bằng tệp JavaScript riêng, fetch-css.js, sẽ đính kèm phần tử Đường liên kết vào DOM sau sự kiện window.onLoad. Điều này có nghĩa là tệp chỉ được tìm nạp sau khi trình duyệt hoàn tất quá trình phân tích cú pháp và thực thi tệp JS. Tương tự, phông chữ web (K2D.woff2) được chỉ định trong main.css chỉ được tìm nạp sau khi tệp CSS tải xuống xong.

Chuỗi yêu cầu quan trọng thể hiện thứ tự tài nguyên mà trình duyệt ưu tiên và tìm nạp. Trang web này hiện có dạng như sau:

├─┬ / (initial HTML file)
  └── fetch-css.js
    └── main.css
      └── K2D.woff2

Vì tệp CSS nằm ở cấp thứ ba của chuỗi yêu cầu, nên Lighthouse đã xác định tệp này là một tài nguyên được phát hiện muộn.

Tải trước các tài nguyên quan trọng

Tệp main.css là một thành phần quan trọng và cần thiết ngay khi trang được tải. Đối với các tệp quan trọng như tài nguyên này được tìm nạp sau đó trong ứng dụng, hãy sử dụng thẻ tải trước đường liên kết để thông báo cho trình duyệt tải xuống sớm hơn bằng cách thêm phần tử Liên kết vào phần đầu tài liệu.

Thêm thẻ tải trước cho ứng dụng này:

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
</head>

Thuộc tính as được dùng để xác định loại tài nguyên nào đang được tìm nạp và as="style" dùng để tải trước tệp biểu định kiểu.

Tải lại ứng dụng và xem bảng điều khiển Mạng trong Công cụ cho nhà phát triển.

Bảng điều khiển mạng có tài nguyên tải trước

Lưu ý cách trình duyệt tìm nạp tệp CSS trước khi JavaScript chịu trách nhiệm tìm nạp tệp này thậm chí đã hoàn tất quá trình phân tích cú pháp. Với tính năng tải trước, trình duyệt biết sẽ tìm nạp trước tài nguyên với giả định rằng đó là hoạt động quan trọng đối với trang web.

Nếu không được sử dụng đúng cách, tính năng tải trước có thể gây tổn hại đến hiệu suất bằng cách đưa ra những yêu cầu không cần thiết đối với những tài nguyên không dùng đến. Trong ứng dụng này, details.css là một tệp CSS khác nằm ở gốc của dự án nhưng được dùng cho một /details route riêng biệt. Để xem ví dụ về cách sử dụng không chính xác tính năng tải trước, hãy thêm gợi ý tải trước cho tài nguyên này.

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

Tải lại ứng dụng và xem bảng điều khiển Network (Mạng). Một yêu cầu được đưa ra để truy xuất details.css ngay cả khi trang web không sử dụng mã này.

Bảng điều khiển mạng có lượt tải trước không cần thiết

Chrome sẽ hiển thị cảnh báo trong bảng điều khiển Bảng điều khiển khi trang không sử dụng tài nguyên tải trước trong vòng vài giây sau khi tải.

Cảnh báo về việc tải trước trong bảng điều khiển

Hãy sử dụng cảnh báo này làm chỉ báo để xác định xem bạn có tài nguyên tải trước nào chưa được trang web của bạn sử dụng ngay lập tức hay không. Bây giờ, bạn có thể xoá đường liên kết tải trước không cần thiết cho trang này.

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

Để biết danh sách tất cả các loại tài nguyên có thể tìm nạp cùng với các giá trị chính xác nên dùng cho thuộc tính as, hãy tham khảo bài viết MMDN về Tải trước.

Tìm nạp trước tài nguyên trong tương lai

Tìm nạp trước là một gợi ý khác của trình duyệt mà bạn có thể sử dụng để đưa ra yêu cầu về một thành phần dùng cho một tuyến điều hướng khác nhưng ở mức độ ưu tiên thấp hơn các thành phần quan trọng khác cần thiết cho trang hiện tại.

Trên trang web này, việc nhấp vào hình ảnh sẽ đưa bạn đến một tuyến details/ riêng biệt.

Tuyến đường chi tiết

Một tệp CSS riêng, details.css, chứa tất cả các kiểu cần thiết cho trang đơn giản này. Thêm phần tử liên kết vào index.html để tìm nạp trước tài nguyên này.

<head>
  <!-- ... -->
  <link rel="prefetch" href="details.css">
</head>

Để hiểu cách điều này kích hoạt yêu cầu cho tệp, hãy mở bảng điều khiển Mạng trong Công cụ cho nhà phát triển và bỏ chọn tuỳ chọn Vô hiệu hoá bộ nhớ đệm.

Vô hiệu hoá bộ nhớ đệm trong Công cụ của Chrome cho nhà phát triển

Tải lại ứng dụng và để ý xem yêu cầu có mức độ ưu tiên rất thấp được thực hiện cho details.css sau khi tất cả các tệp khác đã được tìm nạp.

Bảng điều khiển mạng có tài nguyên được tìm nạp trước

Khi Công cụ cho nhà phát triển mở, hãy nhấp vào hình ảnh trên trang web để chuyển đến trang details. Vì một phần tử đường liên kết được dùng trong details.html để tìm nạp details.css, nên hệ thống sẽ đưa ra yêu cầu cho tài nguyên như dự kiến.

Yêu cầu mạng trang chi tiết

Hãy nhấp vào yêu cầu mạng details.css trong Công cụ cho nhà phát triển để xem thông tin chi tiết về yêu cầu đó. Bạn sẽ nhận thấy tệp được truy xuất từ bộ nhớ đệm trên ổ đĩa của trình duyệt.

Yêu cầu chi tiết đã được tìm nạp từ bộ nhớ đệm của ổ đĩa

Bằng cách tận dụng thời gian không hoạt động của trình duyệt, tính năng tìm nạp trước sẽ thực hiện một yêu cầu sớm về tài nguyên cần thiết cho một trang khác. Điều này giúp đẩy nhanh tốc độ cho các yêu cầu điều hướng trong tương lai bằng cách cho phép trình duyệt lưu tài sản vào bộ nhớ đệm sớm hơn và phân phát tài sản đó từ bộ nhớ đệm khi cần.

Tải trước và tìm nạp trước bằng gói web

Bài đăng Giảm tải trọng JavaScript bằng tính năng chia tách mã tìm hiểu cách sử dụng tính năng nhập động để chia gói thành nhiều phần. Điều này được minh hoạ bằng một ứng dụng đơn giản có thể tự động nhập mô-đun từ Lodash khi biểu mẫu được gửi.

Ứng dụng Magic Sorter minh hoạ quá trình phân tách mã

Bạn có thể truy cập Sự cố nhỏ cho ứng dụng này tại đây.

Khối mã sau đây (nằm trong src/index.js,) chịu trách nhiệm nhập động phương thức khi người dùng nhấp vào nút này.

form.addEventListener("submit", e => {
  e.preventDefault()
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

Việc tách một gói sẽ cải thiện thời gian tải trang bằng cách giảm kích thước ban đầu. Phiên bản 4.6.0 của gói web hỗ trợ tải trước hoặc tìm nạp trước các phần được nhập động. Lấy ứng dụng này làm ví dụ, phương thức lodash có thể được tìm nạp trước tại thời điểm trình duyệt không hoạt động; khi người dùng nhấn nút, sẽ không có độ trễ để tìm nạp tài nguyên.

Sử dụng tham số nhận xét webpackPrefetch cụ thể trong quá trình nhập động để tìm nạp trước một phân đoạn cụ thể. Đây là giao diện của ứng dụng cụ thể này.

form.addEventListener("submit", e => {
  e.preventDefault()
  import(/* webpackPrefetch: true */ 'lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

Sau khi ứng dụng được tải lại, webpack sẽ chèn thẻ tìm nạp trước cho tài nguyên vào phần đầu của tài liệu. Bạn có thể xem thông tin này trong bảng điều khiển Phần tử trong Công cụ cho nhà phát triển.

Bảng điều khiển phần tử có thẻ tìm nạp trước

Việc quan sát các yêu cầu trong bảng điều khiển Network (Mạng) cũng cho thấy phần này được tìm nạp với mức độ ưu tiên thấp sau khi tất cả tài nguyên khác đã được yêu cầu.

Bảng điều khiển mạng có yêu cầu được tìm nạp trước

Mặc dù tính năng tìm nạp trước có ý nghĩa hơn cho trường hợp sử dụng này, nhưng gói web cũng hỗ trợ việc tải trước các phân đoạn được nhập một cách linh động.

import(/* webpackPreload: true */ 'module')

Kết luận

Thông qua lớp học lập trình này, bạn chắc chắn sẽ hiểu rõ về cách việc tải trước hoặc tìm nạp trước một số thành phần có thể cải thiện trải nghiệm người dùng trên trang web của bạn. Xin lưu ý rằng bạn không nên sử dụng những kỹ thuật này cho mọi tài nguyên và việc sử dụng sai cách có thể gây hại cho hiệu suất. Bạn chỉ nhận thấy kết quả tốt nhất bằng cách tải trước hoặc tìm nạp trước một cách có chọn lọc.

Tóm tắt:

  • Sử dụng tính năng tải trước cho những tài nguyên được phát hiện trễ nhưng đóng vai trò quan trọng đối với trang hiện tại.
  • Sử dụng tính năng tìm nạp trước cho các tài nguyên cần thiết cho tuyến điều hướng hoặc hành động của người dùng trong tương lai.

Hiện tại, không phải trình duyệt nào cũng hỗ trợ cả tính năng tải trước và tìm nạp trước. Điều này có nghĩa là không phải tất cả người dùng ứng dụng của bạn đều có thể nhận thấy hiệu suất cải thiện.

Nếu bạn muốn biết thêm thông tin về các khía cạnh cụ thể liên quan đến tác động của việc tải trước và tìm nạp trước đến trang web của bạn, hãy tham khảo các bài viết sau: