Galeria w Crafcie: 439 zapytań SQL na jedną stronę
Strona galerii z 82 zdjęciami, każde z srcset z czterech wariantów, miała w pierwszej wersji 439 poleceń SQL i TTFB 106 ms, więcej niż WordPress z Elementorem. .eagerly() ładuje zasoby jednym zapytaniem, ale $asset->getUrl('wariant') szuka gotowego wariantu w tabeli imagetransformindex osobnym zapytaniem dla każdego zdjęcia i każdego wariantu. Jedna linia w szablonie ładuje indeks wariantów dla całej galerii naraz:
{%- set images = block.images.eagerly().all() -%}
{%- do craft.app.imageTransforms.eagerLoadTransforms(images, ['medium', 'large', 'thumbnail', 'mlarge']) -%}
WordPress ma w tej samej galerii swoją wersję problemu N+1: dwa zapytania na zdjęcie (SELECT * FROM wp_posts WHERE ID = … i zapytanie o meta). Wstępne wczytanie zdjęć galerii zmniejsza je w teście, bez zmiany motywu klienta:
add_action( 'elementor/frontend/widget/before_render', function ( $widget ) {
if ( 'theme-gallery' === $widget->get_name() ) { // nazwa widgetu galerii motywu
_prime_post_caches( wp_list_pluck( (array) $widget->get_settings( 'gallery' ), 'id' ), false, true );
}
} );
| Galeria 82 zdjęć (strona 3) | TTFB | Polecenia SQL |
| WordPress + Elementor, jak oddany | 66,8 ms | 260 |
| WordPress, wstępne wczytanie zdjęć (test) | 61,7 ms | 98 |
| Craft, pierwsza wersja szablonu | 106,0 ms | 439 |
| Craft, warianty jednym zapytaniem | 58,2 ms | 33 |
Na stronie 1 to samo: lista projektów z 67 do 34 poleceń, galeria z 62 do 33. Szablon „działa” w obu systemach także bez tego.
Ta sama jakość, inne bajty
Warianty z tych samych oryginałów WebP, w tych samych wymiarach i z tą samą jakością (80 i 82) są w Crafcie o 8 do 11 % większe (strona 1: 4,3 i 4,8 MB wszystkich wariantów, strona 3: 47,8 i 51,6 MB). WordPress zmniejsza filtrem Triangle z lekkim wyostrzeniem, Craft (biblioteka Imagine) domyślnym filtrem Imagicka. Do tego Craft przy wgrywaniu spoza panelu domyślnie ponownie kompresuje plik: wszystkie 32 oryginały strony 1 miały po imporcie inne bajty niż w WordPressie, dopóki tego nie wyłączyliśmy:
$asset->sanitizeOnUpload = false; // pliki z WordPressa są już oczyszczone; inaczej Craft zapisuje WebP od nowa
Imagick nie mieści się w memory_limit
Pamięć ImageMagicka nie liczy się do limitu PHP i w jednym procesie nie jest zwalniana między obrazami. Import 308 zdjęć i pierwsze wejście na galerię (warianty generowane przy wyświetlaniu, opcja generateTransformsBeforePageLoad) kończyły się w kontenerze 512 MB zabiciem procesu, bez odpowiedzi dla curl:
exit 137
Przy około 1 100 wariantach w jednym procesie ImageMagick zgłaszał:
cache resources exhausted ... @ error/cache.c/OpenPixelCache/3931
WordPress tworzy rozmiary przy wgrywaniu, jeden obraz na żądanie. W Crafcie warianty generujemy z góry osobnym poleceniem w jednorazowym kontenerze CLI z większym limitem:
docker run --rm -m 2g ... cs-cms-php:8.3 craft site/import/transforms # jednorazowy kontener CLI, ten sam obraz
Motyw WordPress bez Elementora: błąd krytyczny
Przy pomiarze „WordPress bez wtyczek” strona 1 zwracała 500:
PHP Fatal error: Uncaught Error: Class "Elementor\Plugin" not found in /var/www/html/wp-content/themes/<motyw>/inc/elementor.php:161
Winny był hook wp_print_footer_scripts, który wyłącza JavaScript Elementora na stronach bez interakcji. Motyw zbudowany pod konstruktor stron jest z nim związany mocniej, niż widać w panelu; do pomiaru zdjęliśmy ten jeden hook tymczasowym plikiem w mu-plugins.
Ponowne schema/apply w Craft 5 kasowało treść
Craft 5 zapisuje wartości pól w kolumnie JSON elements_sites.content pod UID elementu układu pola, nie samego pola. Skrypt schematu, który przy każdym uruchomieniu tworzył nowe elementy układu, po drugim przebiegu „gubił” wszystkie teksty: w bazie były, ale pod starymi UID, a resave/entries utrwalał stratę. Poprawka: przejmować UID istniejących elementów układu. Ważne dla każdego, kto trzyma schemat Crafta w kodzie.
Tekst z Elementora to nie tekst ze strony
Elementor zapisuje surowy HTML, a WordPress przy wyświetlaniu przepuszcza go przez wptexturize: dywiz między słowami staje się półpauzą (–), proste cudzysłowy drukarskimi. Import z danych Elementora dałby inne znaki niż na żywej stronie, więc teksty i tytuły strony 2 przenieśliśmy z wyrenderowanego HTML.
Wyszukiwarka daje inne wyniki przy tej samej treści
WordPress szuka LIKE w post_content, gdzie Elementor trzyma kopię HTML strony razem z tekstami alternatywnymi i nazwami plików zdjęć. Craft szuka w indeksie słów z pól oznaczonych jako przeszukiwalne, a w Craft 5 pole domyślnie przeszukiwalne nie jest: wyszukiwarka znajdowała tylko tytuły. Po włączeniu indeksu dla tego samego słowa WordPress zwraca 6 stron, Craft 4; w dwóch słowo było tylko w nazwach plików zdjęć.