Almacenamiento de datos en el dispositivo
Las aplicaciones web progresivas (PWA) ofrecen opciones sólidas para almacenar datos localmente para permitir a los usuarios seguir trabajando incluso si la conexión de red se vuelve inestable o se queda sin conexión.
Hay varias maneras en las que un PWA puede almacenar datos en un dispositivo, como el almacenamiento local, la API de caché o IndexedDB.
En la tabla siguiente se describen las distintas opciones y el resto de este artículo incluye más detalles y escenarios de uso para cada opción.
Opción de almacenamiento | Descripción |
---|---|
Almacenamiento web | Web Storage tiene dos tipos: sesión y local. El almacenamiento web es útil para almacenar pequeñas cantidades de datos del código front-end de la aplicación. Los datos se estructuran como pares clave-valor y solo están disponibles para el origen de la aplicación actual. En el caso del almacenamiento de sesión, los datos se borran cuando finaliza la sesión, por ejemplo, cuando se cierra la aplicación o cuando el usuario busca otro origen en la misma ventana o pestaña. El almacenamiento local persiste hasta que la aplicación quita los datos. |
IndexadoDB | IndexedDB es una API para almacenar grandes cantidades de datos estructurados. La API es asincrónica y se puede usar tanto desde el código front-end de la aplicación como desde el código de trabajo del servicio. Use indexedDB API para almacenar una cantidad significativa de datos estructurados en el cliente o datos binarios, como archivos o objetos multimedia cifrados. |
Caché | La API de caché se puede usar para administrar los recursos almacenados en caché. Cache API se basa en Promise y permite a los desarrolladores almacenar y recuperar muchos recursos web: HTML, CSS, JavaScript, imágenes, JSON, etc. Normalmente, la API de caché se usa en el contexto de un trabajo de servicio, pero también está disponible para el código front-end de la aplicación. |
Acceso al sistema de archivos | La API de acceso del sistema de archivos permite a la PWA leer archivos y carpetas en el dispositivo del usuario y guardar los cambios en ellos. |
Nota: No use WebSQL ni La caché de aplicaciones. Aunque estos son otros dos mecanismos de almacenamiento del explorador, ambos han quedado en desuso. En lugar de WebSQL, use IndexedDB. En lugar de caché de aplicaciones, use la API de caché.
Almacenamiento web
El almacenamiento web es útil para almacenar pequeñas cantidades de datos de cadena en el dispositivo del usuario. La simplicidad del sistema de par clave-valor de Web Storage facilita su uso.
Web Storage funciona sincrónicamente solo en el subproceso principal de la aplicación. Esto significa que El almacenamiento web no está disponible para su uso dentro de los trabajadores del servicio y que el uso intensivo de Web Storage puede crear problemas de rendimiento para la aplicación.
Cada tipo de almacenamiento web, de sesión y local, se mantiene como un almacén de datos independiente que está aislado en el dominio que lo creó.
-
sessionStorage
solo se conserva durante la sesión, por ejemplo, mientras el explorador está abierto, lo que incluye cuándo se actualiza la página. -
localStorage
se conserva hasta que el código de la aplicación, el usuario o el explorador quitan los datos.
En el código siguiente se muestra cómo usar localStorage
, que es similar a cómo sessionStorage
se usa:
const browserInformation = {
name: 'Microsoft Edge',
version: 108
};
localStorage.setItem('browser', JSON.stringify(browserInformation));
El código anterior almacena un objeto JavaScript como una cadena JSON en localStorage
mediante el setItem()
método y asigna una clave igual a browser
. Puede recuperar la información de localStorage
mediante el getItem()
método como se muestra a continuación:
const value = localStorage.getItem('browser');
const browserInformation = JSON.parse(value);
Para más información, consulte Api de almacenamiento web en MDN.
IndexadoDB
IndexedDB es una API asincrónica para almacenar datos estructurados que se pueden usar en el código front-end o el código de trabajo de servicio de la aplicación. Use indexedDB API para almacenar una cantidad significativa de datos estructurados en el cliente o datos binarios, como archivos o objetos multimedia cifrados.
IndexedDB es la mejor opción para almacenar datos en la PWA, ya que el uso de la API no ralentiza la aplicación bloqueando el subproceso principal y se puede usar tanto desde el código front-end de la aplicación como desde el trabajo de servicio.
El uso de IndexedDB es más complejo que el uso de Web Storage y requiere los pasos siguientes para almacenar datos:
- Abra una base de datos mediante la
window.indexedDB.open()
función . - Cree un almacén de objetos en la base de datos mediante la
IDBDatabase.createObjectStore()
función . - Inicie una transacción para almacenar datos mediante la
IDBDatabase.transaction()
función . - Espere a que se complete la operación, escuchando un evento.
Para obtener más información y ver ejemplos de código, consulte Uso de IndexedDB en MDN.
Caché
Cache API es un sistema para almacenar y recuperar solicitudes y respuestas de red en el código front-end o el trabajo de servicio de la aplicación. Se puede usar para almacenar recursos, como imágenes y archivos, localmente en el dispositivo del usuario. Esto puede hacer que la aplicación funcione incluso cuando está sin conexión o mejorar su rendimiento al reducir el número de solicitudes de red necesarias para representar la aplicación.
El siguiente fragmento de código muestra cómo escuchar el fetch
evento en un trabajo de servicio y almacenar la respuesta del servidor mediante la API de caché:
self.addEventListener("fetch", event => {
async function cacheAndReturnRequest() {
// Get the response from the server.
const fetchResponse = await fetch(event.request.url);
// Open the app's cache.
const cache = await caches.open("cache-name");
// Put the response in cache.
cache.put(event.request.url, fetchResponse.clone());
// And return the response.
return fetchResponse.
}
event.respondWith(cacheAndReturnRequest());
});
Para detectar otros escenarios útiles de Cache API, consulte Uso de un trabajo de servicio para administrar solicitudes de red.
Acceso al sistema de archivos
La API de acceso al sistema de archivos permite que la aplicación acceda a los archivos del dispositivo del usuario de forma similar a las aplicaciones nativas. Se puede usar para crear aplicaciones que puedan leer y escribir archivos, como editores de texto o imágenes.
Para abrir un archivo desde el dispositivo del usuario, use la showOpenFilePicker()
función :
openFileButton.addEventListener("click", async () => {
const fileHandles = await window.showOpenFilePicker();
});
Para obtener más información, vea Window.showOpenFilePicker() en MDN.
La API de acceso del sistema de archivos también se puede combinar con la característica de control de archivos PWA para registrar la aplicación como un controlador de tipos de archivo específicos y, por tanto, se siente más nativa para los usuarios. Para más información, consulte Control de archivos en Aplicaciones web progresivas.
La API de acceso del sistema de archivos privada de origen es una variación de la API de acceso al sistema de archivos que está diseñada para proporcionar más privacidad a los usuarios. También permite a las aplicaciones acceder a los archivos del dispositivo del usuario, pero solo dentro de un directorio específico que es privado para el origen de la aplicación. Además, esta API no está pensada para facilitar a los usuarios el acceso al directorio privado mediante el explorador de archivos.
Para abrir un archivo desde el sistema de archivos privados de origen, use la navigator.storage
API basada en Promise:
// Get the origin-private directory handle.
const root = await navigator.storage.getDirectory();
// Get the handle for a file in the directory.
const fileHandle = await root.getFileHandle("my-file.txt");
Cuota de almacenamiento
En Microsoft Edge, el almacenamiento local y de sesión se limita a unos 5 MB cada uno.
Otros tipos de almacenamiento de datos, como IndexedDB, Cache API o Origin Private File System Access API, pueden usar hasta el 60 % del espacio total en disco en el dispositivo. Por ejemplo, si el dispositivo en el que se ejecuta la aplicación tiene un disco de 64 GB, Microsoft Edge permite que la aplicación almacene hasta unos 38 GB de datos.
Tenga en cuenta que el espacio libre que realmente está disponible en el dispositivo puede ser menor que la cuota de almacenamiento del 60 %. Por ejemplo, si el dispositivo en el que se ejecuta la aplicación tiene un disco de 64 GB, pero el sistema operativo y otros archivos ya usan 50 GB, la aplicación solo podrá almacenar 14 GB de datos, incluso si la cuota de almacenamiento sigue siendo de 38 GB.
Puede usar navigator.storage.estimate()
para preguntar a la API de Storage Manager cuál es la cuota de almacenamiento para el origen de la aplicación y cuánto de ella ya se usa. Para obtener más información, consulte StorageManager.estimate() en MDN.
Al intentar almacenar más datos de los que están disponibles o permitidos, se produce un error de JavaScript. El código debe detectar este error mediante try...catch
instrucciones . En el fragmento de código siguiente se muestra cómo detectar un error de cuota superada al almacenar datos mediante Web Storage:
try {
localStorage.setItem('foo', 'bar');
} catch (e) {
// Code that handles the lack of storage space.
}
Expulsión de datos
Cuando el dispositivo del usuario comienza a tener poco espacio en disco disponible, también conocido como presión de almacenamiento, Microsoft Edge comenzará a expulsar datos no persistentes.
Esto significa que los datos almacenados por la aplicación mediante la API de caché, IndexedDB, la API de acceso del sistema de archivos privado de Origen o El almacenamiento web podrían ser desalojados.
De forma predeterminada, los datos que almacena la aplicación no se consideran persistentes y se pueden expulsar cuando hay presión de almacenamiento. Si la aplicación almacena datos críticos, usa la función para que el navigator.storage.persist()
almacenamiento de la aplicación sea persistente. El usuario solo puede borrar el almacenamiento persistente. Para más información, consulte StorageManager.persist() en MDN.