XxL's Góc riêng

Tôi là XXL – Người lớn nhất quả đất

15 bước tăng (thần) tốc website chạy bằng wordpress

Với nhiều năm vọc vạch cái mã nguồn này (dưới con mắt và đôi tay của một thằng học kinh tế) mình xin chia sẻ những điều mình rút ra được và sẵn sàng nhận feedback/discussion ngay bên dưới nhé.

Có rất nhiều lý do khiến cho website của bạn chạy chậm, load như rùa all the time:

  • Hosting/Server tệ
  • Ảnh trong media quá lớn và không được xử lý
  • Chạy cùng lúc quá nhiều plugins
  • Có quá nhiều widgets và các thành phần màu mè
  • Nhiều mã javascripts chặn hiển thị
  • Quá nhiều request HTTP
  • Chèn thẳng vào source các đoạn JS/CSS dài ơi là dài
  • Quá nhiều các phần tử DOM (nôm na là các thẻ HTML)
  • JS/CSS không được nén
  • Không nén dữ liệu truyền tải
  • Font chữ đa dạng…

Cách đơn giản nhất để tìm ra nguyên nhân gây chậm website của bạn là công cụ Gtmetrix.com hoặc PageSpeed Insights.

Chưa dùng bao giờ? Thử 1 lần sẽ biết.

Khi đã xác định nguyên nhân, ta đi tìm giải pháp. Bên dưới mình sẽ liệt kê các bước mà bạn sẽ gặp sau khi phân tích ở trên để khắc phục nhé.

Nén hình ảnh

Đây là nguyên nhân lớn nhất, rõ ràng nhất, hiển nhiên nhất khi bạn upload hàng ngàn file (đối với 1 shop trung bình) mà mỗi file ảnh chiếm dung lượng từ 300KB – 1MB.

Để hiển thị tốt trên website, tức là đủ độ nét, kích thước tiêu chuẩn, thì 1 tấm ảnh chỉ nên nằm dưới mức 150KB. Và trong bài viết này của mình, các hình ảnh minh họa chỉ luôn <25KB (40 file mới được 1MB)!!!

WHAT? ARE U FKING KIDDING MEY?

No no. I’m Serious!!!! Listen!

Có nhiều yếu tố làm cho file ảnh nó nặng

  1. Độ phân giải cao.
    Ví dụ 1200 x 800 px. Vấn đề là bạn có cần nó to như thế không? Người xem có cần phải zoom vào chi tiết nhỏ để xem không?
  2. Định dạng file chưa tối ưu.
    1 file ảnh chụp bạn tự sướng nếu lưu dạng .JPG thì ~ 250KB
    còn lưu dạng .PNG thì ~600KB
    và mắt của bạn không thấy được sự khác biệt giữa 2 tấm ảnh này @@

Để giải quyết nhanh gọn, ta có thể dùng plugin TinyPNG hoặc WP Smush it. Mình thích dùng Smush It hơn.

Sau khi sử dụng, bạn sẽ tiết kiệm được từ 20 – 50%, thậm chí là 70%. Một dung lượng kha khá được giải phóng khỏi hosting của bạn!

Thay đổi kích thước hình ảnh

Khi bạn upload 1 hình ảnh lên media, wordpress tự động tạo thêm 2 file nữa với kích thước: 150 x 150 px và 300 x 300 px.

Việc sử dụng những hình ảnh này khi bạn cần hiển thị nó với kích thước nhỏ hơn, thay vì sử dụng file gốc bạn up lên là điều mà mình muốn nói ở đây.

Tối kỵ dùng file lớn và sử dụng css để thu nhỏ nó lại

đại loại kiểu

<img src="mybigimage_verybig.jpg" style="width:100px;height:100px" />

Wow!!! Tuyệt đấy, khi đó, bạn sẽ cần thuê một người như mình để tối ưu giúp bạn > Lợi cả đôi đường!

Thay vào đó, ta sử dụng file mà wordpress tạo ra như trên mình trình bày bằng cách

  • thêm đuôi vào sau đường dẫn file gốc. Ví dụ:
<img src="mybigimage_verybig-150x150.jpg" style="width:100px;height:100px" />

hoặc sử dụng tùy chọn ngay trong chức năng Add Media.

scale-img
Sử dụng tùy chọn kích thước trong Add media. (file ảnh này nặng 4KB thôi)

Nếu themes sử dụng hình ảnh kích thước khác?

Trước tiên bạn phải xác định chính xác kích thước hiển thị trong themes bằng cách xem trên công cụ của chrome/firefox:

dim-img
File ảnh mình họa này nặng 14KB

Như đoạn khoanh đỏ, ta có được kích thước 260 x 163. Để wordpress tự động tạo 1 phiên bản ảnh có kích thước này, ta thêm đoạn mã sau vào file functions.php của themes nhé

add_image_size( 'unique_name', 260, 163, true );

Nhưng chỉ có tác dụng đối với các ảnh được up lên từ bây giờ về sau, để tạo phiên bản ảnh kích thước này cho các file đã có sẵn, ta dùng plugin wp regenerate thumbnails.

Chống ăn cắp băng thông

Một hành vi không lạ lẫm khi các blog, website xào bài lại của nhau nhưng không quên sử dụng luôn hình ảnh đang nằm trên hosting của bạn.

Để chống việc này (tiếng Anh là Hotlinking cho các bạn google), ta thêm đoạn mã sau vào file .htaccess ở thư mục chứa website:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourdomain.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ - [NC,F,L]

Nhớ thay đoạn in màu bằng website của bạn.

Giảm tối thiểu số lượng Plugins và Widgets

Nếu có một plugin bạn không sử dụng, hãy xóa nó đi thay vì để trạng thái Deactived vì khi đó, nó vẫn chiếm 1 phần trong database và 1 loạt đoạn mã khác trong mã nguồn của bạn.

Tương tự là Widgets.

Ta nên hiểu là bất kì thứ gì thêm vào trong website của bạn sẽ tạo thêm nhiều truy xuất vào database hơn và nhiều dòng lệnh trên máy chủ hơn ~ càng mất nhiều thời gian để website của bạn hiển thị hoàn tất.

Tối ưu scripts trên source

Javascript là 1 trong những tài nguyên chặn trang, có nghĩa là việc hiển thị HTML có thể bị chặn hay làm chậm bởi Javascript. Khi trình duyệt đọc đến một tag <script>, bất kể là inline (nhúng trực tiếp) hay là external file (nhúng qua một file khác), quá trình parse sẽ tạm dừng để tải script đó về và thực thi đã.

Nếu chúng ta load nhiều file Javascript trên trang, nó làm tăng thời gian load trang mặc dù có thể việc hiển thị html ở trang không thực sự phụ thuộc vào những file javascript đó.

Và may mắn thay, thẻ <script> có 2 thuộc tính, đó là async và defer, cho phép chúng ta kiểm soát và load những file này theo ý muốn, tránh chặn quá trình load trang.

Sử dụng ASYNC cho javascripts

<script async src="script.js">

Với thẻ script có thuộc tính async, khi quá trình parse (tải/đọc/dịch) html gặp phải script này, nó sẽ vẫn tiếp tục parse html cho đến khi script này được download xong, thì quá trình parse html mới tạm dừng để execute những code script này, sau đó lại tiếp tiếp quá trình parse html.

Sử dụng DEFER cho javascripts

<script defer src="script.js">

Với thẻ script có thuộc tính defer, quá trình parse  html sẽ không bị dừng lại, quá trình download các script file được tiến hành song song, và cuối cùng thì sẽ execute những script code này khi html đã parse xong.

WAIT! Tại sao không đưa tất cả scripts xuống cuối trang như một vài TUT khác đã hướng dẫn?

Bình tĩnh, chuyện đâu còn có đó! Thịt chó còn có mắm tôm mà.

Nếu bạn là một người am hiểu về web development, thì bạn sẽ biết scripts cần được đọc và thực thi khi nào, ở đâu. Đôi khi scripts này cần đặt ngay sau phần tử <div id=”excute-js-here”>, và khi bạn đưa scripts xuống cuối cùng, nó ĐÉO CHẠY :)))) OK?

Và cuối cùng về phần này, bạn có 2 option:

  • JS to footer (tên plugin đấy): để tự động đưa tất cả các scripts xuống cuối trang và nếu website vẫn hoạt động ok trên tất cả các trang, good news, bạn không cần đọc dòng bên dưới.
  • Sử dụng thuộc tính defer/async cho tag <scripts>.

Minify CSS và Javascript

Minify (thu gọn) file CSS và JS bằng cách nó xóa các ký tự không cần thiết trong file như: 2 dấu cách liên tiếp, dấu xuống dòng, dấu thụt dòng (tab), các chú thích… Do đó, file sẽ nhẹ hơn khoảng đâu đó 10 – 15%.

Công cụ để Minify CSS/Javascript

Cứ google CSS minifier hoặc JS minifier sẽ có hàng tá website hỗ trợ bạn. Chỉ cần nhập nội dung file gốc vào, nó sẽ output ra một file đã minified!

!! Hãy nhớ backup lại 1 file chưa minified để tiện edit sau này vì khi đã minified, file của bạn sẽ rối loạn hơn nhiều.

css-mini
Filesize: 22KB

Nếu bạn sử dụng Cloudflare, bạn chỉ cần tick và xong, cloudflare sẽ tự minify cho bạn từ css, js, html luôn

mini-clf
Filesize: 5.6KB

Bật Keep-Alive

Trước tiên, ta cần hiểu Keep-Alive là gì?

Mỗi khi trình duyệt request một file từ server, sẽ tạo ra 1 tương tác nhỏ giữa trình duyệt và server. Khi đó, server sẽ phát một tín hiệu OK cho file khi được trình duyệt request. Keep-alive có tác dụng làm cho server chỉ cần báo OK một lần duy nhất thay vì cứ mỗi file đều phải báo khi trình duyệt load hàng loạt file từ css, js, html, jpg…

Check xem server đã bật Keep-alive chưa

Bằng tool này: https://www.giftofspeed.com/check-keep-alive/

Nhập website của bạn vào để nó check, nếu nó báo

Connection: Keep-Alive

là OK, còn nếu

Connection: close

nghĩa là không có kết nối dạng Keep-alive, bạn cần thực hiện bật keep-alive bằng cách thêm đoạn mã sau vào file .htaccess

<ifModule mod_headers.c>
    Header set Connection keep-alive
</ifModule>

Thế là xong!

Xóa một số tag không cần thiết của WordPress

Hàm wp_head() khi thực thi sẽ tạo ra kha khá tag không cần thiết như

  1. # XFN (XHTML Friends Network)
  2. # wlwmanifest (Windows Live Writer) link.
  3. # Comments Feed
  4. # WordPress Version Generator
  5. # XML RPC
  6. # Post Shortlink
  7. # RSS Feed Links

Để loại bỏ phần nội dung này, ta chỉ cần thêm đoạn mã sau vào file functions.php (trong thư mục themes)

remove_action('wp_head', 'rsd_link'); //removes EditURI/RSD (Really Simple Discovery) link.
remove_action('wp_head', 'wlwmanifest_link'); //removes wlwmanifest (Windows Live Writer) link.
remove_action('wp_head', 'wp_generator'); //removes meta name generator.
remove_action('wp_head', 'wp_shortlink_wp_head'); //removes shortlink.
remove_action('wp_head', 'feed_links', 2 );  //removes automatic feed links.

Xong.

Bật nén Gzip

Nghĩa là server trước khi cho trình duyệt đọc dữ liệu, server sẽ thực hiện nén lại và trình duyệt nhận được, sẽ giải nén ra và đọc dữ liệu đó.

Mục đích là giảm dung lượng dữ liệu truyền tải, tuy có mất thêm 1 chút thời gian để zip và unzip, nhưng nó không đáng kể so với lượng dữ liệu tiết kiệm được.

Trung bình một file html 400KB sau khi gzip sẽ chỉ còn 40KB (giảm đến 90%).

Để bật nén gzip, ta chỉ cần thêm đoạn mã sau vào đầu file header.php (trong thư mục themes)

<? ob_start("ob_gzhandler"); ?>

Có một vài server không tương thích với đoạn code trên, bạn có thể sử dụng phương án thay thế: Thêm đoạn mã sau vào cuối file .htaccess

<IfModule mod_deflate.c>
 AddOutputFilterByType DEFLATE text/plain
 AddOutputFilterByType DEFLATE text/html
 AddOutputFilterByType DEFLATE text/xml
 AddOutputFilterByType DEFLATE text/css
 AddOutputFilterByType DEFLATE text/javascript
 AddOutputFilterByType DEFLATE image/svg+xml
 AddOutputFilterByType DEFLATE image/x-icon
 AddOutputFilterByType DEFLATE application/xml
 AddOutputFilterByType DEFLATE application/xhtml+xml
 AddOutputFilterByType DEFLATE application/rss+xml
 AddOutputFilterByType DEFLATE application/javascript
 AddOutputFilterByType DEFLATE application/x-javascript
 
 DeflateCompressionLevel 9
 
# Browser specific settings
 BrowserMatch ^Mozilla/4 gzip-only-text/html
 BrowserMatch ^Mozilla/4\.0[678] no-gzip
 BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
 BrowserMatch \bOpera !no-gzip 

# Setup custom deflate log
 DeflateFilterNote Input instream
 DeflateFilterNote Output outstream
 DeflateFilterNote Ratio ratio
 
 LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate
# Example of log file
 CustomLog logs/deflate_log DEFLATE
</IfModule>

Tăng thời gian lưu file ở trình duyệt

Khi khách mở website của mình 1 lần, hàng loạt những file từ css, font, hình ảnh thumbnails, favicon… sẽ được tải về trình duyệt của khách và lưu tạm dưới dạng file cache. Ta sẽ tận dụng điều này khi tăng thời gian lưu trong trình duyệt của khách để không cần tải về lần nữa > tăng thời gian load web.

Rất đơn giản, chỉ cần thêm đoạn mã sau vào file .htaccess

# BEGIN Cache-Control Headers
<ifModule mod_headers.c>
    <filesMatch "\.(ico|jpeg|jgp|png|gif|swf)$">
        Header set Cache-Control "public"
    </filesMatch>
    <filesMatch "\.(css)$">
        Header set Cache-Control "public"
    </filesMatch>
    <filesMatch "\.(js)$">
        Header set Cache-Control "private"
    </filesMatch>
    <filesMatch "\.(x?html?|php)$">
        Header set Cache-Control "private, must-revalidate"
    </filesMatch>
</ifModule>
# END Cache-Control Headers

# BEGIN Expire headers
<ifModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 5 seconds"
    ExpiresByType image/x-icon "access plus 2592000 seconds"
    ExpiresByType image/jpeg "access plus 2592000 seconds"
    ExpiresByType image/png "access plus 2592000 seconds"
    ExpiresByType image/gif "access plus 2592000 seconds"
    ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
    ExpiresByType text/css "access plus 604800 seconds"
    ExpiresByType text/javascript "access plus 216000 seconds"
    ExpiresByType application/javascript "access plus 216000 seconds"
    ExpiresByType application/x-javascript "access plus 216000 seconds"
    ExpiresByType text/html "access plus 600 seconds"
    ExpiresByType application/xhtml+xml "access plus 600 seconds"
</ifModule>
# END Expire headers

Tắt tính năng hiển thị emoji của WP

Là vẫn sử dụng emoji mặc định thay vì load thêm css và js nhé. Thêm đoạn mã sau vào file functions.php của themes:

function disable_wp_emojicons() {
// remove all actions related to emojis
remove_action( 'admin_print_styles', 'print_emoji_styles' );
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
}
add_action( 'init', 'disable_wp_emojicons' );