Các tập lệnh của bên thứ ba ảnh hưởng đến hiệu suất. Do đó, bạn phải kiểm tra các tập lệnh này thường xuyên và sử dụng các kỹ thuật hiệu quả để tải tập lệnh. Lớp học lập trình này cho bạn biết cách tối ưu hoá việc tải các tài nguyên bên thứ ba. Quá trình này bao gồm các kỹ thuật sau:
Trì hoãn tải tập lệnh
Tải từng phần các tài nguyên không quan trọng
Kết nối trước với những nguồn gốc bắt buộc
Ứng dụng mẫu đi kèm có một trang web đơn giản với ba tính năng đến từ các nguồn của bên thứ ba:
Nhúng video
Thư viện trực quan hoá dữ liệu để kết xuất biểu đồ đường
Tiện ích chia sẻ trên mạng xã hội
Bạn sẽ bắt đầu bằng cách đo lường hiệu suất của ứng dụng, sau đó áp dụng từng kỹ thuật để cải thiện các khía cạnh khác nhau của hiệu suất ứng dụng.
Đo lường hiệu suất
Trước tiên, hãy mở ứng dụng mẫu ở chế độ xem toàn màn hình:
- Nhấp vào Phối lại để chỉnh sửa để có thể chỉnh sửa dự án.
- Để xem trước trang web, hãy nhấn vào Xem ứng dụng. Sau đó nhấn Toàn màn hình .
Chạy một Lighthouse kiểm tra hiệu suất trên trang để thiết lập hiệu suất cơ sở:
- 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ẻ Lighthouse.
- Nhấp vào Thiết bị di động.
- Chọn hộp đánh dấu Hiệu suất. (Bạn có thể xoá các hộp đánh dấu còn lại trong phần Kiểm tra.)
- Nhấp vào Mô phỏng mạng 3G nhanh, Giảm 4 lần CPU.
- Chọn hộp kiểm Clear Storage (Xoá bộ nhớ).
- Nhấp vào Chạy quy trình kiểm tra.
Khi chạy một bài kiểm tra trên máy của mình, kết quả chính xác có thể khác, nhưng bạn nên lưu ý rằng thời gian Hiển thị nội dung đầu tiên (FCP) là khá cao và Lighthouse đề xuất hai cơ hội để điều tra: Loại bỏ tài nguyên chặn hiển thị và Kết nối trước với nguồn gốc bắt buộc. (Ngay cả khi tất cả các chỉ số đều màu xanh lục, tối ưu hoá vẫn sẽ mang lại sự cải thiện.)
Trì hoãn JavaScript của bên thứ ba
Quy trình kiểm tra Loại bỏ tài nguyên chặn hiển thị đã xác định rằng bạn có thể tiết kiệm thời gian bằng cách trì hoãn tập lệnh đến từ d3js.org:
D3.js là thư viện JavaScript để tạo hình ảnh dữ liệu. Tệp script.js
trong ứng dụng mẫu sử dụng các hàm hiệu dụng D3 để tạo biểu đồ dạng đường SVG và nối biểu đồ đó vào trang. Thứ tự các thao tác ở đây rất quan trọng: script.js
phải chạy sau khi tài liệu được phân tích cú pháp và thư viện D3 được tải. Đó là lý do tại sao tài liệu này được đưa vào ngay trước thẻ đóng </body>
trong index.html
.
Tuy nhiên, tập lệnh D3 có trong <head>
của trang, lệnh này chặn quá trình phân tích cú pháp nội dung còn lại trong tài liệu:
Hai thuộc tính ma thuật có thể bỏ chặn trình phân tích cú pháp khi được thêm vào thẻ tập lệnh:
async
đảm bảo rằng các tập lệnh tải xuống ở chế độ nền và thực thi trong cơ hội đầu tiên sau khi tải xuống xong.defer
đảm bảo các tập lệnh tải xuống ở chế độ nền và thực thi sau khi quá trình phân tích cú pháp hoàn tất.
Vì biểu đồ này không thực sự quan trọng đối với trang tổng thể và rất có thể sẽ nằm dưới màn hình đầu tiên, hãy sử dụng defer
để đảm bảo không có tính năng chặn trình phân tích cú pháp nào.
Bước 1: Tải tập lệnh không đồng bộ bằng thuộc tính defer
Trên dòng 17 trong index.html
, hãy thêm thuộc tính defer
vào phần tử <script>
:
<script src="https://d3js.org/d3.v3.min.js" defer></script>
Bước 2: Đảm bảo thứ tự chính xác của các thao tác
Giờ đây, D3 đã bị trì hoãn, nên script.js
sẽ chạy trước khi D3 sẵn sàng, dẫn đến lỗi.
Các tập lệnh có thuộc tính defer
thực thi theo thứ tự được chỉ định. Để đảm bảo script.js
được thực thi sau khi D3 đã sẵn sàng, hãy thêm defer
vào thành phần này và di chuyển lên phần tử <head>
của tài liệu, ngay sau phần tử <script>
của D3. Giờ đây, thao tác này không còn chặn trình phân tích cú pháp nữa và quá trình tải xuống sẽ bắt đầu sớm hơn.
<script src="https://d3js.org/d3.v3.min.js" defer></script>
<script src="./script.js" defer></script>
Tải từng phần các tài nguyên của bên thứ ba
Tất cả các tài nguyên nằm dưới màn hình đầu tiên đều là lựa chọn phù hợp cho tính năng tải từng phần.
Ứng dụng mẫu có video YouTube được nhúng trong iframe. Để xem trang này thực hiện bao nhiêu yêu cầu và yêu cầu nào đến từ iframe YouTube được nhúng:
- Để xem trước trang web, hãy nhấn vào Xem ứng dụng. Sau đó nhấn Toàn màn hì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.
- Chọn hộp kiểm Tắt bộ nhớ đệm.
- Chọn Mạng 3G nhanh trong trình đơn thả xuống Điều tiết.
- Tải lại trang.
Bảng điều khiển Network (Mạng) cho thấy trang này đã thực hiện tổng cộng 28 yêu cầu và chuyển gần 1 MB tài nguyên nén.
Để xác định các yêu cầu mà YouTube iframe
đã đưa ra, hãy tìm mã video 6lfaiXM6waw
trong cột Người khởi tạo. Cách nhóm tất cả yêu cầu theo miền:
Trong bảng điều khiển Mạng, hãy nhấp chuột phải vào tiêu đề cột.
Trong trình đơn thả xuống, hãy chọn cột Miền.
Để sắp xếp các yêu cầu theo miền, hãy nhấp vào tiêu đề cột Miền.
Cách sắp xếp mới cho thấy có thêm yêu cầu đối với các miền mua qua Google. Tổng cộng, iframe YouTube thực hiện 14 yêu cầu đối với tập lệnh, biểu định kiểu, hình ảnh và phông chữ. Nhưng trừ khi người dùng thực sự cuộn xuống để phát video, họ không thực sự cần tất cả các nội dung đó.
Bằng cách chờ tải từng phần video cho đến khi người dùng cuộn xuống phần đó của trang, bạn sẽ giảm số lượng yêu cầu mà trang đưa ra ban đầu. Phương pháp này giúp lưu và tăng tốc độ tải ban đầu.
Một cách để triển khai tính năng tải từng phần là sử dụng Intersection Observer cho trình duyệt. API này sẽ thông báo cho bạn khi một phần tử truy cập hoặc thoát khỏi khung nhìn của trình duyệt.
Bước 1: Ban đầu ngăn video tải
Để tải từng phần iframe video, trước tiên, bạn phải ngăn iframe tải theo cách thông thường. Bạn có thể làm việc này bằng cách thay thế thuộc tính src
bằng thuộc tính data-src
để chỉ định URL của video:
<iframe width="560" height="315" data-src="https://www.youtube.com/embed/lS9D6w1GzGY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
data-src
là một thuộc tính dữ liệu, cho phép bạn lưu trữ thêm thông tin trong các phần tử HTML chuẩn. Bạn có thể đặt tên bất kỳ cho thuộc tính dữ liệu, miễn là thuộc tính đó bắt đầu bằng "data-".
iframe không có src
sẽ không tải được.
Bước 2: Dùng Intersection Observer để tải từng phần video
Để tải video khi người dùng cuộn đến video, bạn cần biết thời điểm việc đó diễn ra. Đây là nơi mà API Intersection Observer API bước vào. API Intersection Observer cho phép bạn đăng ký hàm callback được thực thi bất cứ khi nào một phần tử bạn muốn theo dõi vào hoặc ra khỏi khung nhìn.
Để bắt đầu, hãy tạo một tệp mới rồi đặt tên tệp đó là lazy-load.js
:
- Nhấp vào New File (Tệp mới) rồi đặt tên cho tệp đó.
- Nhấp vào Add This File (Thêm tệp này).
Thêm thẻ tập lệnh vào phần đầu tài liệu:
<script src="/lazy-load.js" defer></script>
Trong lazy-load.js
, hãy tạo một IntersectionObserver
mới rồi truyền vào đó một hàm callback để chạy:
// create a new Intersection Observer
let observer = new IntersectionObserver(callback);
Bây giờ, hãy cung cấp cho observer
một phần tử mục tiêu để xem (trong trường hợp này là iframe video) bằng cách truyền phần tử đó dưới dạng một đối số trong phương thức observe
:
// the element that you want to watch
const element = document.querySelector('iframe');
// register the element with the observe method
observer.observe(element);
callback
nhận được danh sách các đối tượng IntersectionObserverEntry
và chính đối tượng IntersectionObserver
. Mỗi mục chứa một phần tử target
và các thuộc tính mô tả kích thước, vị trí, thời gian phần tử xuất hiện trong khung nhìn và các thông tin khác. Một trong các thuộc tính của IntersectionObserverEntry
là isIntersecting
– một giá trị boolean bằng true
khi phần tử này đi vào khung nhìn.
Trong ví dụ này, target
là iframe
. isIntersecting
bằng true
khi target
đi vào khung nhìn. Để xem mã này trong thực tế, hãy thay thế callback
bằng hàm sau:
let observer = new IntersectionObserver(callback);
let observer = new IntersectionObserver(function(entries, observer) {
entries.forEach(entry => {
console.log(entry.target);
console.log(entry.isIntersecting);
});
});
- Để xem trước trang web, hãy nhấn vào Xem ứng dụng. Sau đó nhấn Toàn màn hì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ẻ Bảng điều khiển.
Hãy thử di chuyển lên và xuống. Bạn sẽ thấy giá trị của isIntersecting
thay đổi và phần tử mục tiêu được ghi vào bảng điều khiển.
Để tải video khi người dùng cuộn đến vị trí của video, hãy dùng isIntersecting
làm điều kiện để chạy hàm loadElement
. Hàm này nhận giá trị từ data-src
của phần tử iframe
và đặt làm thuộc tính src
của phần tử iframe
. Quá trình thay thế đó sẽ kích hoạt quá trình tải video. Sau đó, khi video đã được tải, hãy gọi phương thức unobserve
trên observer
để dừng xem phần tử mục tiêu:
let observer = new IntersectionObserver(function (entries, observer) {
entries.forEach(entry => {
console.log(entry.target);
console.log(entry.isIntersecting);
});
});
if (entry.isIntersecting) {
// do this when the element enters the viewport
loadElement(entry.target);
// stop watching
observer.unobserve(entry.target);
}
});
});
function loadElement(element) {
const src = element.getAttribute('data-src');
element.src = src;
}
Bước 3: Đánh giá lại hiệu suất
Để xem kích thước và số lượng tài nguyên đã thay đổi như thế nào, hãy mở bảng điều khiển Mạng Công cụ cho nhà phát triển rồi tải lại trang. Bảng điều khiển Mạng cho thấy trang này đã thực hiện 14 yêu cầu và chỉ có 260 KB. Đó là một bước cải thiện có ý nghĩa!
Bây giờ, hãy di chuyển xuống phía dưới của trang và để ý bảng điều khiển Network (Mạng). Khi truy cập vào video, bạn sẽ thấy trang kích hoạt thêm yêu cầu.
Kết nối trước với các nguồn gốc bắt buộc
Bạn đã trì hoãn các JavaScript không quan trọng và tải từng phần các yêu cầu YouTube. Vì vậy, bây giờ đã đến lúc tối ưu hoá nội dung còn lại của bên thứ ba.
Khi bạn thêm thuộc tính rel=preconnect
vào một đường liên kết, trình duyệt sẽ được yêu cầu thiết lập kết nối với một miền trước khi thực hiện yêu cầu cho tài nguyên đó. Bạn nên sử dụng thuộc tính này cho những nguồn gốc cung cấp tài nguyên mà bạn chắc chắn đang cần.
Quy trình kiểm tra Lighthouse mà bạn đã thực hiện ở bước đầu tiên được đề xuất trong bài viết Kết nối trước với các nguồn gốc bắt buộc. Bạn có thể tiết kiệm khoảng 400 mili giây bằng cách thiết lập kết nối sớm với staticxx.facebook.com và youtube.com:
Vì video trên YouTube hiện đã được tải từng phần nên chỉ còn lại staticxx.facebook.com, nguồn của tiện ích chia sẻ mạng xã hội. Việc thiết lập kết nối sớm với miền này cũng đơn giản như việc thêm thẻ <link>
vào <head>
của tài liệu:
<link rel="preconnect" href="https://staticxx.facebook.com">
Đánh giá lại hiệu suất
Đây là trạng thái của trang sau khi tối ưu hoá. Làm theo các bước trong phần Đo lường hiệu suất của lớp học lập trình để chạy quy trình kiểm tra Lighthouse khác.