Xóa JavaScript chặn hiển thị và Giảm bớt JavaScript là hai phương pháp tối ưu hóa để tăng tốc trang web, đây cũng là hai yếu tố quan trọng trong Google Pagespeed.
Xóa JavaScript chặn hiển thị
Trước khi trình duyệt có thể hiển thị một trang, nó phải xây dựng cây DOM bằng cách phân tích cú pháp đánh dấu HTML. Trong quá trình này, bất cứ khi nào trình phân tích cú pháp gặp một tập lệnh, nó phải dừng và thực thi nó trước khi nó có thể tiếp tục phân tích cú pháp HTML. Trong trường hợp của một kịch bản bên ngoài, trình phân tích cú pháp cũng buộc phải đợi tài nguyên tải xuống, có thể phải chịu một hoặc nhiều vòng kết nối mạng và làm chậm thời gian hiển thị trang đầu tiên.
Ví dụ dưới đây là cách chèn jQuery vào mã HTML:
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
Khi trình duyệt tải trang, nó sẽ dừng việc phân tích ở đây và chờ đợi tập lệnh này được tải xong trước khi tiếp tục; như vậy, tập lệnh JavaScript ở trên đã chặn hiển thị của trang.
Nhưng liệu việc tải các tập lệnh JavaScript trước khi phân tích xong cú pháp HTML có phải là điều cần thiết không? Chẳng hạn các tập lệnh JavaScript của Sharethis, Facebook, Google+, Twitter dùng để chia sẽ liên kết lên mạng xã hội có cần thiết phải được hiện thị cùng lúc với các nội dung quan trọng trên trang web không? Theo mình nghĩ thì người truy cập sẽ không làm bất kỳ hành động nào trước khi họ nhìn thấy nội dung trên trang web.
Vì vậy, tải một đống tập lệnh JavaScript trước khi nội dung trong màn hình đầu tiên được hiển thị là điều không cần thiết, thậm chí là ngu ngốc. Trừ khi bạn muốn tập lệnh JavaScript được thực thi để tương tác bổ sung trên mã HTML trước khi hiển thị đến người truy cập, ví dụ thêm hiệu ứng hoặc thêm, loại bỏ các phần tử đối với một nhóm đối tượng người dùng.
Bạn có thể nhúng nội tuyến ngay trong mã HTML, điều này giúp giảm một hoặc nhiều vòng kết nối mạng, tuy nhiên nó cũng làm tăng kích thước HTML, vì vậy nó chỉ phù hợp đối với các tập lệnh JavaScript nhỏ.
async và defer
Phương pháp tốt nhất để xóa JavaScript chặn hiển thị là sử dụng thuộc tính async (tải không đồng bộ) hoặc defer (trì hoãn) việc tải các tập lệnh JavaScript.
Định nghĩa và cách sử dụng:
Thuộc tính async và defer là thuộc tính boolean. Khi async có mặt, nó xác định rằng tập lệnh sẽ được thực hiện không đồng bộ ngay khi nó có sẵn. Khi defer có mặt, nó xác định rằng tập lệnh được thực hiện khi trang đã hoàn thành việc phân tích cú pháp.
Lưu ý: Thuộc tính async và defer chỉ dành cho các tập lệnh bên ngoài (và chỉ nên được sử dụng nếu thuộc tính src có mặt). Có một số cách mà tập lệnh bên ngoài có thể được thực thi:
- Nếu async hiện diện: Tập lệnh được thực hiện không đồng bộ với phần còn lại của trang (tập lệnh sẽ được thực thi trong khi trang tiếp tục phân tích cú pháp).
- Nếu async không hiện diện và defer có mặt: Tập lệnh được thực thi khi trang đã phân tích xong.
- Nếu async hoặc defer hiện diện: Tập lệnh được tìm nạp và thực hiện ngay lập tức, trước khi trình duyệt tiếp tục phân tích cú pháp trang.
- Async: Đối với các kịch bản quan trọng, bạn nên bao gồm nó trước nhất trong thẻ
<head></head>
để tập lệnh này được tải càng sớm càng tốt. - Defer: Chỉ nên trì hoãn với các kịch bản không cần thiết phải tải ngay trên trang web, không có sự khác biệt giữ việc đặt thẻ script trong
<head></head>
hay<body></body>
.
Ví dụ về cách sử dụng thuộc tính async để tải tập lệnh jQuery:
<script src="https://code.jquery.com/jquery-3.0.0.min.js" async></script>
Tập lệnh jQuery sẽ được tải ngay mà không chặn trình phân tích cú pháp, HTML tiếp tục được tải mà không cần chờ tập lệnh jQuery tải xong.
Hầu hết các tập lệnh của JavaScript như Google+ Share và Google Adsense được Google cung cấp đều sử dụng thuộc tính async làm mặc định.
Ví dụ về cách sử dụng thuộc tính defer để tải tập lệnh jQuery:
<script src="https://code.jquery.com/jquery-3.0.0.min.js" defer></script>
jQuery sẽ được hoãn lại cho đến sau khi kết xuất ban đầu hoặc các phần quan trọng khác của trang đã tải xong. Làm như vậy có thể giúp giảm ganh đua tài nguyên và cải thiện hiệu suất.
Các lỗi được biết
Tải không đồng bộ và trì hoãn JavaScript là phương pháp tốt để xóa JavaScript chặn hiển thị. Tuy nhiên nó cũng có một số lỗi mà bạn cần lưu ý.
Ví dụ bạn tải không đồng bộ jQuery như sau:
<script src="https://code.jquery.com/jquery-3.0.0.min.js" async></script> <script src="https://code.jquery.com/jquery-migrate-3.0.1.min.js" async></script> <script> if (typeof jQuery == 'undefined') { console.log('jQuery is not defined'); }; </script>
Vì jQuery Migrate cần hàm jQuery nhưng khi bạn tải không đồng bộ jQuery, trình duyệt sẽ tiếp tục tải HTML mà không cần chờ jQuery được tải xong. Vì vậy, các tập lệnh JavaScript và các kịch bản JavaScript có thể được thực thi trước khi hàm jQuery được tải, vì vậy đây là nguyên nhân gây ra lỗi. Uncaught ReferenceError: jQuery is not defined
là một lỗi phổ biến, nguyên nhân là hàm jQuery chưa được tải, bạn không thể gọi một hàm hoặc một biến khi nó chưa được tải. Như đoạn mã mã ở trên, bạn sẽ nhìn thấy hàm jQuery chưa được định nghĩa (undefined) trong Console của trình duyệt.
Để khắc phục lỗi này, bạn có thể không cần phải tải không đồng bộ hoặc trì hoãn các tập lệnh JavaScript chứa các hàm và biến cần thiết được sử dụng trong các mã JavaScript ở phía sau.
Phương pháp tốt nhất là gộp tất cả các tập lệnh JavaScript và các đoạn mã JavaScript vào trong một tập tin duy nhất, sau đó bạn có thể tải không đồng bộ hoặc trì hoãn nó.
Tạo thẻ script bằng JavaScript
Mình đã tạo thẻ script bằng JavaScript và làm một thử nghiệm, kết quả cho thấy có vẻ như trình duyệt Google Chrome và Firefox sẽ trì hoãn việc tải tập lệnh JavaScript trong thẻ script được tạo ra. Nhưng có một ưu điểm mà bạn nên sử dụng JavaScript để tạo thẻ script thay vì chèn mã HTML là tính linh hoạt của nó.
Trong nhiều trường hợp, trang web của bạn chỉ cần tải tập tin để phục vụ cho một nhóm đối tượng người dùng nào đó, hoặc đối với từng nhóm sẽ phục vụ theo cách khác nhau. Ví dụ, bạn yêu cầu người truy cập vào trang web phải nhấn nút Đồng ý một việc gì đó như là chính sách Cookie… nhưng điều này sẽ không còn cần thiết nữa nếu họ đã Đồng ý. Vì vậy, bạn có thể sử dụng JavaScript để kiểm tra thông tin và chỉ tải các tập lệnh khi cần thiết, điều này sẽ giúp tối ưu hóa phân phối JavaScript trên trang web của bạn.
Ví dụ:
if (!localStorage.getItem('agreed')){ localStorage.setItem('agreed','yes'); var head=document.getElementsByTagName('head')[0]; var script=document.createElement('script'); script.async=true; script.src="https://www.sitecuatui.com/jscuaban.js"; head.appendChild(script); }
Để biết chắc chắn trang web của bạn đã tải không đồng bộ hoặc trì hoãn đúng cách hay chưa, chỉ cần kiểm tra mục Loại bỏ JavaScript và CSS chặn hiển thị trong nội dung trong màn hình đầu tiên của Google Pagespeed.
Giảm bớt JavaScript
Không đồng bộ và trì hoãn là phương pháp tối ưu hóa cách tải JavaScript, bạn cũng nên giảm bớt JavaScript để các tập lệnh và kịch bản có kích thước nhỏ nhất có thể, điều này giúp tăng tốc độ trang web đáng kể. Xem thêm về cách giảm bớt HTML, CSS và JavaScript. Bạn nên giữ phiên bản gốc để dễ dàng sửa đổi và tiếp tục phát triển về sau và sử dụng phiên bản đã được tối ưu hóa cho trang web đang chạy.
Đối với WordPress, bạn có thể dùng tính năng Minify của plugin W3 Total Cache để tải không đồng bộ, trì hoãn cũng như giảm bớt HTML, CSS, và JavaScript. Mặc dù vậy, bạn nên tự gộp các tập tin và tối ưu hóa kích thước các tệp tin một lần bằng các công cụ thay vì sử dụng plugin để làm điều này. Nó sẽ giúp bạn tiết kiệm được thời gian và tài nguyên máy chủ cho mỗi lần thực hiện việc này.
Trên đây là các phương pháp để tối ưu hóa cách tải JavaScript cũng như tối ưu hóa kích thước của tập lệnh. Bạn nên tận dụng các phương pháp này để tăng tốc độ trang web tốt nhất có thể. Chúc bạn thành công!