Kompresja obrazków w WordPress bez wtyczki: szybkość i skalowalność
W dawnych czasach WordPressa optymalizacja obrazów oznaczała instalację wtyczki typu Smush czy EWWW i nadzieję na najlepsze.
We współczesnych stronach to media stanowią największą część bajtów przesyłanych do przeglądarki. Web Almanac 2025 mierzy udział obrazów na mniej więcej 37% wagi mediany strony mobilnej. To mniej niż często powtarzane 50 do 70 procent, ale nadal największa pozycja, na którą masz realny wpływ. Jeśli twoja strona na WordPressie ma dobrze wypadać w wyszukiwarce, uporządkowanie obsługi mediów to jedno z kluczowych zadań wydajnościowych. Nowoczesne kodeki AVIF i WebP, przycięcie zbędnych wariantów miniatur, rozsądne zarządzanie lazy loadingiem nad linią zgięcia i przeniesienie plików do chmurowego Object Storage zmniejszają wagę strony i poprawiają wygodę użytkowników.
W 2026 roku krajobraz wygląda inaczej. Rdzeń WordPressa przyjmuje i obsługuje wgrywane pliki WebP i AVIF, choć sam nie konwertuje do nich twoich JPEG-ów. Przeglądarki ustandaryzowały lazy loading. Środowiska hostingowe często oferują kompresję na poziomie serwera.
Ten przewodnik jest dla programistów, którzy chcą zrozumieć natywną mechanikę obsługi mediów w WordPressie i zoptymalizować ją bez zaśmiecania swojego stacku ciężkimi wtyczkami.
Jeśli wolisz oddać to zadanie specjalistom, zobacz naszą usługę przyspieszania stron WordPress, która poprawia wskaźniki wydajności całej witryny.
Każda z poniższych strategii wymaga systematycznego podejścia, w którym optymalizacja techniczna idzie w parze z jakością treści. Poniżej opisuję je po kolei, razem z kodem.
1. Obsługa WebP i AVIF w WordPress przez Imagick lub GD
Klasyczne formaty (JPEG i PNG) kompresują dane znacznie słabiej niż nowoczesne alternatywy.
- WebP: WordPress obsługuje go od wersji 5.8. Format oferuje kompresję stratną i bezstratną. Dokumentacja WebP od Google podaje, że stratny WebP jest o 25 do 34% mniejszy od porównywalnego pliku JPEG, a bezstratny WebP o 26% mniejszy od PNG.
- AVIF (AV1 Image File Format): obsługiwany od WordPressa 6.5. AVIF korzysta z kodowania wewnątrzklatkowego wywodzącego się z kodeka wideo AV1. Przy tej samej jakości wizualnej zwykle wypada lepiej niż WebP, ale przewaga zależy od konkretnego obrazu, więc zmierz ją na własnej bibliotece. Przewodnik po AVIF i JPEG XL omawia koszt kodowania i wsparcie przeglądarek.
WordPress przyjmuje pliki w tych formatach i tworzy dla nich pod-rozmiary w tym samym formacie, ale wgranego JPEG-a nie zamienia na WebP ani AVIF, dopóki nie wskażesz formatu wyjściowego filtrem image_editor_output_format.
Jak sprawdzić obsługę WebP i AVIF w PHP
Żeby generować te formaty, PHP musi korzystać z biblioteki Imagick lub GD skompilowanej z obsługą AVIF i WebP. Dostępne biblioteki do przetwarzania obrazów sprawdzisz na serwerze z wiersza poleceń:
# Sprawdź obsługę WebP i AVIF w modułach PHP
php -r "print_r(gd_info());"
php -r "if (class_exists('Imagick')) { print_r(Imagick::getConfigureOptions()); }"W tablicy GD szukaj wpisów WebP Support => 1 i AVIF Support => 1. Jeśli ich brakuje, musisz przebudować pakiety PHP na serwerze z bibliotekami libwebp i libavif.
[!TIP] Sprawdź stan witryny: wejdź w Narzędzia > Stan witryny (Site Health), aby potwierdzić, czy twoja instalacja PHP obsługuje generowanie AVIF.
Imagick czy GD do przetwarzania obrazów w WordPress
W WordPressie przekształcenia obrazów po stronie serwera wykonują dwie biblioteki: GD i Imagick. Wybór ma bezpośredni wpływ na zużycie zasobów i jakość wyniku:
- Imagick (ImageMagick): preferowany silnik w dużych środowiskach. Lepiej odwzorowuje kolory, zachowuje profile metadanych (na przykład informację o obrocie z EXIF) i obsługuje zaawansowane operacje, takie jak podglądy wielostronicowych PDF-ów. Zużywa jednak sporo pamięci, bo zdekodowany bufor pikseli rośnie z liczbą pikseli, a nie z rozmiarem pliku: 12-megapikselowy JPEG, który na dysku zajmuje 3 MB, w RAM-ie rozrasta się do kilkudziesięciu megabajtów.
- GD (Graphics Library): lekki silnik o małym narzucie. Przy typowym skalowaniu GD jest lżejszy z tej dwójki. Opublikowane benchmarki różnią się co do wielkości tej przewagi, a niektóre nawet co do jej kierunku, więc zmierz to na własnym stacku zamiast ufać nagłówkowemu procentowi. GD nie ma za to zaawansowanych konwersji przestrzeni barw (kolory po konwersji często wyglądają na lekko wyblakłe) i gubi profile EXIF.
- Przy generowaniu WebP i AVIF koder Imagick obsługuje wielowątkowość, a GD działa synchronicznie na jednym rdzeniu procesora. Na stronach z dużym ruchem wybieraj Imagick, ale ustaw mu ścisłe limity zasobów, żeby kontrolować zużycie pamięci.
Limity pamięci Imagick w policy.xml
Generowanie plików AVIF mocno obciąża procesor i pamięć. Jeśli kilka zdjęć w wysokiej rozdzielczości trafi na serwer jednocześnie, procesowi PHP może zabraknąć pamięci (OOM) albo skrypt przekroczy limit czasu. Żeby temu zapobiec, zmień politykę limitów zasobów Imagick na serwerze. Edytuj /etc/ImageMagick-6/policy.xml lub /etc/ImageMagick-7/policy.xml i ustaw rozsądne granice pamięci:
<policymap>
<!-- Limit pamięci na proces: 512MiB -->
<policy domain="resource" name="memory" value="512MiB"/>
<policy domain="resource" name="map" value="1GiB"/>
<!-- Ogranicz liczbę wątków, żeby nie zagłodzić procesora -->
<policy domain="resource" name="thread" value="2"/>
<!-- Zablokuj zewnętrzne programy delegowane -->
<policy domain="delegate" rights="none" pattern="*"/>
</policymap>Takie limity sprawiają, że przetwarzanie obrazów działa stabilnie w twoim środowisku hostingowym, także podczas masowej regeneracji mediów.
2. Jak zmienić jakość kompresji obrazów w WordPress
Domyślna jakość kompresji wgrywanych JPEG-ów w WordPressie to 82. Dla miniatur i elementów tła to często zbyt wysoka wartość, przez co pliki są niepotrzebnie ciężkie.
Jakość kompresji osobno dla każdego formatu
Dodaj te filtry do pliku functions.php motywu, żeby ustawić jakość kompresji zależnie od typu MIME obrazu:
declare(strict_types=1);
namespace WPPoland\Performance\Media;
/**
* Ustawia jakość kompresji zależnie od formatu obrazu.
*/
function set_media_compression_quality( int $quality, string $mime_type ): int {
switch ( $mime_type ) {
case 'image/jpeg':
return 75; // Ok. 20% mniej miejsca niż przy domyślnych 82%
case 'image/webp':
return 80;
case 'image/avif':
return 65; // AVIF zachowuje wysoką jakość nawet przy niższych ustawieniach
default:
return $quality;
}
}
add_filter( 'wp_editor_set_quality', __NAMESPACE__ . '\\set_media_compression_quality', 10, 2 );
add_filter( 'jpeg_quality', function() { return 75; } );3. Jak wyłączyć nieużywane rozmiary obrazów w WordPress
Gdy wgrywasz obraz, WordPress tworzy plik dla każdego zarejestrowanego pod-rozmiaru. Sam rdzeń rejestruje sześć (thumbnail, medium, medium_large, large, 1536x1536 i 2048x2048), a każdy motyw lub wtyczka, która wywołuje add_image_size(), dokłada kolejne. Jeśli dodasz motyw, który rejestruje 5 dodatkowych rozmiarów (portfolio-grid, slider-large itp.), każde pojedyncze wgranie zdjęcia generuje ponad 10 plików. To marnuje limity inodów i przestrzeń dyskową, a przy migracjach mediów także czas procesora.
Usuwanie nieużywanych rozmiarów w functions.php
Usuń nieużywane rozmiary miniatur, żeby oszczędzić miejsce na dysku i skrócić przetwarzanie każdego wgrania:
declare(strict_types=1);
namespace WPPoland\Performance\Thumbnails;
/**
* Usuwa nieużywane wymiary miniatur.
*/
function unregister_bloated_thumbnail_sizes( array $sizes ): array {
// Usuń rozmiary, których nie używa układ motywu
unset( $sizes['medium_large'] ); // 768px wide
unset( $sizes['1536x1536'] ); // Extra large
unset( $sizes['2048x2048'] ); // 2K large
return $sizes;
}
add_filter( 'intermediate_image_sizes_advanced', __NAMESPACE__ . '\\unregister_bloated_thumbnail_sizes' );
/**
* Rejestruje własne rozmiary, których używają aktywne szablony.
*/
function register_theme_image_sizes(): void {
add_image_size( 'hero-lg', 1920, 800, true );
add_image_size( 'blog-card', 600, 400, true );
}
add_action( 'after_setup_theme', __NAMESPACE__ . '\\register_theme_image_sizes' );4. Wyłączenie lazy loadingu dla obrazu LCP w WordPress
Od wersji 5.5 WordPress automatycznie dodaje loading="lazy" do obrazów we wpisach. Ogólnie pomaga to szybkości strony, ale lazy loading zasobów nad linią zgięcia blokuje mechanizmy wczesnego pobierania w przeglądarce i pogarsza LCP (Largest Contentful Paint). Nie włączaj go dla obrazu LCP, zwykle obrazu głównego (hero) lub obrazka wyróżniającego wpisu. Od WordPressa 6.3 rdzeń sam pomija lazy loading dla pierwszego dużego obrazu i nadaje mu fetchpriority="high", co wyjaśnia przewodnik po obsłudze obrazków. Poniższe filtry nadal działają (rdzeń zachowuje wp_img_tag_add_loading_attr dla zgodności wstecznej) i mają znaczenie we własnych szablonach i listach wpisów, w których rdzeń zgaduje źle.
Wczesne ładowanie obrazów nad linią zgięcia z fetchpriority
Skonfiguruj szablony tak, żeby pierwszy obraz na liście wpisów ładował się od razu, a obrazy hero dostawały wysoki priorytet pobierania:
declare(strict_types=1);
namespace WPPoland\Performance\LCP;
/**
* Wyłącza lazy loading dla pierwszego obrazu we wpisie.
*/
function disable_lazy_load_on_first_image( string|bool $value, string $image_tag, string $context ): string|bool {
static $first_image = true;
if ( 'the_content' === $context && $first_image ) {
$first_image = false;
return false; // Blokuje wstawienie loading="lazy"
}
return $value;
}
add_filter( 'wp_img_tag_add_loading_attr', __NAMESPACE__ . '\\disable_lazy_load_on_first_image', 10, 3 );
/**
* Dodaje fetchpriority="high" do obrazów ładowanych od razu.
*/
function apply_fetchpriority_to_eager_images( array $attr, \WP_Post $attachment ): array {
if ( isset( $attr['loading'] ) && 'eager' === $attr['loading'] ) {
$attr['fetchpriority'] = 'high';
}
return $attr;
}
add_filter( 'wp_get_attachment_image_attributes', __NAMESPACE__ . '\\apply_fetchpriority_to_eager_images', 10, 2 );5. Konfiguracja atrybutu sizes dla obrazów responsywnych
WordPress automatycznie obsługuje srcset. Żeby przeglądarka wybrała z niego właściwy rozmiar, musisz jednak dopasować definicje w atrybucie sizes. Domyślny atrybut często sprowadza się do 100vw, przez co na komputerach przeglądarka pobiera za duże obrazy.
Własny atrybut sizes dla progów srcset
declare(strict_types=1);
namespace WPPoland\Performance\Responsive;
/**
* Nadpisuje domyślny atrybut sizes, żeby pasował do progów układu motywu.
*/
function filter_responsive_image_sizes_attribute( string $sizes, array $size_array ): string {
$width = $size_array[0];
// Sprawdź, czy obraz mieści się w granicach układu wpisu na blogu
if ( $width >= 800 ) {
return '(max-width: 840px) 100vw, 800px';
}
return $sizes;
}
add_filter( 'wp_calculate_image_sizes', __NAMESPACE__ . '\\filter_responsive_image_sizes_attribute', 10, 2 );Atrybut sizes we własnej pętli
Atrybut sizes możesz też podać ręcznie, gdy renderujesz obrazy we własnych pętlach:
echo wp_get_attachment_image(
$image_id,
'large',
false,
['sizes' => '(max-width: 600px) 100vw, 800px']
);Taki zapis mówi przeglądarce, że na ekranie węższym niż 600px obraz zajmie pełną szerokość, a w pozostałych przypadkach będzie miał 800px szerokości.
6. Serwowanie AVIF zamiast JPEG przez .htaccess
Jeśli na stronie leżą stare JPEG-i, a chcesz serwować nowoczesnym przeglądarkom wersje WebP lub AVIF bez zmiany kodu HTML, użyj reguł negocjacji treści po stronie serwera.
Serwowanie AVIF regułami rewrite w Apache
Dodaj te reguły do pliku .htaccess, żeby serwer automatycznie podawał plik AVIF, gdy przeglądarka akceptuje ten format, a plik istnieje na dysku:
<IfModule mod_rewrite.c>
RewriteEngine On
# Sprawdź, czy przeglądarka obsługuje AVIF
RewriteCond %{HTTP_ACCEPT} image/avif
# Sprawdź, czy wersja AVIF istnieje na dysku
RewriteCond %{DOCUMENT_ROOT}/$1.avif -f
# Przekieruj żądania JPEG/PNG do wersji AVIF
RewriteRule ^(wp-content/uploads/.*)\.(jpe?g|png)$ $1.avif [T=image/avif,E=accept:1]
</IfModule>Takie reguły przepisywania na poziomie serwera pozwalają podawać zgodnym przeglądarkom nowoczesne, dobrze skompresowane pliki, a starszym systemom zostawić wersje zapasowe.
7. Offload mediów WordPress do S3 z CDN
Na stronach z dużą biblioteką mediów trzymanie plików na lokalnych wolumenach serwera ogranicza skalowanie i komplikuje kopie zapasowe. Przeniesienie mediów do usługi Object Storage (na przykład AWS S3, DigitalOcean Spaces lub Google Cloud Storage) i serwowanie ich przez sieć CDN to standardowe rozwiązanie dla stron z dużym ruchem. Do integracji służą wtyczki takie jak WP Offload Media lub Media Cloud.
Co się zmienia po przeniesieniu mediów
Po przeniesieniu mediów:
- Bezstanowe serwery WWW: poszczególne serwery nie potrzebują już synchronizacji trwałych wolumenów. Kontenery możesz dynamicznie dokładać i usuwać w grupach autoskalowania.
- Oszczędność lokalnego dysku: jeśli integracja usuwa pliki lokalne zaraz po udanym wysłaniu do chmury, dyski serwera się nie zapełniają, a koszty serwerów aplikacji zostają pod kontrolą.
- Cache CDN i rozproszenie geograficzne: żądania trafiają do brzegowych cache (takich jak Cloudflare, Amazon CloudFront czy KeyCDN) zamiast do głównego serwera, co zmniejsza zużycie transferu i opóźnienia dla użytkowników na całym świecie.
Ustawienia WP Offload Media dla S3 w wp-config.php
Stałe konfiguracyjne WP Offload Media opisują AS3CF_SETTINGS jako zserializowaną tablicę. Dostawcy przechowywania to aws, do i gcp; własną domenę CDN ustawia się kluczami dostarczania (delivery), a nie kluczami przechowywania:
// Zdefiniuj dane dostępowe S3 i bucket bezpiecznie w wp-config.php
define( 'AS3CF_SETTINGS', serialize( [
'provider' => 'aws',
'access-key-id' => getenv( 'AWS_ACCESS_KEY_ID' ),
'secret-access-key' => getenv( 'AWS_SECRET_ACCESS_KEY' ),
'bucket' => 'wppoland-media-bucket',
'region' => 'eu-central-1',
'copy-to-s3' => true,
'serve-from-s3' => true,
'remove-local-file' => true, // Oszczędza dysk na głównym serwerze aplikacji
'object-versioning' => true, // Ścieżki ze znacznikiem czasu, więc zmieniony plik dostaje nowy URL
'delivery-provider' => 'cloudflare',
'enable-delivery-domain' => true,
'delivery-domain' => 'media.wppoland.com' // Własna subdomena CDN
] ) );Nagłówki CORS i cache-control dla bucketu S3 lub R2
Żeby grafiki wektorowe (SVG) i własne fonty z bucketu z mediami wyświetlały się poprawnie na oddzielnych domenach headless (na przykład frontendach w Astro działających pod inną domeną), musisz skonfigurować na buckecie Cross-Origin Resource Sharing (CORS).
Zastosuj tę politykę CORS w formacie JSON w ustawieniach bucketu S3 lub R2:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedOrigins": ["https://wppoland.com", "https://www.wppoland.com"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3000
}
]Dopilnuj też, żeby pliki serwowane z bucketu miały nagłówki długiego cache. Skonfiguruj integrację offloadu lub CDN tak, by ustawiała: Cache-Control: public, max-age=31536000, immutable
Dzięki temu przeglądarki i serwery brzegowe trzymają pliki mediów w cache na stałe, co ogranicza liczbę żądań i przyspiesza ładowanie. Dyrektywa immutable jest bezpieczna tylko dlatego, że object-versioning zapisuje zmieniony plik pod nową ścieżką. Bez tego edytowany obraz zachowuje stary URL i zostaje w cache przez rok.
8. Jak ograniczyć rozmiar wgrywanych obrazów w WordPress
Żeby autorzy nie wrzucali nieskompresowanych 10-megabajtowych zdjęć z aparatu prosto do bloków edytora (co marnuje transfer i miejsce na dysku), dodaj automatyczny filtr walidujący na granicy serwera.
Dlaczego walidować rozmiar pliku na serwerze
Sprawdzanie rozmiaru po stronie serwera zapobiega przekroczeniu limitów czasu PHP. Gdy redaktor wgrywa obraz o wadze 10 MB:
- Serwer musi zapisać plik tymczasowy w
/tmp/. - Proces PHP próbuje wczytać obraz do pamięci, żeby go przeskalować. Jeśli GD lub Imagick dojdzie do swojego limitu, skrypt kończy się błędem i zostawia na dysku niekompletne pliki.
- Filtr podpięty pod
wp_handle_upload_prefilterprzechwytuje plik zaraz po odebraniu i sprawdza rozmiar, zanim ruszą jakiekolwiek przekształcenia obrazu. Sekcja oupload_max_filesizeniżej pokazuje, jak sprawić, żeby ten sam limit egzekwowało już okno wgrywania w przeglądarce, zanim plik zostanie wysłany.
Implementacja filtra w PHP:
declare(strict_types=1);
namespace WPPoland\Performance\Limits;
/**
* Egzekwuje limity rozmiaru pliku zależnie od typu podczas wgrywania.
*/
function restrict_large_uploads( array $file ): array {
$size_kb = $file['size'] / 1024;
$type = $file['type'];
// Limit 1.5MB dla zwykłych obrazów rastrowych
if ( strpos( $type, 'image/' ) !== false && 'image/gif' !== $type ) {
if ( $size_kb > 1536 ) {
$file['error'] = 'Image upload failed: File size exceeds the 1.5MB limit. Please compress your asset before uploading.';
}
}
return $file;
}
add_filter( 'wp_handle_upload_prefilter', __NAMESPACE__ . '\\restrict_large_uploads' );9. Co WordPress zapisuje dla każdego wgranego obrazu
Każdy plik w bibliotece mediów to wpis typu attachment. Do samego pliku odwołują się dwa wiersze meta wpisu, a większość problemów z mediami (zepsute miniatury po migracji, wtyczka offloadu serwująca zły rozmiar, regeneracja, która nigdy się nie kończy) sprowadza się do tego, że te dwa wiersze nie zgadzają się z tym, co leży na dysku.
_wp_attached_fileprzechowuje ścieżkę względem katalogu uploads, na przykład2026/10/workshop-floor.jpg. Jeśli oryginał był większy niż próg dużego obrazu, wpis wskazuje na kopię-scaled, a nie na oryginał._wp_attachment_metadataprzechowuje zserializowaną tablicę zbudowaną przezwp_generate_attachment_metadata():width,height,file,filesize(zapisywane od WordPressa 6.0),sizesz jednym wpisem na każdy wygenerowany pod-rozmiar (nazwa pliku, szerokość, wysokość, typ MIME),image_metaz danymi EXIF i IPTC, które odczytuje rdzeń, orazoriginal_image, gdy wgrany plik został zmniejszony.
Zajrzyj do tej tablicy, zanim uwierzysz jakiemukolwiek raportowi wtyczki na jej temat:
# Wypisz metadane załącznika 1874 jako JSON
wp post meta get 1874 _wp_attachment_metadata --format=json
# Pokaż zapisaną ścieżkę względną
wp post meta get 1874 _wp_attached_fileOd WordPressa 5.3 rdzeń zapisuje te metadane po każdym utworzonym pod-rozmiarze, a nie raz na końcu. Jeśli PHP padnie w połowie przetwarzania dużego pliku, gotowe rozmiary są już zapisane, a wp_update_image_subsizes() przy kolejnej próbie tworzy tylko brakujące. Dlatego REST API ma trasę post-process (/wp/v2/media/<id>/post-process z akcją create-image-subsizes): po błędzie serwera okno wgrywania może poprosić o brakujące rozmiary zamiast wysyłać plik jeszcze raz.
Filtr big_image_size_threshold (domyślnie 2560 pikseli) decyduje, kiedy powstaje kopia -scaled. Przewodnik po obsłudze obrazków pokazuje, jak go zmienić lub wyłączyć, i omawia też wp media regenerate.
Jak wypisać zarejestrowane rozmiary obrazów przez WP-CLI
Zanim cokolwiek wyrejestrujesz w sekcji 3, sprawdź, co faktycznie jest zarejestrowane. wp media image-size wypisuje każdy rozmiar z szerokością, wysokością, flagą przycinania i proporcjami, łącznie z rozmiarami dodanymi przez wtyczki, o których mogłeś zapomnieć:
wp media image-size --format=table
wp media image-size --fields=name,width,height,crop --format=csvPorównaj tę listę z plikami w folderze z ostatniego miesiąca. Rozmiar, który jest na dysku, ale nie ma go na liście, należy do motywu lub wtyczki, które nie są już aktywne, i wp media regenerate go nie odtworzy. Wartości domyślne w Ustawienia > Media pochodzą ze schematu instalacji: miniatura 150 x 150 z przycięciem, średni 300 x 300, medium_large o szerokości 768 bez limitu wysokości i duży 1024 x 1024. Wejdź w Ustawienia > Media i ustaw wymiary na 0 dla każdego domyślnego rozmiaru (na przykład średniego), którego nie używasz: rdzeń przestanie go generować dla nowych plików.
10. Jak zmienić strukturę folderów uploads w WordPress
Domyślnie WordPress zapisuje wgrane pliki w folderach roku i miesiąca (wp-content/uploads/2026/10/). Pole wyboru w Ustawienia > Media, które porządkuje przesyłane pliki w folderach według roku i miesiąca, steruje opcją uploads_use_yearmonth_folders, ustawioną na 1 w świeżej instalacji. Wyłączenie go działa tylko na nowe pliki: istniejące zachowują swoje ścieżki, bo ścieżka jest zapisana osobno dla każdego załącznika w _wp_attached_file.
Filtr upload_dir zmienia miejsce zapisu nowych plików. Dostaje tablicę z kluczami path, url, subdir, basedir, baseurl i error, a ty zmieniasz subdir razem z path i url:
declare(strict_types=1);
namespace WPPoland\Performance\Uploads;
/**
* Zapisuje wgrywane PDF-y w /uploads/documents/ zamiast w folderach z datą.
*/
function route_pdf_uploads( array $uploads ): array {
$name = $_FILES['async-upload']['name'] ?? '';
if ( ! str_ends_with( strtolower( $name ), '.pdf' ) ) {
return $uploads;
}
$uploads['subdir'] = '/documents';
$uploads['path'] = $uploads['basedir'] . $uploads['subdir'];
$uploads['url'] = $uploads['baseurl'] . $uploads['subdir'];
return $uploads;
}
add_filter( 'upload_dir', __NAMESPACE__ . '\\route_pdf_uploads' );Rdzeń nie ma folderów na ekranie biblioteki mediów. Widok folderów, który dodają niektóre wtyczki, to taksonomia zarejestrowana dla typu wpisu attachment, więc żyje w bazie danych i nie przenosi plików na dysku. Jeśli budujesz taką taksonomię sam przez register_taxonomy( 'media_folder', 'attachment', ... ), ustaw _update_generic_term_count jako funkcję liczącą: domyślny licznik uwzględnia załącznik tylko przez opublikowany wpis nadrzędny, więc pliki niepodpięte do żadnego wpisu nigdy nie pojawiają się w liczniku terminu.
11. Jak zarządzać tekstem alternatywnym w bibliotece mediów WordPress
Pole tekstu alternatywnego w bibliotece mediów jest zapisane w meta _wp_attachment_image_alt. wp_get_attachment_image() odczytuje je przy każdym renderowaniu, po trim() i strip_tags(), więc obrazki wyróżniające i szablony motywu korzystające z tej funkcji od razu pokazują poprawioną wartość.
Blok Obraz działa inaczej. Jego atrybut alt pochodzi z atrybutu alt znacznika <img> w zapisanej treści wpisu, więc blok kopiuje wartość z biblioteki w chwili wstawienia i potem trzyma własną kopię. Poprawienie tekstu alternatywnego w bibliotece mediów nie aktualizuje wpisów, które już zawierają ten obraz; w nich trzeba poprawić sam blok.
Zapytanie audytowe znajdzie obrazy bez tekstu alternatywnego (dopasuj prefiks wp_ do swojej instalacji):
wp db query "SELECT p.ID, p.post_title FROM wp_posts p
LEFT JOIN wp_postmeta m ON m.post_id = p.ID AND m.meta_key = '_wp_attachment_image_alt'
WHERE p.post_type = 'attachment' AND p.post_mime_type LIKE 'image/%'
AND (m.meta_value IS NULL OR m.meta_value = '')"
# Ustaw tekst alternatywny jednego załącznika
wp post meta update 1874 _wp_attachment_image_alt "Two developers reviewing a staging site on a laptop"Pusty wynik nie zawsze jest celem. Drzewo decyzyjne W3C dla tekstu alternatywnego wskazuje, że obraz czysto dekoracyjny albo taki, którego treść już stoi obok jako zwykły tekst, powinien mieć pusty atrybut alt. Pisz tekst alternatywny dla obrazów, które niosą informację, a dla obrazów działających jak linki lub przyciski opisuj ich funkcję.
12. Jak zwiększyć upload_max_filesize w WordPress
Limit, który okno wgrywania pokazuje jako maksymalny rozmiar przesyłanego pliku, pochodzi z wp_max_upload_size(). Funkcja odczytuje dwa ustawienia PHP, upload_max_filesize i post_max_size, bierze mniejsze z nich i przepuszcza je przez filtr upload_size_limit. Ta sama wartość trafia do okna wgrywania w przeglądarce jako max_file_size, więc plik powyżej limitu zostaje odrzucony, zanim zostanie wysłany.
Podręcznik PHP podaje wartości domyślne 2M dla upload_max_filesize i 8M dla post_max_size i oznacza oba ustawienia jako INI_PERDIR. To ma praktyczną konsekwencję: ini_set() w wp-config.php nie może ich podnieść. Ustaw je w php.ini, w pliku .user.ini, w konfiguracji puli PHP-FPM albo (na Apache z mod_php) w .htaccess, i pilnuj, żeby post_max_size był większy niż upload_max_filesize, bo tego wymaga podręcznik.
; .user.ini w katalogu głównym WordPressa (PHP-FPM / CGI)
upload_max_filesize = 16M
post_max_size = 20MPodniesienie limitów PHP to połowa pracy. Druga połowa to dopilnowanie, żeby redaktorzy nie zużyli nowego zapasu na 12-megapikselowe oryginały z aparatu. Filtr upload_size_limit w praktyce może tylko obniżyć efektywny limit (PHP odrzuca wszystko powyżej własnego ustawienia, zanim WordPress w ogóle ruszy) i jest lepszym miejscem na politykę 1,5 MB z sekcji 8, bo okno wgrywania pokazuje wtedy prawdziwy limit:
add_filter( 'upload_size_limit', static fn ( int $size ): int => min( $size, 1536 * KB_IN_BYTES ) );W multisite jest trzeci limit. Ustawienie sieci określające maksymalny rozmiar wgrywanego pliku jest zapisane w opcji witryny fileupload_maxk, domyślnie 1500 KB, a rdzeń stosuje je przez ten sam filtr razem z pozostałym limitem miejsca na pliki danej witryny.
13. 90-dniowy plan optymalizacji obrazów w WordPress
Trzymaj się tego harmonogramu, żeby uporządkować i monitorować media na stronie:
- Dni 1-30 (konfiguracja od ręki): sprawdź, czy moduły PHP na serwerze obsługują AVIF i WebP. Ustaw filtry jakości w
functions.php, żeby kontrolować kompresję osobno dla każdego formatu. Wyłącz lazy loading dla elementów hero nad linią zgięcia i dodaj filtry wysokiego priorytetu pobierania, żeby poprawić czas Largest Contentful Paint (LCP). - Dni 31-60 (przycinanie rozmiarów i regeneracja): znajdź i wyrejestruj nieużywane rozmiary obrazów motywu filtrem
intermediate_image_sizes_advanced, żeby oszczędzić miejsce na serwerze. Napisz filtr PHP ograniczający duże pliki na granicy serwera i dopasuj do niegoupload_size_limit. Uruchom zapytanie audytowe tekstu alternatywnego i popraw obrazy, które niosą informację. Odpal regenerację przez WP-CLI, żeby odbudować istniejące miniatury z nowymi ustawieniami jakości. - Dni 61-90 (skalowanie i offload do chmury): przenieś bibliotekę mediów do Object Storage w S3 lub R2, z konfiguracją usuwającą lokalne pliki źródłowe. Ustaw osobną, bezciasteczkową subdomenę CDN z właściwymi nagłówkami CORS i cache-control, a poprawę szybkości sprawdź w Search Console.
Potrzebujesz pomocy przy budowie własnego procesu optymalizacji mediów albo konfiguracji offloadu do S3? Nasz zespół od przyspieszania stron WordPress przeprowadzi audyt biblioteki mediów, skompiluje pakiety serwerowe i skonfiguruje CDN. Skontaktuj się z nami, żeby omówić wymagania projektu.
Filtr jpeg_quality załatwia nowe pliki, ale stara biblioteka mediów zwykle zostaje ciężka i nietknięta. Uporządkowanie jej razem z konfiguracją motywu jest częścią naszych optymalizacji.







