• Strona główna
  • Curriculum Vitae
  • O mnie
  • Przykład: Gramatyka w PHP
  • Przykład: Kompresja CSS
  • Przykład: Kompresja JavaScript
  • Przykład: Skracanie linków
  • Przykład: Wykrywanie serwera HTTP
  • Przykład: Własna bramka SMS
  • Mapa strony
  • Kontakt
Niebieski Pomarańczowy Zielony Różowy Fioletowy

HTTP Expires w Apache

Opublikowane 13 czerwca 2010. Autor: Kamil Brenk. Wizyt: 6 399.

Kategorie: Apache
Tematyka: Apache, dyrektywa IfModule, mod_expires, optymalizacja serwisów, praktyczne skrypty, Protokół HTTP, wydajność serwisów internetowych

cze 13

Był wpis o ETag (protokół HTTP), teraz czas na alternatywne rozwiązanie buforowania w przeglądarce klienta. Mowa tutaj o nagłówku Expires, który pozwala na jeszcze efektywniejsze usprawnienie buforowania niż wcześniej omawiany nagłówek ETag.

Co robi nagłówek Expires w praktyce? Jak zautomatyzować dołączanie tego nagłówka do wszystkich obiektów pobieranych z serwera Apache? O tym w niniejszej notce.

Nagłówek Expires jest wysyłany przez serwer w nagłówkach HTTP do klienta (HTTP Responses). Wygląda on mniej więcej następująco:

1
Expires: Thu, 01 Dec 1994 16:00:00 GMT

Wartością tego nagłówku jest data ważności dokumentu przesyłanego do klienta (przeglądarki). Przeglądarka odczytuje tę datę – jeżeli data jest późniejsza niż obecna oraz przeglądarka posiada dany plik w buforze – odczytuje ten plik bezpośrednio z buforu (o ile taki posiada) i kończy komunikację z serwerem.

Dzięki temu zaoszczędzasz na transferze serwera, a klient otrzymuje obiekt bezpośrednio z buforu, co znacząco skróca czas wczytywania strony.

Expires vs ETag

Nagłówek ten jest o tyle lepszy od nagłówka ETag, iż nie wymaga sprawdzania aktualności plików w buforze i na serwerze, co zabierało sporo czasu.

Z drugiej strony jest to też wada, gdyż nie ma pewności, iż obiekt który otrzyma klient jest nadal aktualny.

Sam musisz ocenić dla których plików dać jaki nagłówek. Jedno jest pewne – jeżeli nie zamierzasz w najbliższych miesiącach zmienić danego obiektu (pliku graficznego, animacji) i dopuszczasz przechowywanie przez klienta tego pliku w buforze – nagłówek Expires będzie lepszym rozwiązaniem.

Musisz także wiedzieć, że wysyłając do klienta w odpowiedzi HTTP zarówno nagłówek ETag, jak i Expires – nagłówek ETag będzie miał pierwszeństwo i tym faktem będzie się kierowała przeglądarka.

Expires i Apache

Serwer Apache udostępnia specjalny moduł, który w sposób ekspresowy pozwala zająć się nagłówkiem Expires. Mowa oczywiście o mod_expires.

Stosowane przeze mnie ustawienia dla tego modułu wyglądają następująco (.htaccess):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<IfModule mod_expires.c>
    Header set cache-control: public
    ExpiresActive on
    ExpiresDefault "access plus 1 month"
    ExpiresByType text/html             "access plus 1 hour"
    ExpiresByType application/rss+xml   "access plus 1 hour"
    ExpiresByType image/png             "access plus 1 month"
    ExpiresByType image/jpg             "access plus 1 month"
    ExpiresByType image/jpeg            "access plus 1 month"
    ExpiresByType video/ogg             "access plus 1 month"
    ExpiresByType audio/ogg             "access plus 1 month"
    ExpiresByType video/mp4             "access plus 1 month"
    ExpiresByType image/x-icon          "access plus 1 year"
    ExpiresByType font/ttf              "access plus 1 year"
    ExpiresByType image/svg+xml         "access plus 1 year"
</IfModule>

Co tutaj się wyprawia? Najpierw użyta została wcześniej wspomniana dyrektywa IfModule. Sprawdza on, czy na danym serwerze został wbudowany moduł mod_ expires. Jeśli modułu brak, to kod zostaje pominięty.

Następnie wykorzystujemy dyrektywę Header do ustawienia nagłówka HTTP, jakim jest Cache-Control. Ma to na celu zmuszenie przeglądarek do korzystania z buforowania (jeśli mają taką funkcjonalność zaimplementowaną).

Gdyby nagłówek Cache-Control został ustawiony na wartość no-cache to inne nagłówki odpowiedzialne za buforowanie zostałyby zignorowane.

Następnie uruchamiamy moduł przez wpisanie dyrektywy:

1
ExpiresActive on

Kolejnym krokiem jest ustawienie domyślnej „daty ważności” dla wszystkich plików wczytywanych z serwera poprzez dodanie dyrektywy:

1
ExpiresDefault "access plus 1 month"

Powoduje to domyślne ustawienie dla wszystkich plików z serwera nagłówka Expires na bieżącą datę pobrania pliku z serwera + 1 miesiąc.

Kolejne dyrektywy ustawiają datę ważności dla wybranych typów plików (typ MIME). Powoduje to nadpisane domyślnych ustawień dla wybranych rodzajów plików, a robi się to w następujący sposób:

1
2
ExpiresByType text/html                 "access plus 1 hour"
ExpiresByType application/rss+xml       "access plus 1 hour"

Dokumenty HTML i XML (np. sitemap.xml, kanały RSS i Atom) są natomiast przechowywane przez 1 godzinę:

1
2
3
4
5
6
ExpiresByType image/png         "access plus 1 month"
ExpiresByType image/jpg         "access plus 1 month"
ExpiresByType image/jpeg        "access plus 1 month"
ExpiresByType video/ogg         "access plus 1 month"
ExpiresByType audio/ogg         "access plus 1 month"
ExpiresByType video/mp4         "access plus 1 month"

Pliki multimedialne oraz graficzne przechowywane są w buforze przez jeden miesiąc od czasu ostatniego pobrania:

1
2
3
ExpiresByType image/x-icon      "access plus 1 year"
ExpiresByType font/ttf          "access plus 1 year"
ExpiresByType image/svg+xml     "access plus 1 year"

Najdłużej w buforze przeglądarki są przechowywane pliki najrzadziej aktualizowane, czyli ikony (favicon.ico), pliki czcionek oraz grafika w formacie SVG.

Kilka słów podsumowania

I to by było na tyle. Niewiele trudu trzeba włożyć w to rozwiązanie, a może dać całkiem korzystne efekty dla każdej ze stron (klient & serwer).

Z drugiej strony, powyższe rozwiązanie jest niezbyt uniwersalne. Co jeśli serwerem nie będzie Apache? Jak więc widzisz, nie jest to idealne rozwiązanie. Czasem lepiej poświęcić trochę więcej czasu, napisać prostą klasę w PHP i mieć ustawianie nagłówków Expires (buforowania i innych) na poziomie języka, nie serwera.

Decyzja jednak należy do każdego indywidualnie. Będę jednak wdzięczny za podzielenie się sposobem wykorzystywanym przez innych programistów :-).

Komentarze (2)

  1. maly 25 grudnia 2010

    To co napisałeś o „no-cache” trochę gryzie się z tym, co mamy tutaj:
    http://pl.wikipedia.org/wiki/Lista_nag%C5%82%C3%B3wk%C3%B3w_HTTP#Cache-Control
    Z tego co napisałeś wnioskuję, że no-cache = no-store, a wiki mówi, że właśnie dla no-cache jest sprawdzana aktualność strony…

  2. Kamil Brenk 26 sierpnia 2011

    maly, przepraszam za tempo odpowiedzi, nie wiem jakim cudem przeoczyłem Twój komentarz.

    Zarówno no-cache, jak i no-store nie mogą pojawić się wraz z Expires z prostego powodu – jeden nie pozwala trzymać plików w buforze, a drugi każdorazowo każe sprawdzać aktualność pliku (czyli robi to samo co ETag i ma te same wady wydajnościowe). Dlatego też ważne jest, by nagłówek Cache-control ustawić na „public” :)



Kamil Brenk Blog

PHP, JavaScript, SQL, HTML

  • Informacje o blogu

    Kamil Brenk

    Blog o tworzeniu aplikacji na potrzeby sieci Web.

    Praktyczne przykłady, porady i sztuczki. PHP, SQL, AJAX, JavaScript, HTML i pochodne.

    Kanał RSS

    • Najnowsze
    • Komentarze
    • Popularne
    • Liczniki w CSS
    • Wyprzedaż książek o programowaniu!
    • Niestandardowy placeholder
    • JavaScript w modułach
    • Co dalej z blogiem?
    • Interaktywna mapa w HTML i CSS
    • Olsztyn: Jak wyseparować zawartość zassaną przez file_get_content?
    • ERMLAB: Od czegoś trzeba zacząć :) Wiele osób właśnie stawia na...
    • david: co nalezy wkleić na stronę aby plik ze stylami był ladowany...
    • krynicz: Nie jestem pewien czy dobrze to rozumiem: wpisujemy OG w...
    • yaro: Jak zmienić re_write znak "_" na "-"?
    • Piotr: stworzyłem prostą stronkę w PHP, czy jest możliwość aby...
    • MichalR: Super sprawa... bardzo przydatne.. dzieki i pozdrawiam..
    • Niestandardowe czcionki na stronie
    • Sposoby wczytywania JavaScript
    • Gramatyka w PHP, część 1
    • Umowa i zaliczka dla freelancera
    • Wysyłanie wiadomości SMS w PHP
    • Projekt aplikacji po stronie klienta
    • Własny mechanizm Feed
  • Szukajka
    Wpisz co chcesz wyszukać na stronie…
  • Kategorie
    • Apache
    • Freelancer
    • Front-end Development
    • HTML5 & CSS3
    • Inne
    • JavaScript
    • Książki
    • PHP
    • Po godzinach
    • Pozycjonowanie
    • Protokół HTTP
    • SQL
    • Wyrażenia regularne
  • Moje serwisy
    • Testy zawodowe
    • Miłość, uczucia i seks
  • Czytane blogi
    • Wojciech Sznapka
    • Wojciech Soczyński
    • Michał Wachowski
    • Tomasz Kowalczyk
    • Filip Górczyński
  • Strona główna
  • Curriculum Vitae
  • O mnie
  • Przykład: Gramatyka w PHP
  • Przykład: Kompresja CSS
  • Przykład: Kompresja JavaScript
  • Przykład: Skracanie linków
  • Przykład: Wykrywanie serwera HTTP
  • Przykład: Własna bramka SMS
  • Mapa strony
  • Kontakt

Kamil Brenk © 2010. All rights reserved.

Designed by FTL Wordpress Themes brought to you by Smashing Magazine.

Do góry ∧