Trang chủ Kiến thức cơ bản

Cách tối ưu hóa file HTML, CSS, Javascript (với defer va async) chuẩn nhất 2020

Cách tối ưu hóa file HTML, CSS, Javascript (với defer va async) chuẩn nhất 2020

Khi xây dựng một trang web, bên cạnh việc code đủ tính năng và giao diện đẹp, thì các web developer cũng cần chú ý tới tốc độ tải trang. Có một tốc độ tải trang nhanh sẽ giúp gia tăng trải nghiệm người dùng, và góp phần đưa website lên thứ hạng cao hơn trên trang tìm kiếm Google. Bài viết này sẽ cung cấp cho bạn đọc những mẹo hữu ích nhất để tối ưu hóa các file HTML, CSS và JS (javascript), giúp tăng tốc độ tải trang web.

Hạn chế nhúng hoặc chèn code CSS và Javascript inline

Khi cần chèn code CSS hoặc Javascript vào website, ta có ba cách:

Inline:

Inline CSS

<div style="color:green;">


Inline JS

<button class="btn" onclick="alert('Hello World')">

Nhúng (embed):

Embedded CSS

<style>.red {color: red;}</style>


Embedded JS

<script>alert('Hello World');</script>

Tạo file riêng

External CSS

<link rel="stylesheet" href="file.css">


External JS

<script type="text/javascript" src="script.js">

Trên thực tế, cách chèn code inline và nhúng sẽ tạo ra ít HTTP request đến máy chủ hơn, từ đó giúp tốc độ tải trang web nhanh hơn. Tuy nhiên, hai cách này chỉ phù hợp với các trang web có ít code CSS và Javascript. Bởi vì khi lượng code tăng lên, chúng ta sẽ rất khó kiểm soát, bảo trì hay sửa lỗi.

Hầu hết các website được khuyên sử dụng cách thứ ba, tức là tạo file riêng cho code CSS và Javascript. Tuy việc tạo file CSS và JS làm tăng số lượng request browser gửi tới máy chủ, qua đó tốc độ tải trang bị ảnh hưởng, nhưng mức độ ảnh hưởng không đáng kể. Mặt khác, bạn sẽ dễ dàng quản lý và bảo trì code hơn khi tạo file CSS và Javascript riêng.

Tối ưu tải JavaScript với defer và async

Khi tải tập lệnh javascipt trên trang HTML, bạn cần cẩn thận để không làm ảnh hưởng đến hiệu suất tải 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 mà thời gian tải sẽ bị ảnh hưởng.

Thông thường, một script sẽ được thêm vào trang như dưới đâ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, sẽ có 1 request được tạo để tìm nạp tập lệnh và tập lệnh sau đó được thực hiện.

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

Lúc này bạn có thể nhận thấy, thao tác này có thể có tác động rất lớn đến thời gian tải trang.

Nếu script mất nhiều thời gian để tải hơn dự kiến, ví dụ: nếu mạng chậm một chút hoặc nếu bạn đang sử dụng thiết bị di động và kết nối có phần bập bõm, khách truy cập có thể sẽ thấy một trang trống cho đến khi script được tải xong và chạy.

Vị trí cũng quan trọng

Khi lần đầu tiên học về HTML, bạn được dạy rằng các thẻ script nằm trong thẻ <head>:

<html>

<head>

<title>Title</title>

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

</head>

<body>

...

</body>

</html>

Như đã nói ở trên, khi trình phân tích cú pháp tìm thấy dòng này, nó sẽ tìm nạp script và chạy script. Sau đó, khi đã hoàn thành nhiệm vụ này, nó sẽ phân tích tiếp phần body.

Điều này không tốt vì xảy ra tình trạng chậm trễ tại đây. Một giải pháp rất phổ biến cho vấn đề này là đặt thẻ script ở cuối trang, ngay trước thẻ đóng </ body>.

Khi làm như vậy, script sẽ được tải và chạy sau khi tất cả các trang đã được phân tích cú pháp và được tải, đây là cách tối ưu hơn nhiều so với đặt thẻ script trong thẻ head.

Đây là cách tốt nhất bạn nên dùng nếu bạn cần tối ưu các trình duyệt cũ không hỗ trợ hai tính năng tương đối mới của HTML: async và defer.

Async và Defer

Cả async và defer đều là các đối tượng boolean. Cách sử dụng của chúng là 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 sẽ được ưu tiên trên các trình duyệt phiên bản mới, trong khi các trình duyệt cũ hơn hỗ trợ defer mà không phải async sẽ tự động chuyển sang defer.

Các thuộc tính này chỉ có ý nghĩa khi sử dụng script trong phần đầu trang và chúng sẽ không có vai trò gì nếu bạn đặt script vào phần chân trang như chúng ta đã thấy ở trên.

Việc phân tích cú pháp được tạm dừng cho đến khi script được tìm nạp và chạy. Một khi bước này được thực hiện,việc phân tích trang lại được tiếp tục.

Không có defer hoặc async trong phần body

Dưới đây là cách để một trang tải tập lệnh mà không cần defer hoặc async, đặt ở cuối thẻ body, ngay trước khi đóng thẻ:

Quá trình phân tích cú pháp được thực hiện mà không xảy ra bất kỳ tạm dừng nào và khi nó kết thúc, script được tìm nạp và được chạy. Phân tích cú pháp thậm chí được hoàn thành trước cả khi script được tải xuống, vì vậy trang có thể hiển thị đến người dùng nhanh hơn so với phần ví dụ trước đó.

Có async, trong đầu trang/head

Dưới đây là cách thức một trang tải script với async, đặt trong thẻ head:

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

Với defer, trong đầu trang/head

Dưới đây, là cách một trang tải script với defer, đặt trong thẻ head:

Script được tìm nạp không đồng bộ và chỉ được chạy sau khi đã phân tích cú pháp HTML.

Phân tích cú pháp hoàn tất giống như khi ta đặt script ở cuối thẻ body, nhưng nhìn chung, quá trình chạy script đã hoàn tất hoàn toàn trước đó, bởi vì script đã được tải xuống song song với phân tích cú pháp HTML.

Vì vậy, đây chính là giải pháp tối ưu khi nói đến tốc độ.

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

Async chặn phân tích cú pháp của trang trong khi Defer thì không.

Chặn render

Cả async và defer đều không đảm bảo bất cứ gì về việc chặn render. Mà vấn đề này tùy thuộc vào bạn và script của bạn (ví dụ: đảm bảo script chạy sau onLoad chẳng hạn).

domInteractive

Các script được đánh dấu defer sẽ được chạy ngay sau domInteractive, sự kiện sẽ diễn ra sau khi HTML được tải, được phân tích cú pháp và DOM được tạo.

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

Khi quá trình hoàn tất, trình duyệt sẽ trình phát domComplete và sau đó là onLoad.

domInteractive rất quan trọng vì thời gian của nó được xem là thước đo cho tốc độ tải về mặt cảm nhận.

Sắp xếp các yếu tố 1 cách trật tự

Một trường hợp defer khác: các script được đánh dấu không đồng bộ sẽ được chạy theo thứ tự thông thường khi chúng khả dụng. 

Kết

Vậy điều tốt nhất chúng ta nên làm để tăng tốc độ tải trang khi sử dụng script: là đặt chúng vào phần đầu trang và thêm thuộc tính defer vào thẻ script:

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

Đây là kịch bản để thúc đẩy domInteractive nhanh hơn.

Khi xem xét ưu điểm của defer, có vẻ như đây là lựa chọn tốt hơn so với async trong một loạt các kịch bản.

Trừ khi bạn thấy không vấn đề gì với việc trì hoãn lượt render đầu tiên của trang, hãy đảm bảo rằng khi trang được xử lý xong, mã JavaScript cũng được thực hiện xong.

CSS đặt trước, JS đặt sau

Như bạn đã thấy trong ví dụ trên, JS có thể làm gián đoạn việc tải HTML. Do đó, thông thường JS được đặt ở cuối và load sau cùng. Mặt khác, CSS thường được đặt ở đầu trang để người dùng không phải thấy một giao diện trang web kém thẩm mỹ khi vừa vào trang.

<html lang="vi">

<head>

<meta charset="UTF-8" />

<title>Test | KarmiPhuc</title>

<!-- đặt CSS ở thẻ head -->

<link...>

</head>

<body>

<!-- HTML here -->

...

<!-- đặt JS trước khi đóng body -->

<script...>

</body>

</html>

Hạn chế sử dụng @import

Khi muốn chèn một file CSS bên ngoài vào website, ta có hai cách:

External CSS Link

<link rel="stylesheet" href="file.css">


CSS Import via external or inline style

@import url('style.css');

Với cách đầu tiên, trình duyệt có thể tải đồng thời nhiều file CSS. Với cách thứ hai, file style.css sẽ chỉ được tải khi file CSS gốc đã tải xong. Cách này làm hạn chế khả năng tải song song của trình duyệt, và trong nhiều trường hợp có thể làm giảm tốc độ tải website.

Vì vậy, hạn chế sử dụng @import cũng là một cách giúp tối ưu tốc độ tải trang.

Sử dụng một file CSS/JS duy nhất

Nếu bạn có nhiều file CSS/JS, thì hãy gộp chúng lại thành một file duy nhất nếu bạn muốn trang web được tối ưu.

Việc sử dụng nhiều file CSS/JS sẽ giúp bạn dễ quản lý code hơn, tuy nhiên nó cũng vô tình tạo ra nhiều request tới máy chủ, khiến cho trình duyệt phải thực hiện nhiều việc hơn khi tải đầy đủ trang web. Thông thường khi tải các tài nguyên, trình duyệt sẽ giới hạn trong khoảng từ 4 đến 8 kết nối đồng thời cho mỗi tên miền.

Giả sử trang web của bạn có 10 file CSS và 10 file JS thì sẽ cần ít nhất 3 lượt kết nối để tải hết 30 file này. Trong khi bạn có thể tải hết trong một lượt khi gộp lại thành 1 file CSS và 1 file JS. Mặc dù trọng lượng của file cũng ảnh hưởng tới tốc độ tải file, nhưng việc giảm số lượng file để giảm số request tới máy chủ là một việc làm cần thiết khi tối ưu code web và nó thực sự mang lại hiệu quả nhất định.

Pagespeed Insight - một công cụ đo tốc độ tải trang được khuyến nghị bởi google cũng có những lời khuyên tương tự: chỉ sử dụng một file CSS và một file JS để tối ưu hóa tốc độ tải trang, vốn là một trong những yếu tố quan trọng trong SEO web.

Sử dụng kỹ thuật tải không đồng bộ

Nếu bạn có dự định thu hút người dùng vào website thông qua các kênh mạng xã hội như Facebook hay Twitter, thì việc thêm nút Chia sẻ Facebook hay Tweet là không thể thiếu. Tuy nhiên, những đoạn code dành cho các nút chia sẻ này thường đòi hỏi trang web phải tải về các file CSS/JS cần thiết. Và điều này có thể tiêu tốn một lượng thời gian của người dùng khi tải trang.

Để giải quyết vấn đề này, ta thường sử dụng 2 cách:

Sử dụng JS để tải không đồng bộ các file JS bên ngoài

Async GA Load

(function() {

var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;

ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') '.google-analytics.com/ga.js';

var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);

})();

Trong ví dụ là mã Google Analytics được tải không đồng bộ bằng Javascript.

Cách 2 là sử dụng friendly iframe

Facebook Friendly Iframe

(function() {

var url = 'http://example.org/js.js';

var iframe = document.createElement('iframe');

(iframe.frameElement || iframe).style.cssText =

"width: 0; height: 0; border: 0";

iframe.src = "javascript:false";

var where = document.getElementsByTagName('script')[0];

where.parentNode.insertBefore(iframe, where);

var doc = iframe.contentWindow.document;

doc.open().write('<body onload="'

'var js = document.createElement('script');'

'js.src = '' url '';'

'document.body.appendChild(js);">');

doc.close();

}());

Bằng cách này, bạn có thể tải không đồng bộ các thành phần ít quan trọng hơn trên trang, qua đó tăng tốc độ tải trang web và cải thiện trải nghiệm người dùng.

Lời kết

Việc tối ưu code CSS/JS cho website không chỉ có ý nghĩa về mặt kỹ thuật, SEO, mà còn giúp cho người dùng có trải nghiệm tốt nhất khi tham khảo nội dung website, nó cũng giúp cho web developer dễ dàng quản lý và bảo trì code khi cần thiết. Hy vọng những mẹo trên đây có thể giúp cho bạn tối ưu được code trên trang web của mình để mang lại trải nghiệm tốt nhất và tăng trưởng cho website.

>> Có thể bạn quan tâm: Bỏ túi ngay 9 Tips tối ưu CSS hiệu quả

BizFly Cloud là hệ sinh thái điện toán đám mây được vận hành bởi VCCorp - Công ty dẫn đầu trong lĩnh vực công nghệ và truyền thông tại Việt Nam. Với đội ngũ kỹ thuật viên trình độ cao và kinh nghiệm lâu năm làm việc trên các công nghệ khác nhau như cloud, mobile, web..., chúng tôi có đủ khả năng để hỗ trợ đưa ra những giải pháp và công nghệ toàn diện giúp doanh nghiệp chuyển đổi số thành công. Dành cho độc giả quan tâm tới các dịch vụ đám mây do BizFly Cloud cung cấp có thể truy cập tại đây.