U N E S T

Group

Google có nhiều công cụ giúp người quản trị web tối ưu hóa tốc độ cho người dùng, ngoài Google AMP, định dạng ảnh WebP, tôi cũng rất thích các lời khuyên bảo từ công cụ kiểm tra tốc độ trang web có tên là PageSpeed Insights.

Bạn có thể vào và kiểm tra tốc độ của trang web, nó sẽ đưa ra những điểm bạn chưa tối ưu dẫn đến tốc độ chậm và những điểm bạn đã tối ưu tốt. Với WordPress thì bạn hoàn toàn có thể cài một vài plugin là có thể thấy được điểm số thay đổi tích cực

Tuy nhiên để bạn hiểu bản chất vấn đề tôi sẽ đề cập đến các plugin cụ thể vào lúc khác và sẽ giải thích cơ chế tối ưu trước.

Tại sao phải khổ sở đi tìm các cơ chế bản chất trong tối ưu tốc độ làm gì trong khi có thể ăn sẵn nhờ plugin?

Bởi vì ăn sẵn có các nguy cơ sau:

  • Bạn đơn giản làm theo các lời khuyên, nhưng các lời khuyên luôn có ngoại lệ, và nếu trang của bạn rơi vào ngoại lệ thì cách bạn tối ưu thậm chí là có hại.
  • Bạn chỉ tối ưu hời hợt bề ngoài, tức là bạn làm được rất ít, không hết khả năng.
  • Nếu không có các công cụ hỗ trợ tiện lợi thì bạn không biết làm gì cả!

Hiểu sâu bản chất giúp bạn tối ưu được rất nhiều & hiểu rằng bạn đã tối ưu trang đến đâu, mặc cho có thể tồn tại những điểm mà các báo cáo nói là có vấn đề về tốc độ.

Rồi, giờ chúng ta sẽ xem từng hướng dẫn cụ thể của PageSpeed Insights. Lưu ý là trong bài viết này tôi chỉ đề cập đến phần tốc độ trong lời khuyên của họ. Còn phần tối ưu tính khả dụng sẽ được viết trong bài khác.

1. Tránh chuyển hướng ở trang đích

Quy tắc này kích hoạt (this rule triggers) khi PageSpeed Insights phát hiện (detects) bạn có hơn một chuyển hướng từ url hiện tại đến trang landing page cuối cùng.

Tổng quan

Chuyển hướng tạo thêm một chu trình yêu cầu-phản hồi HTTP và làm trang trì hoãn quá trình hiển thị (rendering). Trong trường hợp tốt nhất, mỗi lần chuyển hướng sẽ thêm một vòng khứ hồi (yêu cầu-phản hồi HTTP), và trong trường hợp tệ nhất nó có thể tạo ra nhiều vòng lặp khứ hồi như thực hiện tra cứu DNS, “bắt tay” TCP, đàm phán TLS ngoài việc có thêm chu kỳ HTTP yêu cầu-hồi đáp. Do vậy bạn phải tối thiểu hoá việc sử dụng chuyển hướng để nâng cao hiệu năng của trang.

Dưới đây là một số ví dụ về các kiểu chuyển hướng điển hình (redirect patterns):

  • example.com sử dụng thiết kế web đáp ứng, không cần chuyển hướng – nhanh và tối ưu! (bạn nên làm như thế này)
  • example.com → m.example.com/home – xuất hiện nhiều chuyển hướng ảnh hưởng đến người dùng di động (xảy ra khi bạn định làm một url riêng cho phiên bản di động)
  • example.com → www.example.com → m.example.com – trải nghiệm di động rất chậm (với đủ các kiểu chuyển hướng từ không có www đến có www rồi đến phiên bản di động)

Lời khuyên

Hãy tìm hiểu các nguyên tắc cơ bản của thiết kế đáp ứng để phân phối trải nghiệm tốt trên nhiều thiết bị và loại bỏ (eliminate) các chuyển hướng không cần thiết.

Nếu trang của bạn yêu cầu chuyển hướng, hãy đọc hướng dẫn chuyển hướng và phát hiện User-Agent của chúng tôi (Google).

Kinh nghiệm cá nhân với WordPress: Nếu bạn dùng WordPress, thông thường bạn sẽ không gặp vấn đề chuyển hướng kiểu như trên. Các giao diện dành cho WordPress (ngay cả miễn phí) hầu như đều là thiết kế đáp ứng.

2. Bật nén

Quy tắc này kích hoạt khi PageSpeed Insights phát hiện các nguồn nén đang thực thi (compressible resources were served) không có nén gzip.

Tổng quan

Tất cả các trình duyệt hiện đại đều hỗ trợ và tự động đàm phán nén gzip cho tất cả các yêu cầu HTTP. Bật gzip có thể giảm dung lượng truyền tải lên đến 90%, điều này có thể giảm đáng kể thời gian tải dữ liệu nguồn, giảm dữ liệu sử dụng cho người dùng và nâng cao thời gian xuất trang lần đầu. Xem nén văn bản với GZIP để hiểu thêm.

Lời khuyên

Bật và kiểm tra xem nén gzip có được hỗ trợ bởi web server của bạn hay là không. Dự án HTML5 Boilerplate bao gồm các tệp tin cấu hình mẫu cho tất cả máy chủ phổ biến nhất với các lời khuyên chi tiết cho việc cấu hình và thiết lập: tìm máy chủ ưa thích của bạn trong danh sách, tìm tới phần gzip, và xem xem máy chủ của bạn có được cấu hình với các thiết lập được khuyến cáo không. Ngoài ra hãy tham khảo tài liệu cho máy chủ web của bạn về cách bật nén:

Kinh nghiệm cá nhân với WordPress: Để kiểm tra xem trang của bạn đã được nén hay chưa, bạn có thể vào các trang web chuyên kiểm tra việc này rồi đưa tên miền của bạn vào. Gõ từ khóa “Check GZIP compression” để có được các trang như vậy.

Rất nhiều dịch vụ hosting mặc định bật gzip nên có thể bạn sẽ bất ngờ khi thấy trang của mình đã được bật rồi dù bản thân chưa làm gì cả. Bật gzip giúp các hãng hosting giảm tải băng thông.

Hiện nay một số hosting hỗ trợ kiểu nén còn tốt hơn tên là brotli, một chương trình do Google phát triển. Để kiểm tra xem hosting của bạn có hỗ trợ kiểu nén này không, bạn vào trang này: https://tools.keycdn.com/brotli-test

Các câu hỏi thường gặp (FAQ)

PageSpeed Insight báo là nhiều nội dung tĩnh của tôi (my static content) cần nén gzip, nhưng tôi đã cấu hình máy chủ web để nén gzip các file đó. Tại sao PageSpeed Insights không phát hiện được là tôi đã bật nén rồi?

Proxy servers và phần mềm chống virus có thể vô hiệu hoá nén khi các file này được tải về máy khách. Kết quả của PageSpeed Insight dựa trên headers, khi chúng thực sự được trả lại cho máy khách, vì vậy nếu bạn thực hiện phân tích trên máy khách sử dụng các phần mềm chống virus như vậy hoặc ngồi phía sau máy chủ proxy trung gian (nhiều máy chủ là vô hình, và bạn có thể thậm chí không ý thức được sự can thiệp của proxy giữa máy khách của bạn và máy chủ web), chúng có thể là nguyên nhân của vấn đề này.

Để xác định nếu proxy là nguyên nhân, bạn có thể sử dụng PageSpeed Insights Chrome extension để kiểm tra headers:

  1. Chạy PageSpeed trên trang.
  2. Click vào tab Hiển thị Nguồn (Show Resource).
  3. Mở rộng URL của nguồn được gắn cờ là không bật nén. Các header đi kèm với nguồn được hiển thị. Nếu bạn thấy header gọi đến ViaForwarded, or Proxy-Connection, điều đấy chỉ ra rằng một proxy đang phục vụ tài nguyên.

3. Cải thiện thời gian phản hồi của máy chủ

Quy tắc này được kích hoạt khi PageSpeed Insights phát hiện thời gian phản hồi máy chủ của bạn trên 200 ms.

Tổng quan

Thời gian phản hồi máy chủ (server response time) đo khoảng thời gian phải bỏ ra (how long it takes) cho việc tải HTML cần thiết để bắt đầu quá trình hiển thị trang từ máy chủ của bạn, trừ đi độ trễ mạng (network latency) giữa Google và máy chủ của bạn. Có thể có sự khác nhau ngay cả lần chạy tiếp theo, nhưng sự khác biệt không nên quá lớn. Trong thực tế, sự không ổn định của thời gian phản hồi máy chủ có thể biểu thị cho một vấn đề nghiêm trọng mang tính nền tảng về hiệu suất (underlying performance issue).

Lời khuyên

Bạn phải giảm thời gian phản hồi của máy chủ xuống dưới 200 ms. Có hàng tá yếu tố tiềm năng có thể gây chậm thời gian phản hồi của máy chủ: ứng dụng logic chậm, truy vấn cơ sở dữ liệu chậm, bộ định tuyến chậm, frameworks, các thư viện, thiếu CPU, hoặc thiếu RAM.

Bạn cần xem xét tất cả các yếu tố đó để cải thiện thời gian phản hồi của máy chủ. Bước đầu tiên để biết được lý do tại sao thời gian phản hồi của máy chủ lại tăng là đo đạc. Sau đó, với dữ liệu trong tay, tìm hiểu các hướng dẫn thích hợp để biết rắc rối nằm ở đâu. Một khi vấn đề được giải quyết, bạn phải tiếp tục đo thời gian phản hồi của máy chủ và xác định bất cứ sự tắc nghẽn cổ chai về hiệu suất nào trong trương lai.

  1. Thu thập và kiểm tra các dữ liệu và thông tin hiệu suất có sẵn. Nếu không có, đánh giá bằng cách sử dụng một ứng dụng theo dõi web tự động (được hosted và có phiên bản nguồn mở cho hầu hết các nền tảng) hoặc thêm thiết bị tùy chỉnh.
  2. Xác định và khắc phục các nguyên nhân hàng đầu gây tắc nghẽn cổ chai làm ảnh hưởng đến hiệu suất. Nếu bạn sử dụng framework web, hoặc nền tảng quản lý nội dung phổ biến, tham khảo tài liệu về các thực hành tốt nhất của nó để tối ưu hóa hiệu suất.
  3. Theo dõi và cảnh báo cho bất cứ vấn đề suy giảm (regressions) về hiệu suất nào trong tương lai!

Kinh nghiệm cá nhân với WordPress: Đôi khi các plugin có khả năng xung đột với nhau và có thể ảnh hưởng đến tốc độ tải trang, có khả năng là do ảnh hưởng đến RAM hoặc CPU.

4. Tận dụng sức mạnh bộ nhớ đệm của trình duyệt

Quy tắc này kích hoạt khi PageSpeed Insights phát hiện hồi đáp từ máy chủ của bạn không bao gồm caching header hoặc nếu có thì chỉ được chỉ định thời gian cache ngắn (specified to be cached for only a short time).

Tổng quan

Tìm nạp nguồn qua mạng (fetching resources over the network) gặp hai bất lợi là chậm và đắt đỏ: dowload có thể cần nhiều vòng lặp giữa máy khách và máy chủ (server), điều này sẽ làm trì hoãn xử lý và có thể ngăn chặn quá trình hiển thị (rendering) nội dung của trang, nó cũng làm tăng chi phí dữ liệu (incurs data costs) cho người xem. Tất cả hồi đáp từ máy chủ phải chỉ rõ (specify) chính sách (thông số) caching để giúp máy khách xác định được khi nào nó có thể sử dụng lại (reuse) phản hồi tìm nạp đã có trước đó.

Lời khuyên

Mỗi tài nguyên nên chỉ định rõ ràng chính sách (thông số) caching để trả lời các câu hỏi sau: khi nào dữ liệu nguồn có thể lưu trữ, ai lưu trữ, trong bao lâu, và nếu được áp dụng thì làm thế nào để việc kiểm tra lại hiệu quả khi thời gian caching hết hạn (caching policy expires). Khi máy chủ trả về hồi đáp, nó phải cung cấp Cache-Control và ETag headers:

  • Cache-Control định nghĩa cách thức và bao lâu một hồi đáp cụ thể được cache bởi trình duyệt và các bộ cache trung gian khác. Để biết thêm, xem caching với Cache-Control.
  • ETag cung cấp mã thông báo kiểm tra lại (revalidation token), được tự động gửi đi bởi trình duyệt để kiểm tra nếu nguồn thay đổi kể từ lần yêu cầu cuối. Để biết thêm, xem xác nhận hồi đáp cache với ETags.

Để xác định được chính sách caching tối ưu cho trang của bạn, hãy sử dụng các hướng dẫn sau:

Chúng tôi khuyên thời gian cache tối thiểu là một tuần và tốt nhất (preferably) là một năm cho nội dung tĩnh, hoặc các nội dung ít khi thay đổi. Nếu bạn cần kiểm soát chính xác khi tài nguyên không được xác nhận, chúng tôi khuyên sử dụng dấu vân tay URL – xem hủy và cập nhật hồi đáp cache ở liên kết trên.

Kinh nghiệm cá nhân với WordPress: Bạn có thể dễ dàng tạo hoặc tối ưu bộ nhớ đệm của trình duyệt thông qua chỉnh sửa file .htaccess. Nhiều plugin tạo bộ nhớ cache phổ biến cho WordPress như W3 Total Cache, WP Super Cache, WP Fastest Cache hoặc WP Rocket cho phép bạn làm điều này qua giao diện trực quan.

Nếu bạn không dùng các plugin trên mà chỉnh sửa thủ công, việc đó cũng không hề khó khăn đâu, bạn dễ dàng tìm các mẫu code chuẩn chỉnh dành cho máy chủ của mình, nó rất phổ biến trên mạng (trong đường link tối ưu bộ nhớ đệm của trình duyệt ở trên cũng có đoạn mã đó).

Cách thức tăng tốc này là điều rất đáng làm vì nó thực sự hiệu quả, rất đơn giản và không tốn kém gì.

5. Giảm thiểu tài nguyên (HTML, CSS và JavaScript)

Quy tắc này được kích hoạt khi PageSpeed Insights phát hiện ra một trong các nguồn của bạn có thể được giảm thiểu dung lượng.

Tổng quan

Giảm thiểu (minification) đề cập đến quá trình loại bỏ các dữ liệu không cần thiết (unnecessary) hoặc dư thừa (redundant) mà không làm ảnh hưởng đến việc trình duyệt xử lý nguồn nội dung – thí dụ như mã của bình luận, loại bỏ code không sử dụng, sử dụng các tên biến và tên hàm ngắn hơn và nhiều kỹ thuật khác nữa.

Xem tiền xử lý và tối ưu hóa theo ngữ cảnh cụ thể để biết thêm chi tiết.

Lời khuyên

Bạn nên giảm thiểu nguồn HTML, CSS và JavaScript:

  • Để giảm thiểu HTML, thử dùng HTMLMinifier
  • Để giảm thiểu CSS thử dụng CSSNano và csso
  • Để giảm thiểu JavaScript thử dùng UglifyJSClosure Compiler cũng rất hiệu quả. Bạn có thể tạo một quá trình xây dựng bằng cách sử dụng các công cụ này để giảm thiểu và thay đổi tên của các file phát triển và lưu chúng trong thư mục sản phẩm.

Ngoài ra, PageSpeed Module, tương hợp với cả máy chủ Apache hoặc Nginx sẽ tự động tối ưu trang của bạn, bao gồm cả việc tối thiểu hóa nguồn.

Kinh nghiệm cá nhân với WordPress: Bạn có thể thấy đây là cách thức rất dễ hiểu để cải thiện dung lượng của trang. Bạn đơn giản loại bỏ các dữ liệu không cần thiết. Hiện một trong các plugin rất mạnh trong công việc này của WordPress là Autoptimize kết hợp nhiều cách thức tối ưu trong đó có cả giảm thiểu dung lượng, nối file & tải không đồng bộ/trì hoãn JS. Ngoài ra thì nhiều plugin chuyên cho cache cũng có sẵn tính năng này, ví dụ như WP-Rocket.

Nếu giảm thiểu dung lượng không ảnh hưởng gì đến việc hiển thị thì nối file và tải không đồng bộ/trì hoãn CSS, JS có thể gây lỗi giao diện. Đây là nguyên nhân mà bạn cần kiểm tra kỹ lại trang sau khi dùng Autoptimize, đặc biệt là những trang có giao diện phức tạp, hoặc có nhiều tính năng. Trong đa số trường hợp tối ưu cho JS, CSS và HTML là cách thức rất an toàn.

Việc chỉnh sửa thủ công bằng các công cụ mà Google gợi ý ở trên cũng khá hay, nhưng đòi hỏi bạn phải tìm hiểu sâu hơn về WordPress chứ nó không đơn giản như cách dùng plugin.

Tuy nhiên nhược điểm của chỉnh sửa thủ công ngay cả khi bạn là người khá thành thạo đi nữa đó là nếu theme cập nhật thì bạn cũng phải cập nhật lại các thao tác thủ công của mình & điều này chẳng phải là công việc nhẹ nhàng, dễ nhớ hay thú vị gì. Dùng plugin thì không bị như thế, nó tự động làm cho bạn (tôi nghĩ có lẽ đó là lý do tại sao người phát triển plugin trên đặt tên của nó bắt đầu bằng tiền tố auto / tự động).

6. Tối ưu hóa ảnh

Quy tắc này được kích hoạt khi PageSpeed Insights phát hiện các hình ảnh trên trang của bạn có thể được tối ưu để giảm dung lượng (optimized to reduce their filesize) mà không ảnh hưởng đáng kể (without significantly impacting) đến chất lượng đồ họa (visual quality).

Tổng quan

Các hình ảnh thường chiếm phần lớn dung lượng tải trên trang. Hệ quả là: tối ưu hóa hình ảnh có thể tiết kiệm được rất nhiều dung lượng (băng thông) và nâng cao hiệu suất: càng ít dữ liệu trình duyệt phải tải xuống, thì sự cạnh tranh cho băng thông của khách hàng cũng ít theo và trình duyệt có thể tải và hiển thị nội dung trên màn hình nhanh hơn.

Lời khuyên

Tìm ra định dạng tối ưu (optimal format) và chiến lược tối ưu hóa hình ảnh của bạn có thể phải yêu cầu phân tích cẩn thận trên nhiều khía cạnh: kiểu dữ liệu được mã hóa, các định dạng hình ảnh có thể, cài đặt chất lượng, độ phân giải và nhiều điều khác nữa. Thêm vào đó, bạn cần xem xét liệu một số hình ảnh sẽ tốt nhất khi ở định dạng vector (SVG), một số hiệu ứng mong muốn có thể đạt được thông qua CSS, và làm thế nào phân phối các định dạng tài nguyên thích hợp cho từng thiết bị.

Tối ưu hóa cho tất cả các định dạng ảnh

Tối ưu hóa cho ảnh GIF, PNG và JPEG

GIF, PNG và JPEG là các định dạng chiếm đến 96% toàn bộ lưu lượng ảnh trên Internet. Do sự phổ biến của chúng, PageSpeed Insights cung cấp các lời khuyên tối ưa hóa cụ thể. Để thuận tiện cho bạn, bạn có thể tải các ảnh được tối ưu hóa trực tiếp từ PageSpeed Insights (được xử lý bằng thư viện tối ưu hình ảnh của modpagespeed.com).

Bạn cũng có thể sử dụng các công cụ chuyển đổi nhị phân của ImageMagick để thực hiện các tối ưu hóa tương tự – xem các ví dụ hướng dẫn bên dưới.

Nếu bạn sử dụng công cụ tối ưu hình ảnh của bên thứ ba, hãy ý thức rằng quá trình chuyển đổi có thể làm hình ảnh lớn hơn nếu các ảnh của bạn đã được tối ưu sẵn từ trước rất tốt rồi (tôi cũng từng chia sẻ kinh nghiệm này trong bài viết thử chuyển JPG & PNG sang WebP). Nếu tình huống này xảy ra, hãy sử dụng lại bản gốc của bạn.

GIF và PNG là định dạng không mất dữ liệu, vì vậy quá trình xử lý nén sẽ không gây bất kỳ ảnh hưởng nào đến chất lượng hình ảnh. Đối với hình ảnh tĩnh, PNG đạt được tỷ lệ nén tốt hơn với chất lượng hình ảnh tốt hơn. Với hình ảnh động, xem xét sử dụng video thay vì GIF để nhận được khả năng nén tốt hơn.

  • Luôn luôn chuyển đổi GIF sang PNG trừ khi ảnh gốc là ảnh động hoặc rất nhỏ (ít hơn vài trăm bytes).
  • Với cả ảnh GIF và PNG, loại bỏ kênh alpha nếu tất cả các pixel không rõ ràng.

Lấy thí dụ, bạn có thể sử dụng chuyển đổi nhị phân để tối ưu ảnh GIF và PNG với các lệnh sau (các thông số bên trong dấu ngoặc là tùy chọn):

convert INPUT.gif_or_png -strip [-resize WxH] [-alpha Remove] OUTPUT.png

cuppa.png (1,763 Bytes)

convert cuppa.png -strip cuppa_converted.png

cuppa_converted.png (856 Bytes) – giảm được hơn 50% dung lượng

JPEG là định dạng mất dữ liệu. Quá trình nén sẽ loại bỏ các chi tiết của bức hình, nhưng tỷ lệ nén có thể cao hơn 10 lần so với GIF hoặc PNG.

  • Giảm chất lượng xuống 85 nếu dung lượng sau vẫn cao hơn. Với chất lượng cao hơn 85, dung lượng hình ảnh tăng lên nhanh chóng, trong khi chất lượng không cải thiện bao nhiêu.
  • Giảm lấy mẫu Chroma xuống 4:2:0, bởi vì hệ thống thị giác của con người kém nhạy cảm với màu sắc khi so sánh với độ sáng (lumniance).
  • Sử dụng định dạng progressive cho ảnh trên 10KB. Ảnh JPEG progressive thường có tỷ lện nén cao hơn so với JPEG baseline cho các ảnh lớn, và có lợi ích trong việc hiển thị dần dần (hiển thị toàn bộ ảnh mờ sau đó rõ dần ra).[2]
  • Sử dụng không gian màu xám (grayscale color space) nếu ảnh là đen trắng.

[2]: Dưới đây là ví dụ về hai trường hợp so sánh ảnh tải theo kiểu baseline & progressive:

Ảnh tải theo kiểu baseline – minh họa của trang adavu.com
Ảnh tải theo kiểu progressive – minh họa của trang adavu.com

Lấy ví dụ, bạn có thể sử dụng chuyển đổi nhị phân để tối ưu các ảnh JPEG với các lệnh sau (các tham số bên trong dấu ngoặc vuông là tùy chọn):

convert INPUT.jpg -sampling-factor 4:2:0 -strip [-resize WxH] [-quality N] [-interlace JPEG] [-colorspace Gray/RGB] OUTPUT.jpg

puzzle.jpg (13,501 Bytes)

convert puzzle.jpg -sampling-factor 4:2:0 -strip -quality 85 -interlace JPEG -colorspace RGB puzzle_converted.jpg

puzzle_converted.jpg (4,654 Bytes)

Kinh nghiệm cá nhân với WordPress: Cải thiện tốc độ tải trang bằng cách sử dụng ảnh thông minh & tối ưu là cách thức rất hiệu quả. Tuy nhiên đây là một trong những việc cần chuyên môn nhiều nhất so với các biện pháp khác.

Mặc dù có khá nhiều plugin hỗ trợ cho WordPress trong việc tối ưu hóa ảnh, có vài điều điều bạn cần lưu ý:

  • Việc quan trọng nhất trong việc tối ưu hóa dung lượng ảnh là bạn biết bản thân thực sự cần chất lượng ảnh đến đâu. Đánh đổi chất lượng dư thừa là cần thiết nhưng nếu quá ham giảm dung lượng thấp bạn có thể biến trang web trông rất thiếu chuyên nghiệp.
  • Nếu số lượng ảnh tối ưu không lớn thì các plugin dành cho WordPress rất dễ tìm hàng miễn phí nhưng nếu số lượng ảnh lớn đa số đều thu phí, mặc dù số tiền không lớn (10 USD / 10 ngàn ảnh, hoặc 1GB).
  • Nếu không cẩn thận bạn sẽ làm chất lượng ảnh của trang giảm đi đáng kể hoặc làm dung lượng của ảnh tăng lên!
  • Nên thận trọng với nén ảnh mất chất lượng.
  • Ảnh định dạng mới như WebP (cũng do Google phát triển) rất đáng tham khảo & tìm hiểu kỹ.

7. Tối ưu hóa việc phân phối CSS

Quy tắc này kích hoạt khi PageSpeed Insights phát hiện (detects) trang bị chặn hiển thị có nguyên nhân từ việc chứa các stylesheet ngoài, điều này làm trì hoãn thời gian trang hiển thị nội dung phần đầu (còn gọi là CSS chặn hiển thị).

Tổng quan

Trước khi trình duyệt có thể hiển thị nội dung nó buộc phải xử lý tất cả thông tin style và layout cho trang hiện tại. Hệ quả là: trình duyệt sẽ chặn hiển thị (block rendering) cho đến khi các file stylesheet ngoài được tải và xử lý xong (downloaded and processed), điều này có thể yêu cầu nhiều vòng lặp (roundtrips) và trì hoãn lần hiển thị trang đầu tiên. Xêm thêm cấu trúc cây của quá trình hiển thị, layout và tạo trang (render-tree construction, layout, and paint) hoặc cách trình duyệt tải trang web của bạn (tiếng Việt) để biết thêm về quá trình xử lý hiển thị trang, và xem thêm render blocking CSS để có các mẹo mở chặn (unblock) hiển thị và nâng cao khả năng phân phối CSS.

Lời khuyên

Nếu file CSS bên ngoài nhỏ, bạn có thể chèn nó trực tiếp vào tài liệu HTML (inline), điều này được gọi là nội tuyến (khác với nội dòng – nội dòng là chèn thẳng vào thẻ HTML cụ thể). CSS nội tuyến nhỏ theo cách này cho phép trình duyệt xử lý với việc xuất trang tốt hơn. Nên nhớ rằng nếu file CSS lớn, để CSS nội tuyến có thể là nguyên nhân khiến PageSpeed Insights cảnh báo (warn) phần nội dung đầu (above-the-fold) [1] của trang quá lớn thông qua Ưu tiên nội dung hiển thị (prioritize visible content / được nói chi tiết trong phần 8 – ngay sau phần này). Trong trường hợp file CSS lớn, bạn sẽ cần xác định và đặt nội tuyến CSS cần thiết cho việc xử lý hiển thị trang ở phần đầu (critical CSS) và trì hoãn tải cho các style còn lại cho đến khi nội dung phần đầu được tải xong.

[1]: Above the fold: chỉ đến phần nội dung hiển thị ra bên ngoài màn hình đầu tiên khi người dùng tải trang, họ không phải cuộn chuột để xem nội dung thuộc Above the fold. Xem thêm bài viết nội dung thuộc màn hình đầu tiên để thấy ưu thế của phần nội dung này.

Ví dụ về việc đặt nội tuyến file CSS nhỏ

Lấy ví dụ, nếu tài liệu HTML giống như thế này:

<html>
  <head>
    <link rel="stylesheet" href="small.css">
  </head>
  <body>
    <div class="blue yellow big bold">
      Hello, world!
    </div>
  </body>
</html>

Và file nguồn small.css là như này:

.yellow {background-color: yellow;}
  .blue {color: blue;}
  .big { font-size: 8em; }
  .bold { font-weight: bold; }

Thì bạn có thể đặt nội tuyến CSS như bên dưới:

<html>
  <head>
    <style>
      .yellow {background-color: yellow;}
      .blue {color: blue;}
      .big { font-size: 8em; }
      .bold { font-weight: bold; }
    </style>
    </head>
  <body>
    <div class="blue yellow big bold">
      Hello, world!
    </div>
  </body>
</html>

Điều này sẽ loại bỏ yêu cầu của trình duyệt tới small.css bằng cách đặt CSS nội tuyến trong tài liệu HTML.

Hoặc cách này, phức tạp hơn:

<html>
  <head>
    <style>
      .blue{color:blue;}
    </style>
    </head>
  <body>
    <div class="blue">
      Hello, world!
    </div>
    <noscript id="deferred-styles">
      <link rel="stylesheet" type="text/css" href="small.css"/>
    </noscript>
    <script>
      var loadDeferredStyles = function() {
        var addStylesNode = document.getElementById("deferred-styles");
        var replacement = document.createElement("div");
        replacement.innerHTML = addStylesNode.textContent;
        document.body.appendChild(replacement)
        addStylesNode.parentElement.removeChild(addStylesNode);
      };
      var raf = requestAnimationFrame || mozRequestAnimationFrame ||
          webkitRequestAnimationFrame || msRequestAnimationFrame;
      if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); });
      else window.addEventListener('load', loadDeferredStyles);
    </script>
  </body>
</html>

Bạn có thể thấy việc chuyển đổi này bao gồm việc xác định nội dung CSS nào quan trọng (critical) / không quan trọng (non-critical). Rồi sau đó đặt nội tuyến CSS quan trọng và trì hoãn tải các file CSS không quan trọng. Phương pháp này có thể được làm tự động bằng modules PageSpeed Optimization cho nginx, apache, IIS, ATS, và Open Lightspeed, khi bạn bật bộ lọc (filter) prioritize_critical_css (ưu tiên các CSS quan trọng – hay tổng quan hơn được gọi là tuyến hiển thị quan trọng).

Xem thêm hàm loadCSS để giúp bạn tải CSS không đồng bộ, nó có thể làm việc với Critical, một công cụ cho phép xuất ra file CSS quan trọng từ trang web.

Các định kiểu quan trọng cần cho việc định kiểu nội dung phần đầu nên được đưa nội tuyến và áp dụng lên tài liệu ngay lập tức (immediately). Bản đầy đủ của small.css sẽ được tải sau khi hiển thị xong phần đầu của trang. Style của nó được áp dụng lên trang một khi nó được tải xong, và không chặn render của phần nội dung quan trọng (critical content).

Lưu ý là các nền tảng web sẽ sớm hỗ trợ tải stylesheets theo cách thức (manner) không-chặn-hiển-thị, và không phải nhờ đến (resort) việc dùng JavaScript nữa, sử dụng HTML Imports.

Đừng đặt nội dòng lượng lớn dữ liệu URIs

Hãy cẩn thận khi đặt nội dòng dữ liệu URIs trong file CSS. Trong khi lựa chọn sử dụng dữ liệu nhỏ URIs trong CSS của bạn có thể có ý nghĩa, đặt nội dòng lượng lớn dữ liệu URIs có thể là nguyên nhân làm dung lượng của CSS phần đầu trang lớn thêm, cái sẽ làm chậm thời gian render trang.

Đừng đặt thuộc tính CSS trong dòng

Đặt thuộc tính CSS trong dòng trên các phần tử HTML (thí dụ: <p style=”…”>) phải tránh khi có thể (should be avoided where possible), bởi nó thường dẫn đến các đoạn mã lặp lại không cần thiết. Thêm nữa, CSS trong dòng trên phần tử HTML đã bị chặn theo mặc định với Chính sách Bảo mật Nội dung (CSP).

Kinh nghiệm cá nhân với WordPress: Phương pháp trên rõ ràng không dành cho dân không chuyên với việc phải xác định style quan trọng, rồi phải tách mã CSS ra làm hai phần để tối ưu. Hy vọng các trình duyệt sớm đưa vào tính năng mà nó vừa khoe: non-render-blocking để việc tối ưu này thành mặc định.

8. Ưu tiên nội dung hiển thị

Quy tắc này được kích hoạt khi PageSpeed Insight phát hiện thấy có thêm các vòng lặp yêu cầu trong quá trình hiển thị phần nội dung thuộc màn hình đầu tiên (above the fold content) của trang.

Tổng quan

Nếu dung lượng dữ liệu yêu cầu vượt quá (exceeds) ngưỡng nghẽn ban đầu (thông thường là 14,6KB đã nén), nó sẽ yêu cầu thêm vòng lặp giữa máy chủ và trình duyệt của người dùng. Với người dùng trên mạng có độ trễ cao (high latencies) như mạng điện thoại, điều này có thể là nguyên nhân gây ảnh hưởng đáng kể đến độ trễ của việc tải trang.

Lời Khuyên

Để trang tải nhanh hơn, cần giới hạn dung lượng dữ liệu (mã đánh dấu HTML, các hình ảnh, CSS, JavaScript) cần thiết để render phần nội dung đầu của trang. Có một số cách để làm điều đó:

  • Cấu trúc HTML để tải nội dung quan trọng, ở phần đầu trước
  • Giảm dung lượng dữ liệu sử dụng

Cấu trúc HTML để tải nội dung quan trọng, ở phần đầu trước

Tải phần nội dung chính (main content) trang của bạn trước. Cấu trúc trang của bạn để các phản hồi đầu tiên (initial response) từ máy chủ gửi dữ liệu cần thiết để render phần quan trọng của trang ngay lập tức và trì hoãn phần còn lại (defer the rest). Điều này có nghĩa là bạn phải chia CSS của bạn thành hai phần: phần inline để phản hồi lại định dạng cho phần ATF (viết tắt của Above The Fold) của nội dung (còn được gọi là critical CSS), và phần còn lại có thể được trì hoãn.

Xem xét các ví dụ sau về cách trang của bạn có thể cấu trúc lại (restructured) để tải nhanh hơn:

  • Nếu trang HTML tải widget của bên thứ ba trước khi tải nội dung chính, hãy thay đổi thứ tự để nó tải nội dung chính trước.
  • Nếu trang của bạn sử dụng thiết kế hai cột (two-column design) với sidebar điều hướng (sidebar navigation) và bài viết, nhưng trang HTML của bạn tải sidebar trước bài viết, hãy xem xét việc tải nội dung bài viết trước.

Giảm dung lượng dữ liệu sử dụng

Một khi trang của bạn được thiết kế lại để hoạt động tốt trên nhiều thiết bị khác nhau và ưu tiên tải nội dung quan trọng trước, sử dụng các kỹ thuật bên dưới để giảm lượng dữ liệu yêu cầu cho việc render trang của bạn:

  • Giảm thiểu nguồn: HTML, CSS, và JavaScript có thể được giảm thiểu bằng cách loại bỏ các khoảng trắng (whitespace) và comments không cần thiết (unnecessary). Kỹ thuật tối ưu hóa gia tăng còn có thể áp dụng thông qua việc dùng các công cụ để thay đổi tên biến trong mã nguồn của bạn. (đã nói ở phần 5)
  • Xem xét việc sử dụng CSS để thay thế hình ảnh khi có thể.
  • Bật nén. (đã nói ở phần 2)

9. Loại bỏ JavaScript chặn hiển thị

Quy tắc này kích hoạt khi PageSpeed Insights phát hiện trang HTML của bạn tham chiếu đến file JavaScript bên ngoài chặn hiển thị nội dung đầu trang (nội dung nằm trong màn hình đầu tiên).

Tổng quan

Trước khi trình duyệt có thể hiển thị trang nó xây dựng cây DOM bằng cách phân tích (parsing) mã đánh dấu HTML. Trong suốt quá trình này, bất cứ khi nào trình xử lý (parser) bắt gặp script, nó phải dừng lại và thực thi nó trước khi có thể tiếp tục xử lý với HTML. Trong trường hợp mã script ngoài, trình xử lý buộc phải chờ nguồn tải xong, điều này có thể tạo thêm một hoặc nhiều truy vấn lặp và trì hoãn thời gian hiển thị phần đầu trang. Xem Thêm tương tác với JavaScript để hiểu hơn cách JavaScript ảnh hưởng đến hiển thị như thế nào.

Lời khuyên

Bạn cần phải tránh và tối thiểu hóa việc sử dụng JavaScript chặn hiển thị, đặc biệt là các script ngoại tuyến bắt buộc phải tải (fetched) trước khi được thực thi (executed). Script cần thiết để render nội dung trang có thể đặt nội tuyến để tránh gia tăng các yêu cầu mạng, dầu vậy nội dung nội tuyến cần nhỏ và phải thực thi nhanh để có được hiệu năng tốt. Scripts không quan trọng để hiển thị nội dung đầu trang nên tải không đồng bộ hoặc trì hoãn cho đến khi nội dung đầu trang hiển thị xong xuôi. Nên nhớ là để nâng cao thời gian tải, bạn phải thực hiện tối ưu phân phối CSS nữa.

JavaScript nội tuyến

Script ngoài chặn hiển thị bắt buộc trình duyệt phải đợi JavaScript tải xong, điều này sẽ tạo thêm nhiều vòng lặp mạng trước khi trang có thể được hiển thị. Nếu mã script ngoài là nhỏ, bạn có thể đặt nội tuyến trực tiếp đoạn mã trong tài liệu HTML và tránh được độ trễ của việc truy vấn mạng (giống kiểu với CSS). Lấy ví dụ, nếu tài liệu HTML giống như thế này:

<html>
  <head>
    <script type="text/javascript" src="small.js"></script>
  </head>
  <body>
    <div>
      Hello, world!
    </div>
  </body>
</html>

Và nguồn small.js giống như này:

  /* một đoạn mã JavaScript nhỏ */

Sau đó bạn có thể đặt nội tuyến mã như sau:

<html>
  <head>
    <script type="text/javascript">
      /* một đoạn mã JavaScript nhỏ */
    </script>
  </head>
  <body>
    <div>
      Hello, world!
    </div>
  </body>
</html>

Nội dung script nội tuyến giúp loại bỏ truy vấn ngoài đến file small.js và cho phép trình duyệt phân phối thời gian nhanh hơn cho việc hiển thị nội dung đầu trang. Dầu vậy, lưu ý là nội tuyến cũng có thể làm tăng kích cỡ tài liệu HTML và cùng một đoạn mã có thể cần đặt nội tuyến qua nhiều trang. Hệ quả, bạn chỉ nên đặt nội tuyến script nhỏ đế phân phối hiệu suất tối ưu cho trang.

Làm JavaScript tải không đồng bộ

Theo mặc định JavaScript ngăn chặn cấu trúc DOM và vì vậy trì hoãn thời gian hiển thị lần đầu (the time to first render). Để ngăn JavaScript chặn trình xử lý, chúng tôi khuyên bạn sử dụng thuộc tính async (không đồng bộ) trong HTML với các mã script ngoài (external scripts). Lấy thí dụ:

<script async src=”my.js”>

Xem thêm Chặn trình xử lý và JavaScript không đồng bộ để hiểu thêm về script không đồng bộ. Lưu ý là mã không đồng bộ không đảm bảo (guaranteed) thực hiện theo thứ tự chỉ định và không nên sử dụng document.write. Mã script phụ thuộc vào thứ tự thực thi (execution order) hoặc cần truy cập hoặc thay đổi (access or modify) DOM hoặc CSSDOM của trang có thể cần viết lại (rewritten) để khắc phục các khó khăn này.

Trì hoãn việc tải JavaScript

Việc tải và thực thi mã script không cần thiết cho việc hiển thị nội dung đầu trang (initial page render/tức là trang nằm trong màn hình đầu tiên) có thể được hoãn lại cho đến khi trang ban đầu được hiển thị hoặc các phần quan trọng khác (other critical parts) của trang được tải xong. Làm thế giúp giảm tranh chấp tài nguyên (reduce resource contention) và cải thiện hiệu suất (improve performance).

Các câu hỏi thường gặp (FAQ)

Nếu tôi sử dụng thư viện JavaScript như jQuery thì sao?

Nhiều thư viện JavaScript như jQuery, được sử dụng để cải tiến trang với việc thêm tương tác, hình động, và các hiệu ứng khác. Dầu vậy, nhiều hành vi có thể được thêm vào an toàn sau khi nội dung đầu trang được hiển thị đầy đủ. Bạn nên thử nghiệm (investigate) với cả tải không đồng bộ hoặc trì hoãn tải để xem có vấn đề gì xảy ra hay không.

Nếu tôi sử dụng JavaScript framework để xây dựng trang?

Nếu nội dung của trang được xây dựng bởi JavaScript phía máy khách, bạn phải xem xét đặt nội tuyến các module JavaScript thích hợp để tránh gia tăng vòng lặp mạng (extra network roundtrips). Tương tự như vậy, tận dụng sử dụng render phía máy chủ có thể tác động đáng kể đến hiệu suất tải trang lần đầu: render JavaScript templates trên máy chủ để phân phối render lần đầu nhanh hơn, và sau đó sử dụng templating phía máy khách một khi trang được tải xong. Để có thêm thông tin về việc rendering phía máy chủ (server-side rendering), xem video này: http://youtu.be/VKTWdaupft0?t=14m28s

Kinh nghiệm cá nhân với WordPress: Đến trước khi tôi sử dụng PageSpeed Insights để nhận các lời khuyên về cải thiện tốc độ thì tôi chưa bao giờ để ý đến việc sử dụng JavaScript không đồng bộ cả.

Xét về mặt kỹ thuật việc điều chỉnh thủ công để đạt chuẩn yêu cầu này không khó vì bạn chỉ cần thêm thuộc tính vào. Các plugin để chuyển các đoạn mã về không đồng bộ cũng dễ tìm được, thí dụ như Async JavaScript. Vấn đề quan trọng là bạn cần biết được việc chuyển như vậy ảnh hưởng đến đâu các chức năng của trang? Và điều chỉnh lại về trạng thái cũ khi cần. Nhiều plugin cache cũng tích hợp sẵn tính năng tải không đồng bộ này.

Theo chủ trang Varvy thì tải không đồng bộ (Async) không tốt bằng trì hoãn tải.

10. Sử dụng mã Script không đồng bộ

Quy tắc này kích hoạt khi PageSpeed Insights phát hiện bạn sử dụng phiên bản đồng bộ cho các script (kịch bản) thay vì sử dụng phiên bản không đồng bộ.

Tổng quan

Sử dụng mã không đồng bộ đồng nghĩa với việc trang của bạn có thể render nhanh hơn. Thay vì ép (forcing) người dùng đợi script tải xong trước khi trang được render thì bằng cách triển khai “mã không đồng bộ” script có thể được tải dưới nền.

Mặc dù hầu hết script mặc định ban đầu là đồng bộ (synchronous), các phiên bản mới của nó được thiết kế để tải không đồng bộ (asynchronously).

Lời khuyên

Để chắc chắn bạn sử dụng mã kịch bản (script) không đồng bộ. Các script phổ biến dưới đây hỗ trợ tải không đồng bộ:

  • BuySellAds (s3.buysellads.com/ac/bsa.js) : blog post – mặc định là async
  • ChartBeat (static.chartbeat.com/js/chartbeat.js) : docblog post – mặc định là async
  • Clicky (static.getclicky.com/js) : blog post
  • Disqus (disqus.com/count.js, disqus.com/embed.js) : docblog post – mặc định là async
  • Facebook (connect.facebook.net/.../all.js) : docblog post – mặc định là async
  • Google AdSense (pagead2.googlesyndication.com/pagead/show_ads.js) : docblog post
  • Google Analytics (google-analytics.com/ga.js) : docblog post – mặc định là async
  • Google DFP GPT (www.googletagservices.com/tag/js/gpt.js) : doc
  • Google Plus (apis.google.com/js/plusone.js) : docblog post
  • New Relic (d7p9czrvs14ne.cloudfront.net/11/eum/rum.js) : doc – mặc định là async
  • Pinterest (assets.pinterest.com/js/pinit.js) : doc
  • Shareaholic : doc – mặc định là async
  • ShareThis (w.sharethis.com/button/buttons.js) : doc
  • ScorecardResearch/Comscore (b.scorecardresearch.com/beacon.js) : doc – mặc định là async
  • StumbleUpon (platform.stumbleupon.com/.../widgets.js)
  • Quantcast (quantserve.com/quant.js) : doc – mặc định là async
  • Twitter (platform.twitter.com/widgets.js) : doc – mặc định là async
  • Tynt (cdn.tynt.com/tc.js)
  • Yandex (mc.yandex.ru/metrika/watch.js)

Lưu ý: Chúng tôi nỗ lực hết sức để giữ (best effort to keep) danh sách trên được cập nhật (up-to-date). Dầu vậy, nếu bạn có câu hỏi đặc biệt nào về JavaScript của bên thứ ba hoặc bạn không tìm được phiên bản không đồng bộ (async) của họ ở đây, chúng tôi khuyến khích (encourage) bạn liên hệ trực tiếp với nhà cung cấp.

Chúng tôi có thêm thông tin giải thích tại sao loại bỏ JavaScript chặn hiển thị có thể tăng tốc độ tải trang của bạn (nó ở ngay phần 9 nếu bạn để ý!)

Kinh nghiệm cá nhân với WordPress: Khi mới đọc đến phần 9, tôi đã nghĩ phải điều chỉnh lại các đoạn mã JavaScript của Google Analystics và Facebook Fanpage thôi, nhưng tôi lo thừa rồi. Các hãng công nghệ lớn đều ý thức được ý nghĩa của việc tải không đồng bộ nên các đoạn mã của họ đã mặc định như thế rồi.

(Dịch từ các bài viết thuộc phần Speed Rules – PageSpeed Insights Rules – Make the Web Faster – Google Developers)

Related Post

Leave a Comment