Tải JavaScript hiệu quả với trì hoãn và không đồng bộ

Khi tải một tập lệnh trên một trang HTML, bạn cần phải cẩn thận để không làm tổn hại đến hiệu suất tải của trang. Tùy thuộc vào vị trí và cách bạn thêm tập lệnh của mình vào trang HTML sẽ ảnh hưởng đến thời gian tải

Khi tải một tập lệnh trên một trang HTML, bạn cần phải cẩn thận để không làm tổn hại đến hiệu suất tải của trang.

Theo truyền thống, một tập lệnh được đưa vào trang theo cách này:

<script src="script.js"></script>

bất cứ khi nào trình phân tích cú pháp HTML tìm thấy dòng này, một yêu cầu sẽ được thực hiện để tìm nạp tập lệnh và tập lệnh được thực thi.

Khi quá trình này được thực hiện, quá trình phân tích cú pháp có thể tiếp tục và phần còn lại của HTML có thể được phân tích.

Như bạn có thể tưởng tượng, thao tác này có thể có tác động rất lớn đến thời gian tải của trang.

Nếu tập lệnh tải lâu hơn một chút so với dự kiến, ví dụ: nếu mạng hơi chậm hoặc nếu bạn đang sử dụng thiết bị di động và kết nối hơi cẩu thả, khách truy cập có thể sẽ thấy một trang trống cho đến khi tập lệnh đó được tải và thực thi.

Vị trí quan trọng

Khi bạn lần đầu tiên học HTML, bạn được biết các thẻ script nằm trong<head>nhãn:

<html>
  <head>
    <title>Title</title>
    <script src="script.js"></script>
  </head>
  <body>
    ...
  </body>
</html>

Như tôi đã nói với bạn trước đó, khi trình phân tích cú pháp tìm thấy dòng này, nó sẽ tìm nạp tập lệnh và thực thi nó.Sau đó, sau khi hoàn thành tác vụ này, nó sẽ tiếp tục phân tích cú pháp phần thân.

Điều này thật tệ vì có rất nhiều sự chậm trễ được giới thiệu. Một giải pháp rất phổ biến cho vấn đề này là đặtscriptở cuối trang, ngay trước khi đóng</body>nhãn.

Khi làm như vậy, tập lệnh được tải và thực thi sau khi tất cả trang đã được phân tích cú pháp và tải, đó làcải tiến lớnquaheadthay thế.

Đây là điều tốt nhất bạn có thể làm nếu bạn cần hỗ trợ các trình duyệt cũ hơn không hỗ trợ hai tính năng tương đối gần đây của HTML:asyncdefer.

Async and Defer

Cả async và defer đều là các thuộc tính boolean. Cách sử dụng của chúng tương tự nhau:

<script async src="script.js"></script>
<script defer src="script.js"></script>

nếu bạn chỉ định cả hai,asyncđược ưu tiên trên các trình duyệt hiện đại, trong khi các trình duyệt cũ hơn hỗ trợdefernhưng khôngasyncsẽ dự phòng chodefer.

Đối với bảng hỗ trợ, hãy kiểm tra caniuse.com để biết không đồng bộhttps://caniuse.com/#feat=script-asyncvà để trì hoãnhttps://caniuse.com/#feat=script-defer

Các thuộc tính này chỉ có ý nghĩa khi sử dụng tập lệnh trongheadcủa trang và chúng sẽ vô dụng nếu bạn đặt tập lệnh vàobodyfooter như chúng ta đã thấy ở trên.

So sánh hiệu suất

Không trì hoãn hoặc không đồng bộ, trong đầu

Đây là cách một trang tải một tập lệnh mà không hoãn lại hoặc không đồng bộ, hãy đưa vàoheadphần của trang:

Without defer or async, in the head

Quá trình phân tích cú pháp bị tạm dừng cho đến khi tập lệnh được tìm nạp và thực thi. Sau khi hoàn tất, quá trình phân tích cú pháp sẽ tiếp tục.

Không trì hoãn hoặc không đồng bộ, trong cơ thể

Đây là cách một trang tải tập lệnh mà không hoãn lại hoặc không đồng bộ, hãy đặt ở cuốibody, ngay trước khi nó đóng:

Without defer or async, in the body end

Quá trình phân tích cú pháp được thực hiện mà không có bất kỳ khoảng tạm dừng nào và khi nó kết thúc, tập lệnh sẽ được tìm nạp và thực thi. Việc phân tích cú pháp được thực hiện trước khi tập lệnh được tải xuống, vì vậy trang xuất hiện cho người dùng theo cách trước ví dụ trước.

Với async, trong đầu

Đây là cách một trang tải một tập lệnh vớiasync, đặt trongheadnhãn:

With async

Tập lệnh được tìm nạp không đồng bộ và khi nó sẵn sàng, quá trình phân tích cú pháp HTML sẽ bị tạm dừng để thực thi tập lệnh, sau đó nó được tiếp tục lại.

Với sự trì hoãn, trong đầu

Đây là cách một trang tải một tập lệnh vớidefer, đặt trongheadnhãn:

With defer

Tập lệnh được tìm nạp không đồng bộ và nó chỉ được thực thi sau khi phân tích cú pháp HTML hoàn tất.

Quá trình phân tích cú pháp kết thúc giống như khi chúng ta đặt tập lệnh vào cuốibody, nhưng nhìn chung, quá trình thực thi tập lệnh kết thúc tốt trước đó, vì tập lệnh đã được tải xuống song song với quá trình phân tích cú pháp HTML.

Vì vậy, đây là giải pháp chiến thắng về tốc độ 🏆

Chặn phân tích cú pháp

asyncchặn phân tích cú pháp của trang trong khideferkhông làm.

Chặn kết xuất

Cũng khôngasynccũng khôngdeferđảm bảo bất cứ điều gì về việc chặn hiển thị. Điều này phụ thuộc vào bạn và tập lệnh của bạn (ví dụ: đảm bảo rằng các tập lệnh của bạn chạy sauonLoad) biến cố.

domInteractive

Tập lệnh được đánh dấudeferđược thực hiện ngay saudomInteractivesự kiện xảy ra sau khi HTML được tải, phân tích cú pháp vàDOMđược xây dựng.

CSS và hình ảnh tại thời điểm này vẫn phải được phân tích cú pháp và tải.

Khi điều này được thực hiện, trình duyệt sẽ phát radomCompletesự kiện, và sau đóonLoad.

domInteractiverất quan trọng vì thời gian của nó được công nhận là thước đo tốc độ tải cảm nhận.Xem MDNđể biết thêm.

Giữ mọi thứ theo thứ tự

Một trường hợp chuyên nghiệp khácdefer: các tập lệnh được đánh dấuasyncđược thực hiện theo thứ tự bình thường, khi chúng có sẵn. Tập lệnh được đánh dấudeferđược thực thi (sau khi phân tích cú pháp hoàn tất) theo thứ tự mà chúng được xác định trong đánh dấu.

Chỉ cần cho tôi biết cách tốt nhất

Điều tốt nhất cần làm để tăng tốc độ tải trang của bạn khi sử dụng các tập lệnh là đặt chúng vàoheadvà thêm mộtdeferthuộc tính của bạnscriptnhãn:

<script defer src="script.js"></script>

Đây là tình huống kích hoạt nhanh hơndomInteractivebiến cố.

Xem xét các ưu điểm củadefer, có vẻ là một lựa chọn tốt hơnasynctrong nhiều tình huống khác nhau.

Trừ khi bạn ổn với việc trì hoãn lần hiển thị đầu tiên của trang, hãy đảm bảo rằng khi trang được phân tích cú pháp, JavaScript bạn muốn đã được thực thi.

Tải xuống miễn phí của tôiSổ tay dành cho Người mới bắt đầu JavaScript


Các hướng dẫn khác về trình duyệt: