Przewodnik dla początkujących na temat korzystania z pamięci podręcznej aplikacji

Wprowadzenie

Coraz większą rolę odgrywają aplikacje internetowe dostępne offline. Tak, wszystkie przeglądarki mogą przechowywać strony i zasoby w pamięci podręcznej przez długi czas, ale w dowolnym momencie mogą usunąć poszczególne elementy z pamięci podręcznej, aby zrobić miejsce na inne treści. HTML5 rozwiązuje niektóre problemy związane z brakiem połączenia z internetem dzięki interfejsowi ApplicationCache. Korzystanie z interfejsu pamięci podręcznej daje aplikacji 3 korzyści:

  1. Przeglądanie offline – użytkownicy mogą przeglądać całą witrynę, gdy są offline.
  2. Szybkość – zasoby pochodzą bezpośrednio z dysku, bez dostępu do sieci.
  3. Odporność – jeśli Twoja witryna przejdzie w tryb „konserwacji” (czyli ktoś przypadkowo wszystko zepsuje), użytkownicy będą mogli korzystać z niej w trybie offline.

Pamięć podręczna aplikacji (AppCache) pozwala deweloperowi określić, które pliki przeglądarka powinna zapisać w pamięci podręcznej i udostępnić użytkownikom offline. Aplikacja wczyta się i będzie działać prawidłowo, nawet jeśli użytkownik naciśnie przycisk odświeżania w trybie offline.

Plik manifestu pamięci podręcznej

Plik manifestu pamięci podręcznej to prosty plik tekstowy z listą zasobów, które przeglądarka powinna zapisać w pamięci podręcznej na potrzeby dostępu offline.

Odwoływanie się do pliku manifestu

Aby włączyć pamięć podręczną aplikacji, dodaj atrybut pliku manifestu do tagu html dokumentu:

<html manifest="example.appcache">
  ...
</html>

Atrybut manifest powinien znajdować się na każdej stronie aplikacji internetowej, którą chcesz przechowywać w pamięci podręcznej. Przeglądarka nie przechowuje w pamięci podręcznej strony, jeśli nie zawiera ona atrybutu manifest (chyba że jest on wyraźnie wymieniony w pliku manifestu). Oznacza to, że każda strona, na którą użytkownik przechodzi i która zawiera element manifest, zostanie dodana do pamięci podręcznej aplikacji. Dlatego nie musisz wymieniać wszystkich stron w pliku manifestu. Jeśli strona odwołuje się do pliku manifestu, nie można zapobiec umieszczeniu jej w pamięci podręcznej.

Aby zobaczyć adresy URL kontrolowane przez pamięć podręczną aplikacji, otwórz w Chrome stronę about://appcache-internals/. Tutaj możesz wyczyścić pamięć podręczną i wyświetlić wpisy. W Firefoksie są podobna narzędzia dla programistów.

Atrybut manifest może wskazywać bezwzględny adres URL lub ścieżkę względną, ale bezwzględny adres URL musi znajdować się w tej samej domenie co aplikacja internetowa. Plik manifestu może mieć dowolne rozszerzenie, ale musi być udostępniany z prawidłowym typem mime (patrz poniżej).

<html manifest="http://www.example.com/example.mf">
  ...
</html>

Plik manifestu musi być udostępniany z typem MIME text/cache-manifest. Może być konieczne dodanie niestandardowego typu pliku do konfiguracji serwera WWW lub .htaccess.

Aby na przykład serwować ten typ mime w Apache, dodaj ten wiersz do pliku konfiguracyjnego:

AddType text/cache-manifest .appcache

Możesz też w pliku app.yaml w Google App Engine:

- url: /mystaticdir/(.*\.appcache)
  static_files: mystaticdir/\1
  mime_type: text/cache-manifest
  upload: mystaticdir/(.*\.appcache)

Ten wymóg został niedawno wycofany ze specyfikacji i nie jest już wymagany w najnowszych wersjach Chrome, Safari i Firefox, ale w starszych przeglądarkach i IE11 będziesz potrzebować typu mime.

Struktura pliku manifestu

Plik manifestu to osobny plik, do którego linkujesz za pomocą atrybutu manifestu w elemencie HTML. Prosty plik manifest wygląda mniej więcej tak:

CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js
http://cdn.example.com/scripts/main.js

W tym przykładzie na stronie, która określa ten plik manifestu, zostaną zapisane w pamięci podręcznej 4 pliki.

Należy pamiętać o kilku kwestiach:

  • Ciąg znaków CACHE MANIFEST jest pierwszym wierszem i jest wymagany.
  • Pliki mogą pochodzić z innej domeny.
  • Niektóre przeglądarki nakładają ograniczenia na ilość miejsca na dane dostępnego dla Twojej aplikacji. Na przykład w Chrome pamięć podręczna korzysta z wspólnego puli tymczasowego miejsca na dane, z którego mogą korzystać inne interfejsy API w trybie offline. Jeśli piszesz aplikację na Chrome Web Store, użycie unlimitedStorage powoduje usunięcie tego ograniczenia.
  • Jeśli sam plik manifestu zwraca kod błędu 404 lub 410, pamięć podręczna zostaje usunięta.
  • Jeśli nie uda się pobrać pliku manifestu lub zasobu określonego w tym pliku, cały proces aktualizacji pamięci podręcznej zakończy się niepowodzeniem. W przypadku awarii przeglądarka będzie nadal używać starej pamięci podręcznej aplikacji.

Przyjrzyjmy się bardziej złożonemu przykładowi:

CACHE MANIFEST
# 2010-06-18:v2

# Explicitly cached 'master entries'.
CACHE:
/favicon.ico
index.html
stylesheet.css
images/logo.png
scripts/main.js

# Resources that require the user to be online.
NETWORK:
*

# static.html will be served if main.py is inaccessible
# offline.jpg will be served in place of all images in images/large/
# offline.html will be served in place of all other .html files
FALLBACK:
/main.py /static.html
images/large/ images/offline.jpg

Wiersze zaczynające się od znaku „#” to wiersze komentarza, ale mogą też służyć do innych celów. Pamięć podręczna aplikacji jest aktualizowana tylko wtedy, gdy zmienia się plik manifestu. Jeśli na przykład zmodyfikujesz zasób obrazu lub funkcję JavaScript, zmiany te nie zostaną ponownie zapisane w pamięci podręcznej. Aby poinformować przeglądarkę o konieczności odświeżenia plików w pamięci podręcznej, musisz zmodyfikować sam plik manifestu.

Unikaj używania ciągle aktualizowanej sygnatury czasowej lub losowego ciągu znaków, aby wymuszać aktualizacje za każdym razem. Podczas aktualizacji manifest jest sprawdzany dwukrotnie: raz na początku i raz po zaktualizowaniu wszystkich plików w pamięci podręcznej. Jeśli manifest zmienił się podczas aktualizacji, przeglądarka może pobrać niektóre pliki z jednej wersji, a inne z innej, więc nie zastosuje pamięci podręcznej i próbuje ponownie później.

Chociaż pamięć podręczna jest aktualizowana, przeglądarka nie będzie używać tych plików, dopóki strona nie zostanie odświeżona, ponieważ aktualizacje są wprowadzane po załadowaniu strony z bieżącej wersji pamięci podręcznej.

Plik manifestu może zawierać 3 odrębne sekcje: CACHE, NETWORK i FALLBACK.

CACHE:
To domyślna sekcja dla wpisów. Pliki wymienione w tym nagłówku (lub bezpośrednio po CACHE MANIFEST) będą wyraźnie zapisywane w pamięci podręcznej po pierwszym pobraniu. NETWORK:
Pliki wymienione w tej sekcji mogą pochodzić z sieci, jeśli nie znajdują się w pamięci podręcznej. W przeciwnym razie sieć nie jest używana, nawet jeśli użytkownik jest online. Możesz tutaj dodać do białej listy konkretne adresy URL lub po prostu wpisać „”, co spowoduje dodanie wszystkich adresów URL. Większość witryn wymaga użycia opcji „”.FALLBACK:
Opcjonalna sekcja określająca strony zastępcze, jeśli dany zasób jest niedostępny. Pierwszy identyfikator URI to zasób, drugi to identyfikator URI zastępczy używany w przypadku błędu lub błędu sieciowego. Oba identyfikatory URI muszą pochodzić z tego samego źródła co plik manifestu. Możesz rejestrować nie tylko konkretne adresy URL, ale też ich prefiksy. „images/large/” zarejestruje błędy z adresów URL takich jak „images/large/whatever/img.jpg”.

Poniższy plik manifestu definiuje stronę „catch-all” (offline.html), która będzie wyświetlana, gdy użytkownik spróbuje uzyskać dostęp do katalogu głównego witryny w trybie offline. Wyraźnie określa też, że wszystkie inne zasoby (np. te w witrynie zdalnej) wymagają połączenia z internetem.

CACHE MANIFEST
# 2010-06-18:v3

# Explicitly cached entries
index.html
css/style.css

# offline.html will be displayed if the user is offline
FALLBACK:
/ /offline.html

# All other resources (e.g. sites) require the user to be online.
NETWORK:
*

# Additional resources to cache
CACHE:
images/logo1.png
images/logo2.png
images/logo3.png

Aktualizowanie pamięci podręcznej

Gdy aplikacja jest offline, dane pozostają w pamięci podręcznej do momentu wystąpienia jednego z tych zdarzeń:

  1. Użytkownik czyści pamięć podręczną przeglądarki dla Twojej witryny.
  2. Plik manifestu został zmodyfikowany. Uwaga: zaktualizowanie pliku wymienionego w pliku manifestu nie oznacza, że przeglądarka ponownie zapisze ten zasób w pamięci podręcznej. Musisz zmienić sam plik manifestu.

Stan pamięci podręcznej

Obiekt window.applicationCache to Twój zautomatyzowany dostęp do pamięci podręcznej aplikacji przeglądarki. Właściwość status jest przydatna do sprawdzania bieżącego stanu pamięci podręcznej:

var appCache = window.applicationCache;

switch (appCache.status) {
case appCache.UNCACHED: // UNCACHED == 0
return 'UNCACHED';
break;
case appCache.IDLE: // IDLE == 1
return 'IDLE';
break;
case appCache.CHECKING: // CHECKING == 2
return 'CHECKING';
break;
case appCache.DOWNLOADING: // DOWNLOADING == 3
return 'DOWNLOADING';
break;
case appCache.UPDATEREADY:  // UPDATEREADY == 4
return 'UPDATEREADY';
break;
case appCache.OBSOLETE: // OBSOLETE == 5
return 'OBSOLETE';
break;
default:
return 'UKNOWN CACHE STATUS';
break;
};

Aby sprawdzić, czy manifest został zaktualizowany, wywołaj najpierw funkcję applicationCache.update(). Spowoduje to próbę zaktualizowania pamięci podręcznej użytkownika (co wymaga zmiany pliku manifestu). Na koniec, gdy applicationCache.status jest w stanie UPDATEREADY, wywołanie applicationCache.swapCache() spowoduje zastąpienie starej pamięci podręcznej nową.

var appCache = window.applicationCache;

appCache.update(); // Attempt to update the user's cache.

...

if (appCache.status == window.applicationCache.UPDATEREADY) {
appCache.swapCache();  // The fetch was successful, swap in the new cache.
}

Dobra wiadomość: możesz to zautomatyzować. Aby zaktualizować użytkowników do najnowszej wersji witryny, ustaw odbiornik, który będzie monitorować zdarzenie updateready podczas wczytywania strony:

// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {

window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
    // Browser downloaded a new app cache.
    if (confirm('A new version of this site is available. Load it?')) {
    window.location.reload();
    }
} else {
    // Manifest didn't changed. Nothing new to server.
}
}, false);

}, false);

Zdarzenia AppCache

Jak można się spodziewać, aby monitorować stan pamięci podręcznej, są dostępne dodatkowe zdarzenia. Przeglądarka wywołuje zdarzenia dotyczące m.in. postępu pobierania, aktualizacji pamięci podręcznej aplikacji i błędów. Ten fragment kodu konfiguruje odbiorniki zdarzeń dla każdego typu zdarzenia pamięci podręcznej:

function handleCacheEvent(e) {
//...
}

function handleCacheError(e) {
alert('Error: Cache failed to update!');
};

// Fired after the first cache of the manifest.
appCache.addEventListener('cached', handleCacheEvent, false);

// Checking for an update. Always the first event fired in the sequence.
appCache.addEventListener('checking', handleCacheEvent, false);

// An update was found. The browser is fetching resources.
appCache.addEventListener('downloading', handleCacheEvent, false);

// The manifest returns 404 or 410, the download failed,
// or the manifest changed while the download was in progress.
appCache.addEventListener('error', handleCacheError, false);

// Fired after the first download of the manifest.
appCache.addEventListener('noupdate', handleCacheEvent, false);

// Fired if the manifest file returns a 404 or 410.
// This results in the application cache being deleted.
appCache.addEventListener('obsolete', handleCacheEvent, false);

// Fired for each resource listed in the manifest as it is being fetched.
appCache.addEventListener('progress', handleCacheEvent, false);

// Fired when the manifest resources have been newly redownloaded.
appCache.addEventListener('updateready', handleCacheEvent, false);

Jeśli nie uda się pobrać pliku manifestu lub zasobu określonego w tym pliku, cała aktualizacja zakończy się niepowodzeniem. W takim przypadku przeglądarka będzie nadal używać starej pamięci podręcznej aplikacji.

Odniesienia