Đây là cấu hình liên quan tới xử lý ảnh mà mình đang khá hài lòng, gần như miễn phí, có thể áp dụng trên mọi nền tảng (Jetpack Photon chỉ cho chạy trên WordPress) link ảnh đẹp, sạch sẽ, các ảnh được xử lý tạo thumbail, nén ảnh ….. qua các công nghệ hàng đầu từ Cloudinary, tốc độ load ảnh rất gần với load trực tiếp từ localhost, trong trường hợp trang có lượng truy cập cực lớn, hoặc khách ở nhiều nơi trên thế giới, có thể chuyển sang dùng Cloudflare cache để tận dụng CDN tốt hơn
Các bước tuần tự như sau
Cloudinary khả năng nén, tối ưu hóa bằng các công nghệ liên quan tới ảnh cực kì mạnh, nhiều công ty tầm vóc thế giới sử dụng dịch vụ của họ
Trong tất cả các plugin, dịch vụ về ảnh mình từng dùng, Cloudinary cho ra dung lượng nhỏ nhất mà chất lượng gần như không thay đổi, tùy biến siêu nhiều, nếu thích có thể giảm dung lượng xuống rất nhỏ mà chất lượng chỉ thay đổi chút ít
Ngoài chuyện hỗ trợ định dạng AVIF rất mới, họ còn bóc tách, xem nội dung tấm ảnh, biết ảnh chụp cái gì, người, động vật hay cây cối, vật thể (khá giống google images, facebook), nên khi sử dụng các tùy chọn biến thể ảnh, nó có thể tạo thumbnail chính xác hơn tới đối tượng bạn mong muốn
Cloudinary sẽ hiệu quả hơn nếu bạn làm các shop bán hàng, ảnh thumbnail sẽ hiện, zoom chính xác hơn vào chủ thể, trên các blog cơ bản kiểu thèng bibica.net, thumbnail đa phần chỉ là làm nhỏ lại tấm ảnh, các ưu điểm mạnh của Cloudinary gần như không dùng tới, khá là phí :]]
Thứ duy nhất mình có thể phàn nàn về Cloudinary là vấn đề CDN, dù họ dùng tới 3-4 dịch vụ CDN cực to là Akamai, Fastly, Cloudflare, nhưng đôi khi, ở Việt Nam truy cập các ảnh từ Cloudinary khá chậm, cũng không quan trọng lắm, vì ở bài này chúng ta sẽ xử lý tất cả vấn đề phát sinh
Đăng kí tài khoản Cloudinary
Tạo tài khoản Cloudinary miễn phí, tại phần Account sẽ thấy Cloud Name của tài khoản (có thể ấn edit để đổi sang 1 tên dễ nhớ)
Sau đó đi tới Upload, tạo Auto upload mapping
- Folder: đặt tên tùy ý, chủ yếu để nhớ
- URL prefix: điền đường dẫn tới thư mục uploads trên WordPress
Các ảnh thông thường sẽ có url là:
https://bibica.net/wp-content/uploads/2023/09/2023-09-25-10-27-33.png
Sau khi tạo Auto upload mapping, Cloudinary sẽ có url là:
https://res.cloudinary.com/xinclub/f_webp,q_auto,dpr_auto/img/2023/09/2023-09-25-10-27-33.png
Trong đó xinclub
là Cloud Name, img
là Folders bạn vừa chọn, giữa 2 giá trị này là các giá trị f_webp,q_auto,dpr_auto,w_500,h_300 … để tùy biến ảnh, tùy bạn đưa vào
Cloudinary cho phép tạo rất nhiều các auto upload mapping khác nhau, bạn có thể tạo thêm nhiều folder cho các ảnh từ Gravatar, Github ….
Custom domain và cache qua Webinoly Reverse Proxy FastCgi Cache
Bài viết cụ thể tại đây,
File cấu hình như bên dưới
# REVERSE PROXY NGINX CONFIGURATION by Webinoly location / { proxy_set_header Connection ""; proxy_http_version 1.1; # WebinolyProxyCacheStart proxy_cache img_bibica_net; proxy_cache_key "$scheme$request_method$host$request_uri"; proxy_cache_valid 200 10y; proxy_cache_valid 301 302 303 307 308 404 410 451 1m; proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; proxy_cache_background_update on; proxy_cache_lock on; proxy_buffer_size 16k; proxy_buffers 16 16k; set $skip_cache_img_bibica_net 0; include apps.d/img.bibica.net*site_custom_cache.conf; proxy_cache_bypass $skip_cache_img_bibica_net; proxy_no_cache $skip_cache_img_bibica_net; # WebinolyProxyCacheEnd proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; proxy_ignore_headers Set-Cookie; proxy_intercept_errors on; #proxy_next_upstream error timeout http_500; # Upstream defined here: conf.d/upstream_proxy.conf proxy_pass https://res.cloudinary.com/xinclub/f_webp,q_auto:best/img/; } location /auto/ { proxy_set_header Connection ""; proxy_http_version 1.1; # WebinolyProxyCacheStart proxy_cache img_bibica_net; proxy_cache_key "$scheme$request_method$host$request_uri"; proxy_cache_valid 200 10y; proxy_cache_valid 301 302 303 307 308 404 410 451 1m; proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; proxy_cache_background_update on; proxy_cache_lock on; proxy_buffer_size 16k; proxy_buffers 16 16k; set $skip_cache_img_bibica_net 0; include apps.d/img.bibica.net*site_custom_cache.conf; proxy_cache_bypass $skip_cache_img_bibica_net; proxy_no_cache $skip_cache_img_bibica_net; # WebinolyProxyCacheEnd proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; proxy_ignore_headers Set-Cookie; proxy_intercept_errors on; #proxy_next_upstream error timeout http_500; # Upstream defined here: conf.d/upstream_proxy.conf proxy_pass https://res.cloudinary.com/xinclub/w_300,f_webp,q_auto:best/img/; }
Link custom là img.bibica.net
Hiện tại thì mình dùng 2 kích thước, 1 là chiều rộng 300 px cho ảnh thumbnail, còn lại là giữ nguyên kích thước gốc
- w_300 là vị trí thumbnail -> đường dẫn img/bibica.net/auto/ (chất lượng ảnh dùng auto best)
- Ở ảnh full thì giữ nguyên kích thước gốc, đường dẫn img.bibica.net (chất lượng ảnh dùng auto best)
Các tùy biến ảnh như 500,f_webp,q_auto:best, Cloud Name và Folder images đều đã được ẩn hoàn toàn, link đã ngắn gọn và sạch sẽ hết sức có thể
- Ảnh thực tiếp từ WordPress ban đầu : https://bibica.net/wp-content/uploads/2023/09/2023-09-25-10-27-33.png
- Sau khi được Cloudinary xử lý và Reverse Proxy : https://img.bibica.net/2023/09/2023-09-25-10-27-33.png
- Trong trường hợp muốn dùng ảnh có chiều rộng tối đa 300px, thêm /auto/ vào sau domain: https://img.bibica.net/auto/2023/09/2023-09-25-10-27-33.png
Bạn có thể thêm các tùy biến ảnh khác nhau, tùy vào sở thích, mình đang dùng 2 tùy chọn là /f_webp/q_auto:best/ ảnh nén về .webp và chất lượng ảnh tốt nhất có thể, kể cả ảnh thumbnail
Nếu thích hoặc đú đởn, có thể dùng trực tiếp custom domain các link Cloudinary lên chính domain gốc bibica.net, nhìn link ảnh là hú hồn con chồn, vì cứ tưởng ảnh gốc là để trên host 😀 có điều nên tách ra 1 domain phụ làm link ảnh cho dễ quản lý và cấu hình, chung hết 1 domain nhìn chằng chịt lắm 😛
Set ảnh vào các vị trí phù hợp
Sử dụng Code Snippets tạo 1 file php với nội dung:
function cloudinary_photon_custom($attr, $attachment, $size) { $image_id = get_post_thumbnail_id(); $image_meta = wp_get_attachment_metadata( $image_id ); $image_path = get_attached_file( $image_id ); if ($size === 'thumbnail') { $attr['src'] = "https://img.bibica.net/auto/".$image_meta['file']; } else if ($size === 'large') { $attr['src'] = "https://img.bibica.net/w_768/".$image_meta['file']; } return $attr; } add_filter('wp_get_attachment_image_attributes', 'cloudinary_photon_custom', 999 , 3);
Đoạn code này mình làm thủ công, đó là cứ ảnh size thumbnail thì đập thẳng luôn link https://img.bibica.net/auto/ vào 😀 sau đó nối với thư mục và tên file
Nếu bạn dùng nhiều định dạng hơn thì cứ thêm vào
Khắc phục tạm lỗi trên thì ở vị trí thumbnail, featured image, để tránh việc trùng tên với các album trước đây tạo, ở vị trí đó mình set dùng ảnh medium hay 1 tên mới tùy ý chưa dùng là được
Ban đầu tính nhờ tay bạn già Vượng Nguyễn viết hộ phần này, mà thấy hắn cũng bận, nên thôi, cứ google loạn hết cả lên, xong cắt dán đủ kiểu, không hiểu sao cuối cùng cũng có chạy :]] bạn nào rành code chắc chỉ cần 5 phút là viết xong với xử lý tốt cái lỗi mình nói ở trên rồi
Lúc này, chúng ta đã xử lý cơ bản các ảnh ở các vị trí thumbnail và featured image
Về các ảnh trong nội dung bài viết có thể dùng Lucas String Replace, để tìm và thay thế các link, mình thì để tăng trải nghiệm xem bài, các ảnh bên trong nội dung bài viết, giữ nguyên ảnh gốc, nên chỉ cần đổi //bibica.net/wp-content/uploads/
sang //img.bibica.net/
là xong
Hiệu quả?
Cấu hình như trong bài này, nó rất đa năng, do chỉ dùng Cloudinary làm bước trung gian để nén ảnh, nên tiêu tốn credit gần như không đáng kể, về mặt lý thuyết có thể áp dụng trên mọi nền tảng, chứ không chỉ trên WordPress
- Nếu bạn đang vận hành trên location Việt Nam, chỉ cần bỏ dùng Cloudflare cache
- Trong trường hợp chạy trên location Singapore, US …. dùng Cloudflare cache để user mọi nơi trên thế giới có tốc độ ổn định hơn (cá nhân mình thích dùng Cloudflare cache cho ảnh, vì Cloudflare có sập, thì thèng bibica.net …. sập luôn, đỡ lằng nhằng :D)
Nó vận hành cũng cực kì nhẹ, vì chỉ đổi ảnh khi bài viết được xuất bản, còn thực tế bên trong quản trị, các link bài viết đều là link gốc, sau này, nếu không thích dùng Cloudinary, chỉ cần tắt các đoạn code thêm vào Lucas String Replace, Code Snippets …. link ảnh sẽ về lại ảnh gốc
Link ảnh rất gọn cũng có thể là 1 ưu điểm 😀 nếu bạn nào làm theo bài này, gần như không ai biết là đang dùng Cloudinary để nén ảnh, tạo thumbnail, vì các thông tin bị ẩn đi sạch sẽ
Sử dụng Auto upload mapping, có một ưu điểm nhỏ, các ảnh sẽ được kéo về Cloudinary với cấu trúc thư mục tương tự trên WordPress, trong trường hợp bạn xóa nhầm ảnh trên VPS, vẫn còn 1 nơi để sơ cua
Cách này cũng có thêm 1 ưu điểm, bạn có thể set chính xác các tùy biến vào vị trí mình mong muốn, ví dụ ở ảnh thumbnail, có thể giảm chất lượng ảnh, chọn các tỷ lệ cắt, zoom khác nhau …. các plugin khác đa phần áp dụng cùng 1 bộ lọc cho tất cả vị trí
Mặc định Cloudinary cho miễn phí 20 credit, tốn đa là 100 credit, điểm này có thể quy đổi ra 100GB bandwidth, 100GB storage hoặc 100.000 lượt chuyển đổi mỗi tháng
Cấu hình như trong bài, gần như Cloudinary chỉ sử dụng khi bạn vừa upload ảnh lên, lưu file vào server của Cloudinary sau đó chuyển đổi định dạng, 1 tấm ảnh khoảng 200-300kb …. các con số gần như không đáng kể, trung bình mỗi tháng, thèng bibica.net dùng khoảng 5 credit
Bạn có thể dùng 20 credit miễn phí ban đầu, trong trường hợp ảnh nhiều quá, thì share sang Twitter, Facebook, cho bạn bè vào đăng kí thành viên để lấy thêm credit
Thay đổi quan điểm về Responsive Images
Trước đây, mình khá thần thánh các tính năng Responsive Images, nôm na dễ hiểu là mỗi vị trí, ảnh sẽ có kích thước khác nhau, kiểu vị trí đó độ rộng chỉ tối đa 700 px, bạn nhét cái ảnh 3000 px vào, chẳng để làm gì, set chính xác kích thước vào nó logic hơn về mặt lý thuyết
Thực tế sử dụng thì vấn đề Responsive Images lại liên quan tới tỷ lệ % cache, giả sử bạn quản lý responsive images tốt, trên các thiết bị như điện thoại, máy tính bảng, PC, laptop …. mỗi thiết bị sẽ có kích thước chính xác, lúc này mỗi tấm ảnh sẽ có 4-5 kích thước khác nhau, số lượng ảnh cần cache sẽ rất nhiều, và khi bạn clear cache, thời gian tạo lại cũng x3 x4 lần
Dùng duy nhất kích thước FULL, nó khá là ngu học về mặt kĩ thuật, nhưng sử dụng thực tế, nó lại hiệu quả, vì chỉ cần 1 thiết bị đầu tiên truy cập, nó lập tức được tạo cache, tất cả các thiết bị khác, truy xuất vào tấm ảnh đã cache này, gần như là load tức thì
Kết quả là sau nhiều năm sử dụng responsive images, mình đã bỏ 😀 các bài viết hiện tại đều chỉ dùng 1 kích thước duy nhất là FULL, ảnh thumbnail chỉ dùng cho các ảnh ở phần featured image, khi người đọc xem bài, các ảnh dù kích thước to vật, nhưng thời gian load ra vẫn nhanh, không ảnh hưởng tới trải nghiệm đọc
Kết luận:
Hiện tại mình đang sử dụng chính xác cấu hình Cloudinary trong bài này cho mọi bức ảnh bạn thấy trên trang bibica.net, bao gồm cả ảnh từ các comment và avatar từ gravatar 😀
Giải pháp này, cấu hình theo mình là khá phức tạp và hơi lằng nhằng, dùng WordPress chỉ cần cái Jetpack vào là xong, đơn giản hơn nhiều, hiệu quả về tốc độ hay chất lượng nén ảnh cũng gần như tương đương
Mình có thử dùng nhiều công nghệ nén ảnh khác nhau từ nhiều dịch vụ, thử nhiều dịch vụ CDN, thậm chí có hỗ trợ location Việt Nam …. đều cảm thấy không hiệu quả bằng cấu hình như bài này, chưa kể các dịch vụ khác, phần lớn họ bắt trả phí nữa …
Sau khoảng 6 tháng sử dụng thì mình khá hài lòng, gần như không gặp bất cứ lỗi nào, thực tế trừ cấu hình lần đầu tiên, mình không bao giờ cần log vào Cloudinary hay VPS để kiểm tra, mọi thứ vận hành trơn tru
Chính sách bình luận: Chúng tôi rất trân trọng các bình luận của bạn và cảm ơn thời gian bạn dành để chia sẻ ý tưởng và phản hồi.
Ghi chú: Những bình luận được xác định là spam hoặc chỉ mang tính quảng cáo sẽ bị xóa.
• Để cải thiện trải nghiệm bình luận, chúng tôi khuyến khích bạn tạo một tài khoản Gravatar. Thêm avatar vào tài khoản Gravatar sẽ giúp bình luận của bạn dễ nhận diện hơn đối với các thành viên khác.
• ✂️ Sao chép và 📋 Dán Emoji 💪 giúp bình luận thêm sinh động và thú vị!