Woocommerce + cache a frontend - Zoptymalizowany Wordpress
Włączenie cache'owania na stronach Wordpress to podstawa. Dobre czasy TTFB to priorytet, jeśli myślimy o dobrej wydajności projektu. W przypadku stron ecommerce opartych np. o Woocommerce sprawa nie zawsze jest taka prosta. Rozwiązanie to agresywne cache'owanie, z dynamicznymi aktualizacjami niektórych elementów na frontendzie przez API.
Takim przypadkiem jest chociażby element jak przycisk koszyka z liczbą dodanych produktów.
Jeżeli cache'ujemy całe strony, gdy użytkownik odwiedza np. stronę główną (jest scache'owana), a następnie przechodzi na stronę produktu, dodaje go do koszyka i później wraca na stronę główną - licznik produktów w koszyku się nie zaktualizował.
Dlaczego? Dlatego, bo wciąż załadowała się strona sprzed operacji dodania produktu do koszyka zapamiętana wcześniej.
Jak rozwiązać problem cache na stronach WP z Woocommerce?
Większość developerów rezygnuje z agresywnego cache'owania w takich momentach. Niesłusznie.
Możemy zastosować pewien trick.
Nadal cache'ujmy agresywnie, ale oprócz tego uruchamiajmy żądanie XHR/Ajax do stworzonego przez nas API endpointu (niecache'ujący odpowiedzi), który zwracał będzie liczbę produktów w koszyku. Dzięki kilku liniom kodu JS możemy wtedy dynamicznie podmienić liczbę produktów w koszyku w takim elemencie, gdy strona się ładuje.
Przykład kodu endpointu API:
<?php
add_action('wp_loaded', function() {
if (!empty($_REQUEST['get_cart_info'])) {
$cart = WC()->cart;
$cart_contents_count = $cart ? $cart->get_cart_contents_count() : 0;
$response = [
'products_count' => $cart_contents_count,
];
echo json_encode($response);
exit;
}
});
Powyższy snippet kodu powinien zostać dodany do functions.php (lub innego jeśli korzystasz z Bedrocka). Próbowałem stworzyć customowy route API (poprzez register_rest_route()), jednak Woocommerce nie zwraca danych o koszyku (który bazuje na sesji) w RESTfulowych endpointach.
A tutaj kod odpowiadający za wysyłanie żądania do tego API i podmianę wartości produktów w koszyku w przycisku na frontendzie.
Taki kod można dodać np. przed znacznikiem zamykającym </body>.
document.addEventListener("DOMContentLoaded", function() {
function updateProductsCounter() {
const apiUrl = '/?get_cart_info=1';
fetch(apiUrl)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
if (data.hasOwnProperty('products_count')) {
const counterElement = document.getElementById('products-counter');
if (counterElement) {
counterElement.textContent = data.products_count;
} else {
console.error('Element with ID #products-counter not found.');
}
} else {
console.error('Invalid data format received from API.');
}
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});
}
updateProductsCounter();
});
Dzięki temu sposobowi możemy ów problem rozwiązać. Globalne cache'owanie całej strony, a element strony jak licznik produktów w koszyku aktualizuje się na bieżąco, czyniąc żądanie do końcówki API, która zwraca obecną liczbę produktów (i podmienia liczbę w przycisku dynamicznie).
W ramach ciekawostki - textContent jest dużo szybszy niż innerText czy też innerHTML w JS. Tutaj możesz sobie samodzielnie przetestować. Metody .innerHTML i .innerText powodują rekalkulację stylów i reflow.
Demo:
- Wejdź na jeden z naszych projektów (Wordpress z Woocommerce, pełne cache'owanie).
- Przejdź na stronę produktu (np. ten).
- Powróć na stronę główną - u góry widoczna będzie aktualna liczba produktów w koszyku, zaktualizowana poprzez odpowiedź z naszego API (pomimo tego, że w dokumencie HTML nadal liczba wskazywać będzie na 0 z powodu cache'u strony sprzed dodania produktu do koszyka).
Pełne cache'owanie przynosi wiele korzyści na powyższej stronie. Zerknij na dane z CrUX jak wspaniałe czasy TTFB odnotowuje ten projekt (stronę uruchomiliśmy w październiku 2023).
Polecany artykuł:
Technika Window Shopping Caching
Polega na cache'owaniu stron produktów do momentu, gdy użytkownik nie doda jakiegoś produktu do koszyka - ciekawe, aczkolwiek opisana przeze mnie technika nie będzie sprawiać potencjalnych problemów z pluginami oraz zawsze cache'uje strony produktów, nawet gdy coś się już znajduje w koszyku.
Jeśli chcesz więcej treści związanych z optymalizacją wydajności Wordpressa - zapisz się na bezpłatny newsletter.