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 przeglądarka może w dowolnym momencie usunąć poszczególne elementy z pamięci podręcznej, aby zrobić miejsce na inne. 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 korzystania z sieci.
  3. Odporność – jeśli witryna zostanie wyłączona z powodu konserwacji (np. ktoś przypadkowo coś zepsuje), użytkownicy będą mogli korzystać z funkcji 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 załaduje się i będzie działać prawidłowo, nawet jeśli użytkownik naciśnie przycisk odświeżania, gdy jest 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 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 podawać wszystkich stron w pliku manifestu. Jeśli strona wskazuje plik manifestu, nie ma sposobu, aby zapobiec zapisywaniu tej strony 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ą podobne narzędzia dla programistów.

Atrybut manifest może wskazywać bezwzględny lub względny adres URL, ale bezwzględny adres URL musi znajdować się w tym samym źródle 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 obsługiwać 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)

To wymaganie zostało usunięte ze specyfikacji jakiś czas temu i nie jest już wymagane w najnowszych wersjach przeglądarek Chrome, Safari i Firefox. Typ MIME będzie jednak wymagany do działania w starszych przeglądarkach i w IE11.

Struktura pliku manifestu

Manifest to oddzielny plik, do którego link podajesz 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 jest usuwana.
  • Jeśli nie uda się pobrać pliku manifestu lub określonego w nim zasobu, cały proces aktualizacji pamięci podręcznej zakończy się niepowodzeniem. W przypadku awarii przeglądarka korzysta ze 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 „#” są komentarzami, ale mogą też służyć do innych celów. Pamięć podręczna aplikacji jest aktualizowana tylko wtedy, gdy zmienia się jej 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 plik manifestu zmienił się podczas aktualizacji, możliwe, że przeglądarka pobrała niektóre pliki z jednej wersji, a inne z innej, dlatego nie stosuje pamięci podręcznej i później ponawia próbę.

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 sekcje: CACHE, NETWORK i FALLBACK.

CACHE:
To jest 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 określa zasób, a drugi jest używany w przypadku błędu lub błędu żądania 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 wyczyści pamięć przeglądarki na potrzeby witryny.
  2. Plik manifestu został zmodyfikowany. Uwaga: aktualizacja 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. Jego właściwość status przydaje się 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 funkcji 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, skonfiguruj listenera, 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ć, dostępne są dodatkowe zdarzenia służące do monitorowania stanu pamięci podręcznej. 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 przypadku takiej awarii przeglądarka będzie nadal używać starej pamięci podręcznej aplikacji.

Pliki referencyjne