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

Wstęp

Dostęp do aplikacji internetowych w trybie offline staje się coraz ważniejszy. Tak. Jeśli tak jest, wszystkie przeglądarki mogą buforować strony i zasoby na dłuższy czas, ale przeglądarka może w każdej chwili wyrzucić poszczególne elementy z pamięci podręcznej, by zrobić miejsce na inne rzeczy. Format HTML5 eliminuje niektóre niedogodności związane z brakiem połączenia z internetem za pomocą interfejsu ApplicationCache. Korzystanie z interfejsu pamięci podręcznej zapewnia aplikacji 3 korzyści:

  1. Przeglądanie offline – użytkownicy mogą poruszać się po całej witrynie, gdy są offline
  2. Szybkość – zasoby pochodzą bezpośrednio z dysku, bez przechodzenia do sieci.
  3. Odporność – jeśli witryna przestanie działać z powodu „konserwacji” (jak np. ktoś przypadkowo zepsuje wszystko), użytkownicy będą mogli korzystać z trybu offline

Pamięć podręczna aplikacji (lub AppCache) umożliwia deweloperowi określenie, które pliki przeglądarka ma buforować i udostępniać 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 zawierający listę zasobów, które przeglądarka powinna buforować w celu 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 być zawarty na każdej stronie aplikacji internetowej, którą chcesz przechowywać w pamięci podręcznej. Przeglądarka nie zapisuje strony w pamięci podręcznej, 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ą przejdzie użytkownik, zawierająca element manifest, zostanie domyślnie dodana do pamięci podręcznej aplikacji. Nie musisz więc wymieniać każdej strony w pliku manifestu. Jeśli strona wskazuje na plik manifestu, nie możesz zapobiec buforowaniu.

Aby zobaczyć URL-e kontrolowane przez pamięć podręczną aplikacji, wejdź na stronę about://appcache-internals/ w Chrome. Tutaj możesz wyczyścić pamięć podręczną i wyświetlić wpisy. W przeglądarce Firefox są podobne 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 pochodzić z tego samego pochodzenia 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. Konieczne może być dodanie niestandardowego typu pliku do serwera WWW lub konfiguracji .htaccess.

Aby na przykład udostępniać ten typ MIME na serwerze Apache, dodaj ten wiersz do pliku konfiguracyjnego:

AddType text/cache-manifest .appcache

Lub 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 oraz Firefox, ale typ MIME będzie potrzebny do działania w starszych przeglądarkach i przeglądarkach IE11.

Struktura pliku manifestu

Plik manifestu to oddzielny plik, do którego prowadzi się link za pomocą atrybutu manifestu w elemencie html. Prosty plik manifestu 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 zostaną umieszczone w pamięci podręcznej 4 pliki na stronie określające ten plik manifestu.

Pamiętaj o dwóch kwestiach:

  • Ciąg CACHE MANIFEST to pierwszy wiersz i jest wymagany.
  • Pliki mogą pochodzić z innej domeny
  • Niektóre przeglądarki nakładają ograniczenia na ilość miejsca dostępnego dla aplikacji. Na przykład w Chrome AppCache korzysta z puli współdzielonej pamięci TYMCZASOWEJ, którą mogą współdzielić inne interfejsy API offline. Jeśli tworzysz aplikację dla Chrome Web Store, użycie unlimitedStorage usunie to ograniczenie.
  • Jeśli sam plik manifestu zwraca kod 404 lub 410, pamięć podręczna jest usuwana.
  • Jeśli nie uda się pobrać wskazanego pliku manifestu lub zasobu, cały proces aktualizacji pamięci podręcznej się nie powiedzie. W przypadku awarii przeglądarka będzie nadal używać starej pamięci podręcznej aplikacji.

Przeanalizujmy bardziej złożony przykład:

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 rozpoczynające się znakiem „#” to wiersze komentarza, ale mogą też służyć do innych celów. Pamięć podręczna aplikacji jest aktualizowana tylko w przypadku zmiany pliku manifestu. Jeśli na przykład zmodyfikujesz zasób graficzny lub zmienisz funkcję JavaScriptu, te zmiany nie zostaną ponownie zapisane w pamięci podręcznej. Musisz zmodyfikować plik manifestu, aby poinformować przeglądarkę, że ma odświeżyć pliki w pamięci podręcznej.

Unikaj ciągłego aktualizowania sygnatury czasowej lub losowego ciągu znaków, aby wymuszać aktualizację za każdym razem. Podczas aktualizacji plik manifestu jest sprawdzany dwukrotnie: raz na początku i po zaktualizowaniu wszystkich plików w pamięci podręcznej. Jeśli podczas aktualizacji plik manifestu zmienił się, możliwe, że przeglądarka pobrała niektóre pliki z jednej wersji, a inne z innej. Dlatego nie wykorzystuje pamięci podręcznej i ponawia próby później.

Mimo że pamięć podręczna jest aktualizowana, przeglądarka nie będzie używać tych plików do czasu odświeżenia strony, ponieważ aktualizacje są przeprowadzane już po wczytaniu strony z bieżącej wersji pamięci podręcznej.

Plik manifestu może się składać z 3 różnych sekcji: CACHE, NETWORK i FALLBACK.

CACHE:
To jest domyślna sekcja wpisów. Pliki wymienione pod tym nagłówkiem (lub bezpośrednio po elemencie CACHE MANIFEST) są 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 umieścić konkretne adresy URL na białej liście lub po prostu dodać „”, co oznacza, że dozwolone są wszystkie adresy URL. Większość witryn potrzebuje „”. FALLBACK:
Opcjonalna sekcja określająca strony zastępcze na wypadek niedostępności zasobu. Pierwszy identyfikator URI jest zasobem, a drugi – adres zastępczy używany w przypadku niepowodzenia lub błędu żądania sieciowego. Oba identyfikatory URI muszą pochodzić z tego samego źródła co plik manifestu. Możesz przechwytywać konkretne adresy URL, ale także prefiksy adresów URL. Wartość „images/large/” rejestruje błędy z adresów URL takich jak „obrazy/duży/cokolwiek/obraz.jpg”.

Poniższy plik manifestu określa stronę typu „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. Deklaruje ona również, że wszystkie inne zasoby (np. te znajdujące się zdalnie w witrynie) 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

Po przejściu do trybu offline aplikacja pozostaje w pamięci podręcznej do czasu wystąpienia jednego z następujących zdarzeń:

  1. Użytkownik wyczyści pamięć przeglądarki związaną z Twoją witryną.
  2. Plik manifestu został zmodyfikowany. Uwaga: zaktualizowanie pliku wymienionego w pliku manifestu nie oznacza, że przeglądarka ponownie zapisze zasób w pamięci podręcznej. Plik manifestu musi zostać zmieniony.

Stan pamięci podręcznej

Obiekt window.applicationCache zapewnia programowy dostęp do pamięci podręcznej przeglądarki przeglądarki. 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 programowo sprawdzić dostępność aktualizacji pliku manifestu, najpierw wywołaj applicationCache.update(). Spowoduje to próbę zaktualizowania pamięci podręcznej użytkownika (co wymaga zmiany pliku manifestu). Gdy applicationCache.status znajdzie się w stanie UPDATEREADY, wywołanie metody 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ść jest taka, że to wszystko można zautomatyzować. Aby aktualizować użytkowników do najnowszej wersji witryny, skonfiguruj detektor do monitorowania zdarzenia 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ć, dodatkowe zdarzenia są udostępniane na potrzeby monitorowania stanu pamięci podręcznej. Przeglądarka uruchamia zdarzenia takie jak postęp pobierania, aktualizacja pamięci podręcznej aplikacji czy warunki błędu. Ten fragment kodu pozwala skonfigurować detektory zdarzeń dla każdego typu zdarzeń 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 określonego w nim zasobu, cała aktualizacja się nie powiedzie. W przypadku takiego błędu przeglądarka będzie nadal korzystać ze starej pamięci podręcznej aplikacji.

Odniesienia