Programación Web: Gestión de la caché

La memoria caché almacena páginas web en el dispositivo para que la próxima vez que se acceda, se cargue más rápido y reduzca el ancho de banda consumido. Los navegadores almacenan caché independienemente de la configuración de la web, pero existen distintos métodos para personalizar este comportamiento

1. Service Workers

Es el sistema más moderno y que va camino de convertirse en un estándar, tanto por las posibilidades que brinda para cachear contenido, como sus múltiples opciones para ejecutar trabajos en segundo plano, de forma independiente a la página web.

Los Service Workers sólo funcionan en sitios con protocolo HTTPS para evitar ataques de tipo man-in-the-middle.

A continuación, vamos a explicar como usar los Service Workers para poder usar una página web sin conexión a Internet:

  • Registramos el Service Worker, comprobando si el navegador soporta esta opción (se indica un archivo "sw.js" que es donde escribiremos cómo debe actuar el "trabajador"):
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
} else {
console.log('ServiceWorker is not allowed in this browser');
}
  • En el archivo sw.js (que es recomendable que se sitúe en la raíz del sitio, por la razón que se indicará más adelante), escribimos qué páginas queremos que cachee e instalamos (activamos) el Worker. Recuerda que no se pueden cachear elementos externos a la página:
var CACHE_NAME = 'lista-compra-v1';
var urlsToCache = [
'/',
'index.html',
'favicon.png',
'res/js/main.js',
'res/jquery/jquery-3.4.1.min.js',
'res/css/main.css',
'res/fontawesome/5.10.2/css/all.css',
'res/fontawesome/5.10.2/webfonts/fa-solid-900.ttf',
'res/fontawesome/5.10.2/webfonts/fa-solid-900.woff',
'res/fontawesome/5.10.2/webfonts/fa-solid-900.woff2'
];

self.addEventListener('install', function(event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
  • Ahora el Worker tiene que "escuchar" cuando se actualiza o se cambia de página para decidir si tiene que usar una versión en caché o (si no existe esa versión) hacer una petición normal al servidor. Si no hemos colocado el archivo en la raíz del sitio, no detectará los cambios de páginas que estén fuera de su carpeta:
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// Cache hit - return response
if (response) {
return response;
}
return fetch(event.request);
}
)
);
});
  • Con estos pasos ya estaría configurado el Service Worker. Si queremos actualizar la caché, tendremos que actualizar el archivo sw.js (de ahí la primera línea con la versión, para llevar un seguimiento sobre los cambios). Por otro lado, si nuestro sitio hace uso de bases de datos, tendremos que buscar una forma de guardar esos datos en el navegador para poder acceder a ellos cuando no haya conexión. Una forma bastante simple es descargando los datos a una base de datos del navegador, como LocalStorage. A continuación, voy a poner un ejemplo en la que la conexión a la base externa se hace a través de una petición ajax a una API (que permite que se puedan ejecutar acciones si no puede llevar a cabo dicha petición por no haber conexión):
$.ajax({
... //Parámetros de la petición a la API
}).done(function(data) { //Código si la petición prospera
...
localStorage.setItem(0, JSON.stringify(data));
...
}).fail(function(err) { //Código si la petición falla
let off_list = JSON.parse(localStorage.getItem(0));
...
})



2. ApplicationCache (HTML 5)

  • SE CONSIDERA UN SISTEMA ANTIGUO E INSEGURO Y PERDERÁ LA COMPATIBILIDAD CON LOS NAVEGADORES MÁS IMPORTANTES
  • Con HTML 5 se ha introducido una forma de poder navegar por una web sin conexión a Internet, indicándole que recursos se pueden utilizar “offline”.
  • Requiere páginas HTTPS.
  • Funciona a través de un “manifiesto”, que es el archivo que le dice al navegador que recursos descargar. La ruta al manifiesto se indica a través de la siguiente propiedad en la etiqueta <html> de cada página:
    • <html manifest="example.appcache">
  • El tipo MIME con el que se deben mostrar los archivos de manifiesto es text/cache-manifest. Puede que haya que añadirlo a la configuración de Apache:
    AddType text/cache-manifest .appcache
  • El contenido del manifiesto (incluye líneas opcionales) es el siguiente:
CACHE MANIFEST 
# 2010-06-18:v2
# Recursos que pueden accederse “offline”.
CACHE:
/favicon.ico
index.html
stylesheet.css
images/logo.png
scripts/main.js
# Recursos que requieren que el usuario esté en línea.
NETWORK:
login.php
/myapi
http://api.twitter.com
FALLBACK:
/main.py /static.html
images/large/ images/offline.jpg
*.html /offline.html

# static.html será servido si main.py es inaccesible
# offline.jpg será servido en lugar de las imágenes de images/large/
# offline.html será servido en lugar del resto de archivos .html
  • El tamaño total del contenido en caché no puede superar los 5 MB.
  • Para que el navegador actualize la caché, se tiene que modificar el manifiesto, de ahí el comentario con la fecha.

3. Memcached (para bases de datos)

  • Memcached es un sistema de caché para bases de datos, que evita el acceso frecuente a la base poniendo los datos en caché, cuyo acceso es más rápido.
  • Instalación del servidor Memcached (Ubuntu)
    • apt-get install memcached
  • Instalación del módulo para PHP
    • sudo pecl install memcached

4. APCu

  • Instalación:
    • sudo apt install php-apcu

5. Otros