Những năm gần đây, xu hướng tiếp cận người dùng bằng việc liên kết website thông qua những đoạn scripts của các trang web quảng cáo, mạng xã hội hay các dịch vụ live chat như Google, Facebook, hay Tawk.to, Subiz dần trở nên phổ biến. Tuy nhiên, việc sử dụng quá nhiều scripts của bên thứ 3 sẽ khiến trang web load chậm hay điểm test PageSpeed bị thấp do không thế tối ưu dữ liệu được. Do vậy, chủ website thường chấp nhận việc load site chậm hoặc là bỏ các scripts đi. Sau 1 thời gian tìm hiểu, chúng mình đã tìm ra cách để giải quyết được vấn đề này. Kỹ thuật mà chúng mình sắp nói tới sau đây được gọi là trì hoãn tải / thực thi script (delay the loading / execution of JavaScript). Cùng tìm hiểu nhé!
Lý do kỹ thuật trì hoãn thực thi script ra đời
Những dữ liệu tải từ server của bên thứ ba như Facebook Page Widget, Facebook Messenger, Facebook Comments, iframe hay các dịch vụ live chat như Tawk.to là những dữ liệu mà bạn không thể tự tối ưu được. Bạn không thể nén, gộp hay thiết lập cache cho chúng, đơn giản vì chúng không nằm trên host của bạn. Những dữ liệu này thường rất nặng và có thể gây ra các vấn đề nghiêm trọng liên quan đến tốc độ load của website. Để thấy rõ điều này, các bạn có thể dùng Google PageSpeed Insights, GTmetrix hay các công cụ test tốc độ để kiểm chứng.
Và vì không thể tối ưu được, nên giải pháp duy nhất để tích hợp các dịch vụ kể trên vào website mà không gây ảnh hưởng tới tốc độ load trang chính là trì hoãn việc tải chúng bằng cách trì hoãn việc thực thi các đoạn script tương ứng. Bằng cách này, bạn sẽ giảm thời gian hiển thị của trang và cải thiện các chỉ số tốc độ trên Google PageSpeed Insights như Time to Interactive, First CPU Idle, Max Potential Input Delay v.v. Điều này cũng sẽ giảm tải ban đầu cho trình duyệt bằng cách giảm số lượng request.
Cách thực hiện trì hoãn thực thi script cho website WordPress
Bước 1: Thêm script để hoãn việc thực thi các script khác
Trước tiên, bạn hãy thêm một đoạn script như ở dưới đây vào website của bạn. Script này sẽ làm nhiệm vụ trì hoãn việc tải / thực thi các script khác có trên website.
Các bạn có thể đặt script này trong thẻ <head>
hoặc thẻ <body>
. Nhưng các bạn nên đặt trong thẻ <head>
để chạy cùng với các đoạn script dành cho lazy load thì hợp lý hơn. Nếu đặt trong thẻ <body>
thì script của bạn phải đợi cả trang load xong thì nó mới được load. Như vậy đoạn script này sẽ không có tác dụng nếu các đoạn script cần trì hoãn đang được đặt ở thẻ <head>
.
<script> const loadScriptsTimer = setTimeout(loadScripts, 5000); const userInteractionEvents = ["mouseover","keydown","touchmove","touchstart" ]; userInteractionEvents.forEach(function (event) { window.addEventListener(event, triggerScriptLoader, { passive: true }); }); function triggerScriptLoader() { loadScripts(); clearTimeout(loadScriptsTimer); userInteractionEvents.forEach(function (event) { window.removeEventListener(event, triggerScriptLoader, { passive: true }); }); } function loadScripts() { document.querySelectorAll("script[data-type='lazy']").forEach(function (elem) { elem.setAttribute("src", elem.getAttribute("data-src")); }); document.querySelectorAll("iframe[data-type='lazy']").forEach(function (elem) { elem.setAttribute("src", elem.getAttribute("data-src")); }); } </script>
Vì vẫn sẽ có những script các bạn muốn thực hiện ngay nên mình không để đoạn code trên trì hoãn thực thi tất cả các script. Trong đoạn code trên, mình đã quy định là chỉ những đoạn script nào có thuộc tính là data-type="lazy"
(bạn có thể đổi tên thuộc tính tùy ý) thì mới bị trì hoãn thôi. Chính vì thế, sau khi thêm đoạn script này vào, bạn cần tìm đến các đoạn script mà bạn muốn trì hoãn để thêm thuộc tính này vào nhé. Việc này mình sẽ thực hiện ở bước tiếp theo.
Đoạn script trên cũng quy định là sẽ trì hoãn thực thi các đoạn script được chỉ định cho đến khi một trong 2 điều kiện sau xảy ra:
- Có sự tương tác của người dùng lên website, ví dụ như di chuột cuộn màn hình, nhập từ bàn phím hay cảm ứng từ các thiết bị di động.
- Sau một thời nhất định do bạn tự quy định (ví dụ như ở đoạn code trên mình đang đặt là 5s), nếu không có sự tương tác của người dùng thì đoạn script sẽ vẫn sẽ được thực thi.
Bước 2: Thêm thuộc tính cho các script cần trì hoãn thực thi
Với từng loại script sẽ có một cách sửa khác nhau. Mình sẽ hướng dẫn chi tiết để trì hoãn load 1 số script phổ biến như Facebook Customer Chat, Youtube, hay Google Maps.
Với Facebook Customer Chat
Dưới đây là script mặc định của Facebook, dùng để load widget Customer Chat:
<div id="fb-root"></div> <div id="fb-customer-chat" class="fb-customerchat"></div> <script> var chatbox = document.getElementById('fb-customer-chat'); chatbox.setAttribute("page_id", "YOUR_PAGE_ID"); chatbox.setAttribute("attribution", "biz_inbox"); window.fbAsyncInit = function() { FB.init({ xfbml : true, version : 'v12.0' }); }; (function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = 'https://connect.facebook.net/en_US/sdk/xfbml.customerchat.js'; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); </script>
Trong đó, phần code nằm trong đoạn (function()...);
dùng để tải widget chat vào website của bạn.
Mình sẽ rút ngắn script của Facebook Customer Chat bằng việc xóa function()
và thêm một đoạn script như này ngay bên dưới script của Facebook Customer Chat như sau:
<script data-type='lazy' data-src="https://connect.facebook.net/en_US/sdk/xfbml.customerchat.js"></script>
Khi đó, đoạn code của Facebook Customer Chat sẽ trở thành như sau:
<div id="fb-root"></div> <div id="fb-customer-chat" class="fb-customerchat"></div> <script> var chatbox = document.getElementById('fb-customer-chat'); chatbox.setAttribute("page_id", "YOUR_PAGE_ID"); chatbox.setAttribute("attribution", "biz_inbox"); window.fbAsyncInit = function() { FB.init({ xfbml : true, version : 'v12.0' }); }; </script> <script data-type='lazy' data-src="https://connect.facebook.net/en_US/sdk/xfbml.customerchat.js"></script>
Nếu bạn dùng các plugin khác của Facebook như Facebook Comment, Facebook Widget hay các dịch vụ live chat như Tawk.to, các bạn có thể làm tương tự như trên.
Với thẻ iFrame
Youtube, Google Maps thường hay dùng các thẻ iFrame. Với các thẻ này, bạn chỉ cần thêm một thuộc tính là data-type="lazy"
như sau:
Với Youtube
Iframe mặc định của Youtube là:
<iframe src="https://www.youtube.com/embed/I3ncHxLxwlM"></iframe>
Thì bây giờ, mình sẽ đổi nó thành:
<iframe data-type="lazy" data-src="https://www.youtube.com/embed/I3ncHxLxwlM"></iframe>
Với Google Maps
Iframe mặc định của Google Maps như này:
<iframe src="https://www.google.com/maps/embed/v1/place?key=API_KEY&q=Space+Needle,Seattle+WA"></iframe>
Mình sẽ đổi thành:
<iframe data-type="lazy" data-src="https://www.google.com/maps/embed/v1/place?key=API_KEY&q=Space+Needle,Seattle+WA"></iframe>
Với các script thông thường
Nếu bạn muốn áp dụng kỹ thuật trên với các đoạn script thông thường, bạn chỉ cần đổi src
thành data-src
và cũng thêm thuộc tính data-type="lazy"
.
Ví dụ một script là:
<script src="custom-javascript.js"></script>
Thì sẽ được đổi thành:
<script data-src="custom-javascript.js" data-type="lazy"></script>
Nên và không nên dùng trì hoãn thực thi script khi nào?
Kỹ thuật trì hoãn thực thi script này nên được sử dụng cho những script kiểu tương tác người dùng hay live chat như Facebook Customer Chat, Facebook Widget, Facebook Comment, iframe (Youtube, Google Maps), Tawk.to …
Ngược lại, mình không khuyến khích sử dụng nó cho những script kiểu theo dõi hay phân tích số liệu người dùng như là Google Analytics, Facebook Pixel, Google Tag Manager, Crazy Egg, Google Remarketing Tag, … Bởi vì việc áp dụng kỹ thuật này sẽ khiến các dữ liệu được ghi nhận không đầy đủ hoặc thiếu chính xác. Chắc chắn bạn sẽ không muốn bỏ lỡ các dữ liệu này đâu.
Lời Cuối
Kỹ thuật trì hoãn thực thi script sẽ giúp website của bạn được tối ưu hơn cũng như tăng điểm PageSpeed. Tuy nhiên, bạn hãy cân nhắc dùng script sao cho phù hợp nhé. Bởi ngoài cách này ra thì cũng có rất nhiều cách khác nữa để tăng tốc cho website của bạn. Nếu bạn cảm thấy không thể áp dụng kỹ thuật này lên website của bạn, thì hãy tham khảo các cách khác trong series bài viết này nhé.
Bạn có thấy phần nào khó hiểu hay còn khúc mắc ở đâu không? Hãy chia sẻ để cùng thảo luận ở phần comment nhé.