diff options
| author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:45 -0500 |
|---|---|---|
| committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:45 -0500 |
| commit | 1109132f09d75da9a28b649c7677bb6ce07c40c0 (patch) | |
| tree | 0dd8b084480983cf9f9680e8aedb92782a921b13 /files/es/web/progressive_web_apps | |
| parent | 4b1a9203c547c019fc5398082ae19a3f3d4c3efe (diff) | |
| download | translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.tar.gz translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.tar.bz2 translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.zip | |
initial commit
Diffstat (limited to 'files/es/web/progressive_web_apps')
10 files changed, 1543 insertions, 0 deletions
diff --git a/files/es/web/progressive_web_apps/app_structure/index.html b/files/es/web/progressive_web_apps/app_structure/index.html new file mode 100644 index 0000000000..fb6e6b812c --- /dev/null +++ b/files/es/web/progressive_web_apps/app_structure/index.html @@ -0,0 +1,286 @@ +--- +title: Estructura de una aplicación web progresiva +slug: Web/Progressive_web_apps/App_structure +tags: + - Estructura + - Intérprete de la aplicación + - PWAs + - Servicio workers + - Streams + - Transmisiones + - aplicaciones web progresivas + - js13kGames + - progresiva +translation_of: Web/Progressive_web_apps/App_structure +--- +<div>{{PreviousMenuNext("Web/Progressive_web_apps/Introduction", "Web/Progressive_web_apps/Offline_Service_workers", "Web/Progressive_web_apps")}}</div> + +<p class="summary">Ahora que conoces la teoría detrás de las PWAs, veamos la estructura recomendada de una aplicación real. Comenzaremos analizando la aplicación <a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a>, veamos por qué está construida de esa manera y qué beneficios aporta.</p> + +<h2 id="Arquitectura_de_una_aplicación">Arquitectura de una aplicación</h2> + +<p>Hay dos principales y diferentes enfoques para representar un sitio web — en el servidor o en el cliente. Ambos tienen sus ventajas y desventajas, y puedes combinar los dos enfoques hasta cierto punto.</p> + +<ul> + <li>La representación del lado del servidor (SSR) significa que un sitio web se representa en el servidor, por lo que ofrece una primera carga más rápida, pero navegar entre páginas requiere descargar contenido HTML nuevo. Funciona muy bien en todos los navegadores, pero adolece en términos de tiempo de navegación entre páginas y, por lo tanto, rendimiento percibido general — cargar una página requiere un nuevo viaje de ida y vuelta al servidor.</li> + <li>La representación de lado del cliente (CSR) permite que el sitio web se actualice en el navegador casi instantáneamente cuando se navega a diferentes páginas, pero requiere más de un golpe de descarga inicial y una representación adicional en el cliente al principio. El sitio web es más lento en una visita inicial, pero puede ser más rápido para navegar.</li> +</ul> + +<p>La combinación de SSR con CSR puede generar los mejores resultados: puedes representar un sitio web en el servidor, almacenar en caché su contenido y luego actualizar la representación en el lado del cliente cuando sea necesario. La carga de la primera página es rápida debido al SSR y la navegación entre páginas es fluida porque el cliente puede volver a renderizar la página solo con las partes que han cambiado.</p> + +<p>Las PWAs se pueden crear utilizando cualquier enfoque que desees, pero algunas funcionarán mejor que otras. El enfoque más popular es el concepto de "intérprete de la aplicación", que combina SSR y CSR exactamente de la manera descrita anteriormente, y además sigue la metodología "fuera de línea primero" que explicaremos en detalle en los próximos artículos y utilizaremos en nuestra aplicación de ejemplo. También hay un nuevo enfoque que involucra la {{web.link("/es/docs/Web/API/Streams_API", "API Streams")}}, que mencionaremos brevemente.</p> + +<h2 id="Intérprete_de_la_aplicación">Intérprete de la aplicación</h2> + +<p>El concepto de intérprete de la aplicación se ocupa de cargar una interfaz de usuario mínima lo antes posible y luego almacenarla en caché para que esté disponible sin conexión para visitas posteriores antes de cargar todo el contenido de la aplicación. De esa manera, la próxima vez que alguien visite la aplicación desde el dispositivo, la interfaz de usuario se cargará desde la caché de inmediato y se solicitará cualquier contenido nuevo del servidor (si aún no está disponible en la caché).</p> + +<p>Esta estructura es rápida y también se siente rápida, ya que el usuario ve "algo" instantáneamente, en lugar de una ruleta de carga o una página en blanco. También permite que el sitio web sea accesible sin conexión si la conexión de red no está disponible.</p> + +<p>Podemos controlar lo que se solicita del servidor y lo que se recupera de la caché con un {{web.link("/es/docs/Web/API/Service_Worker_API", "servicio worker")}}, que se explicará en detalle en el próximo artículo, por ahora centrémonos en la estructura en sí misma.</p> + +<h3 id="¿Por_qué_debería_usarla">¿Por qué debería usarla?</h3> + +<p>Esta arquitectura permite que un sitio web se beneficie al máximo de todas las funciones de PWA — almacena en caché el intérprete de la aplicación y administra el contenido dinámico de una manera que mejora enormemente el rendimiento. Además del intérprete básico, puedes agregar otras funciones como {{web.link("/es/docs/Web/Progressive_web_apps/Add_to_home_screen", "agregar a la pantalla de inicio")}} o {{web.link("/es/docs/Web/API/Push_API", "notificaciones push")}}, con la certeza de que la aplicación seguirá funcionando correctamente si no son compatibles con el navegador del usuario — esta es la belleza de la mejora progresiva.</p> + +<p>El sitio web se siente como una aplicación nativa con interacción instantánea y un rendimiento sólido, al tiempo que conserva todos los beneficios de la web.</p> + +<h3 id="Ser_enlazable_progresiva_y_adaptable_por_diseño">Ser enlazable, progresiva y adaptable por diseño</h3> + +<p>Es importante recordar las ventajas de PWA y tenerlas en cuenta al diseñar la aplicación. El enfoque del intérprete de la aplicación permite que los sitios web sean:</p> + +<ul> + <li>Enlazable: aunque se comporta como una aplicación nativa, sigue siendo un sitio web; puedes hacer clic en los enlaces dentro de la página y enviar una URL a alguien si deseas compartirla.</li> + <li>Progresiva: comienza con el "buen, antiguo sitio web básico" y agrega progresivamente nuevas funciones mientras recuerdas detectar si están disponibles en el navegador y manejas con elegancia cualquier error que surja si no hay soporte disponible. Por ejemplo, un modo fuera de línea con la ayuda del servicio <em>workers</em> es solo un rasgo adicional que mejora la experiencia del sitio web, pero aún se puede usar perfectamente sin él.</li> + <li>Adaptable: El diseño web adaptable también se aplica a las aplicaciones web progresivas, ya que ambas son principalmente para dispositivos móviles. Hay una gran variedad de dispositivos con navegadores — es importante preparar tu sitio web para que funcione en diferentes tamaños de pantalla, ventanas gráficas o densidades de píxeles, utilizando tecnologías como {{web.link("/es/docs/Mozilla/Mobile/Viewport_meta_tag", "metaetiqueta de la ventana gráfica")}}, {{web.link("/es/docs/Web/CSS/Media_Queries/Using_media_queries", "consultas de medios CSS")}}, {{web.link("/es/docs/Web/CSS/CSS_Flexible_Box_Layout", "Flexbox")}} y {{web.link("/es/docs/Web/CSS/CSS_Grid_Layout", "Rejilla CSS")}}.</li> +</ul> + +<h2 id="Concepto_diferente_streams_o_transmisiones">Concepto diferente: <em>streams</em> o transmisiones</h2> + +<p>Se puede lograr un enfoque completamente diferente para la representación del lado del servidor o del cliente con la {{web.link("/es/docs/Web/API/Streams_API", "API Streams")}}. Con un poco de ayuda del servicio <em>workers</em>, las transmisiones pueden mejorar en gran medida la forma en que analizamos el contenido.</p> + +<p>El modelo de intérprete de la aplicación requiere que todos los recursos estén disponibles antes de que el sitio web pueda comenzar a renderizarse. Es diferente con HTML, ya que el navegador ya está transmitiendo los datos y puede ver cuándo se cargan y procesan los elementos en el sitio web. Sin embargo, para que JavaScript esté "operativo", se debe descargar en su totalidad.</p> + +<p>La API de <em>Streams</em> permite a los desarrolladores tener acceso directo a la transmisión de datos desde el servidor — si deseas realizar una operación en los datos (por ejemplo, agregar un filtro a un video), ya no necesitas esperar a que se complete la descarga y convertirla en un blob (o lo que sea) — puedes comenzar de inmediato. Proporciona un control detallado: la transmisión se puede iniciar, encadenar con otra transmisión, cancelar, verificar errores y más.</p> + +<p>En teoría, la transmisión es un mejor modelo, pero también es más complejo, y en el momento de redactar este artículo (marzo de 2018), la API de <em>Streams</em> todavía está en proceso y aún no está completamente disponible en ninguno de los principales navegadores. Cuando esté disponible, será la forma más rápida de servir el contenido — los beneficios serán enormes en términos de rendimiento.</p> + +<p>Para obtener ejemplos trabajando y más información, consulta la {{web.link("/es/docs/Web/API/Streams_API", "documentación de la API de Streams")}}.</p> + +<h2 id="Estructura_de_nuestra_aplicación_de_ejemplo">Estructura de nuestra aplicación de ejemplo</h2> + +<p>La estructura del sitio web <a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a> es bastante simple: consta de un solo archivo HTML (<a href="https://github.com/mdn/pwa-examples/blob/master/js13kpwa/index.html">index.html</a>) con estilo CSS básico (<a href="https://github.com/mdn/pwa-examples/blob/master/js13kpwa/style.css">style.css</a>) y algunas imágenes, scripts y tipos de letra. La estructura de la carpeta se ve así:</p> + +<p><img alt="Estructura del directorio de js13kPWA." src="https://mdn.mozillademos.org/files/15925/js13kpwa-directory.png" style="border-style: solid; border-width: 1px; display: block; height: 356px; margin: 0px auto; width: 320px;"></p> + +<h3 id="El_HTML">El HTML</h3> + +<p>Desde el punto de vista HTML, el intérprete de la aplicación es todo lo que está fuera de la sección de contenido:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>js13kGames — Entradas del marco A</title> + <meta name="description" content="Una lista de las entradas del marco A enviadas a la competencia js13kGames 2017, que se utiliza como ejemplo para los artículos de MDN sobre Aplicaciones Web Progresivas"> + <meta name="author" content="end3r"> + <meta name="theme-color" content="#B12A34"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta property="og:image" content="icons/icon-512.png"> + <link rel="shortcut icon" href="favicon.ico"> + <link rel="stylesheet" href="style.css"> + <link rel="manifest" href="js13kpwa.webmanifest"> + <script src="data/games.js" defer></script> + <script src="app.js" defer></script> +</head> +<body> +<header> + <p><a class="logo" href="http://js13kgames.com"><img src="img/js13kgames.png" alt="js13kGames"></a></p> +</header> +<main> + <h1>js13kGames — Entradas del marco A</h1> + <p class="description">Lista de juegos enviada a <a href="http://js13kgames.com/aframe">categoría Marco A</a> en la competencia de <a href="http://2017.js13kgames.com">js13kGames 2017</a>. Puedes <a href="https://github.com/mdn/pwa-examples/blob/master/js13kpwa">bifurcar js13kPWA en GitHub</a> para revisar su código fuente.</p> + <button id="notifications">Solicitar notificaciones ficticias</button> + <section id="content"> + // Contenido insertado aquí + </section> +</main> +<footer> + <p>© js13kGames 2012-2020, creado y mantenido por <a href="http://end3r.com">Andrzej Mazur</a> de <a href="http://enclavegames.com">Enclave Games</a>.</p> +</footer> +</body> +</html></pre> + +<p>La sección {{HTMLElement("head")}} contiene información básica como título, descripción y enlaces a CSS, manifiesto web, archivo JS de contenido de juegos y app.js; ahí es donde se inicia nuestra aplicación JavaScript. El {{HTMLElement("body")}} se divide en {{HTMLElement("header")}} (que contiene la imagen vinculada), {{HTMLElement("main")}} de la página (con título, descripción y lugar para el contenido) y {{HTMLElement("footer")}} (derechos de autor y enlaces).</p> + +<p>El único trabajo de la aplicación es enumerar todas las entradas del Marco A de la competencia js13kGames 2017. Como puedes ver, es un sitio web muy común de una página — el objetivo es tener algo simple para que podamos centrarnos en la implementación de las características reales de PWA.</p> + +<h3 id="El_CSS">El CSS</h3> + +<p>El CSS también es lo más sencillo posible: usa {{CSSxRef("@font-face")}} para cargar y usar un tipo de letra personalizado, y aplica un estilo simple de los elementos HTML. El enfoque general es que el diseño se vea bien tanto en dispositivos móviles (con un enfoque de diseño web adaptable) como en dispositivos de escritorio.</p> + +<h3 id="El_main_de_la_aplicación_JavaScript">El <code>main</code> de la aplicación JavaScript</h3> + +<p>El archivo <code>app.js</code> hace algunas cosas que veremos de cerca en los próximos artículos. En primer lugar, genera el contenido en base a esta plantilla:</p> + +<pre class="brush: js notranslate">var template = "<article>\n\ + <img src='data/img/SLUG.jpg' alt='NAME'>\n\ + <h3>#POS. NAME</h3>\n\ + <ul>\n\ + <li><span>Author:</span> <strong>AUTHOR</strong></li>\n\ + <li><span>Twitter:</span> <a href='https://twitter.com/TWITTER'>@TWITTER</a></li>\n\ + <li><span>Website:</span> <a href='http://WEBSITE/'>WEBSITE</a></li>\n\ + <li><span>GitHub:</span> <a href='https://GITHUB'>GITHUB</a></li>\n\ + <li><span>More:</span> <a href='http://js13kgames.com/entries/SLUG'>js13kgames.com/entries/SLUG</a></li>\n\ + </ul>\n\ +</article>"; +var content = ''; +for(var i=0; i<games.length; i++) { + var entry = template.replace(/POS/g,(i+1)) + .replace(/SLUG/g,games[i].slug) + .replace(/NAME/g,games[i].name) + .replace(/AUTHOR/g,games[i].author) + .replace(/TWITTER/g,games[i].twitter) + .replace(/WEBSITE/g,games[i].website) + .replace(/GITHUB/g,games[i].github); + entry = entry.replace('<a href=\'http:///\'></a>','-'); + content += entry; +}; +document.getElementById('content').innerHTML = content;</pre> + +<p>A continuación, registra un servicio <em>works</em>:</p> + +<pre class="brush: js notranslate">if('serviceWorker' in navigator) { + navigator.serviceWorker.register('/pwa-examples/js13kpwa/sw.js'); +};</pre> + +<p>El siguiente bloque de código solicita permiso para recibir notificaciones cuando se hace clic en un botón:</p> + +<pre class="brush: js notranslate">var button = document.getElementById("notifications"); +button.addEventListener('click', function(e) { + Notification.requestPermission().then(function(result) { + if(result === 'granted') { + randomNotification(); + } + }); +});</pre> + +<p>El último bloque crea notificaciones que muestran un elemento seleccionado al azar de la lista de juegos:</p> + +<pre class="brush: js notranslate">function randomNotification() { + var randomItem = Math.floor(Math.random()*games.length); + var notifTitle = games[randomItem].name; + var notifBody = 'Creado por '+games[randomItem].author+'.'; + var notifImg = 'data/img/'+games[randomItem].slug+'.jpg'; + var options = { + body: notifBody, + icon: notifImg + } + var notif = new Notification(notifTitle, options); + setTimeout(randomNotification, 30000); +}</pre> + +<h3 id="El_servicio_worker">El servicio <em>worker</em></h3> + +<p>El último archivo que veremos rápidamente es el servicio <em>worker</em>: <code>sw.js</code> — primero importa datos del archivo <code>games.js</code>:</p> + +<pre class="brush: js notranslate">self.importScripts('data/games.js');</pre> + +<p>A continuación, crea una lista de todos los archivos que se almacenarán en caché, tanto del intérprete de la aplicación como del contenido:</p> + +<pre class="brush: js notranslate">var cacheName = 'js13kPWA-v1'; +var appShellFiles = [ + '/pwa-examples/js13kpwa/', + '/pwa-examples/js13kpwa/index.html', + '/pwa-examples/js13kpwa/app.js', + '/pwa-examples/js13kpwa/style.css', + '/pwa-examples/js13kpwa/fonts/graduate.eot', + '/pwa-examples/js13kpwa/fonts/graduate.ttf', + '/pwa-examples/js13kpwa/fonts/graduate.woff', + '/pwa-examples/js13kpwa/favicon.ico', + '/pwa-examples/js13kpwa/img/js13kgames.png', + '/pwa-examples/js13kpwa/img/bg.png', + '/pwa-examples/js13kpwa/icons/icon-32.png', + '/pwa-examples/js13kpwa/icons/icon-64.png', + '/pwa-examples/js13kpwa/icons/icon-96.png', + '/pwa-examples/js13kpwa/icons/icon-128.png', + '/pwa-examples/js13kpwa/icons/icon-168.png', + '/pwa-examples/js13kpwa/icons/icon-192.png', + '/pwa-examples/js13kpwa/icons/icon-256.png', + '/pwa-examples/js13kpwa/icons/icon-512.png' +]; +var gamesImages = []; +for(var i=0; i<games.length; i++) { + gamesImages.push('data/img/'+games[i].slug+'.jpg'); +} +var contentToCache = appShellFiles.concat(gamesImages);</pre> + +<p>El siguiente bloque instala el servicio <em>worker</em>, que luego almacena en caché todos los archivos contenidos en la lista anterior:</p> + +<pre class="brush: js notranslate">self.addEventListener('install', function(e) { + console.log('[Service Worker] Install'); + e.waitUntil( + caches.open(cacheName).then(function(cache) { + console.log('[Servicio Worker] Almacena todo en caché: contenido e intérprete de la aplicación'); + return cache.addAll(contentToCache); + }) + ); +});</pre> + +<p>Por último, el servicio <em>worker</em> obtiene contenido de la caché si está disponible allí, lo cual proporciona una funcionalidad fuera de línea:</p> + +<pre class="brush: js notranslate">self.addEventListener('fetch', function(e) { + e.respondWith( + caches.match(e.request).then(function(r) { + console.log('[Servicio Worker] Obteniendo recurso: '+e.request.url); + return r || fetch(e.request).then(function(response) { + return caches.open(cacheName).then(function(cache) { + console.log('[Servicio Worker] Almacena el nuevo recurso: '+e.request.url); + cache.put(e.request, response.clone()); + return response; + }); + }); + }) + ); +});</pre> + +<h3 id="Los_datos_de_JavaScript">Los datos de JavaScript</h3> + +<p>Los datos de los juegos están presentes en el directorio <em>data</em> en forma de un objeto JavaScript (<a href="https://github.com/mdn/pwa-examples/blob/master/js13kpwa/data/games.js"><code>games.js</code></a>):</p> + +<pre class="brush: js notranslate">var games = [ + { + slug: 'perdido-en-el-ciberespacio', + name: 'Perdido en el ciberespacio', + author: 'Zosia y Bartek', + twitter: 'bartaz', + website: '', + github: 'github.com/bartaz/lost-in-cyberspace' + }, + { + slug: 'vernissage', + name: 'Vernissage', + author: 'Platane', + twitter: 'platane_', + website: 'github.com/Platane', + github: 'github.com/Platane/js13k-2017' + }, +// ... + { + slug: 'emma-3d', + name: 'Emma-3D', + author: 'Prateek Roushan', + twitter: '', + website: '', + github: 'github.com/coderprateek/Emma-3D' + } +];</pre> + +<p>Cada entrada tiene su propia imagen en el directorio <code>data/img</code>. Este es nuestro contenido, cargado en la sección de contenido con JavaScript.</p> + +<h2 id="Siguiente">Siguiente</h2> + +<p>En el próximo artículo veremos con más detalle cómo se almacenan en caché el intérprete de la aplicación y el contenido para su uso sin conexión con la ayuda del servicio <em>worker</em>.</p> + +<p>{{PreviousMenuNext("Web/Progressive_web_apps/Introduction", "Web/Progressive_web_apps/Offline_Service_workers", "Web/Progressive_web_apps")}}</p> + +<p>{{QuickLinksWithSubpages("/es/docs/Web/Progressive_web_apps/")}}</p> diff --git a/files/es/web/progressive_web_apps/developer_guide/index.html b/files/es/web/progressive_web_apps/developer_guide/index.html new file mode 100644 index 0000000000..79d2859352 --- /dev/null +++ b/files/es/web/progressive_web_apps/developer_guide/index.html @@ -0,0 +1,79 @@ +--- +title: PWA developer guide +slug: Web/Progressive_web_apps/Developer_guide +tags: + - Applications + - Apps + - Developer Guide + - Landing + - NeedsTranslation + - Offline + - PWA + - Persistent + - Progressive web apps + - TopicStub + - Web + - progressive +translation_of: Web/Progressive_web_apps/Developer_guide +--- +<p>{{draft}}</p> + +<p><span class="seoSummary">In the articles listed here, you'll find guides about every aspect of development specific to the creation of progressive web applications (PWAs).</span> For all other documentation about web development, which generally pertains to PWAs as well, see our primary <a href="/en-US/docs/Web">web development documentation</a>.</p> + +<p><strong>--->>> Titles below are just for the list; give articles good SEO names and feel free to tweak those and this as needed... <<<---</strong></p> + +<div class="row topicpage-table"> +<div class="section"> +<h2 class="Basics" id="Web_app_basics">Web app basics</h2> + +<dl> + <dt>Introduction and getting started with PWA development</dt> + <dd>some description</dd> + <dt><a href="/en-US/docs/Web/Progressive_web_apps/Developer_guide/Installing">Installing and uninstalling web apps</a></dt> + <dd>An introductory guide to how a web app can be installed on the user's device...</dd> + <dt>Using service workers to run offline</dt> + <dd>description</dd> + <dt>Alerting the user using notifications</dt> + <dd>description</dd> + <dt>Creating a web app from an existing site</dt> + <dd>description</dd> +</dl> + +<h2 id="Advanced_topics">Advanced topics</h2> + +<dl> + <dt>Pushing data from the server to your web application</dt> + <dd>some description</dd> + <dt>Resource management</dt> + <dd>description</dd> + <dt>Integration with the host device</dt> + <dd>description</dd> + <dt>Security and privacy</dt> + <dd>description</dd> + <dt>Gaming topics for web app developers</dt> + <dd>description</dd> +</dl> +</div> + +<div class="section"> +<h2 class="Polishing" id="Polishing_web_apps">Polishing web apps</h2> + +<dl> + <dt>Web API equivalents for common native APIs</dt> + <dd>some description</dd> + <dt>Platform-specific tips and issues</dt> + <dd>description</dd> + <dt>Web application performance guide</dt> + <dd>description</dd> + <dt>Ensuring a good user experience</dt> + <dd>description</dd> +</dl> + +<h2 class="landingPageList" id="Related_topics">Related topics</h2> + +<dl> + <dt>some topic</dt> + <dd>some description</dd> +</dl> +</div> +</div> diff --git a/files/es/web/progressive_web_apps/developer_guide/instalar/index.html b/files/es/web/progressive_web_apps/developer_guide/instalar/index.html new file mode 100644 index 0000000000..ef54a3b24c --- /dev/null +++ b/files/es/web/progressive_web_apps/developer_guide/instalar/index.html @@ -0,0 +1,96 @@ +--- +title: Instalar y desinstalar aplicaciones web +slug: Web/Progressive_web_apps/Developer_guide/Instalar +tags: + - Android + - Apps + - Chrome + - Desinstalar + - Firefox + - Guía + - Lanzar + - PWA + - Pantalla de inicio + - Principiante + - Samsung + - Web + - aplicaciones + - aplicaciones web progresivas + - instalar +translation_of: Web/Progressive_web_apps/Developer_guide/Installing +--- +<p>{{draft}}</p> + +<p><span class="seoSummary">La instalación de aplicaciones web es una función disponible en los navegadores modernos que permite a los usuarios elegir "instalar" fácil y cómodamente una aplicación web en su dispositivo para que puedan acceder a ella de la misma manera que lo harían con cualquier otra aplicación.</span> Dependiendo del dispositivo y las características del sistema operativo y el navegador, esto puede resultar en lo que esencialmente es una aplicación con todas las funciones (por ejemplo, usando <a href="https://developers.google.com/web/fundamentals/integration/webapks">WebAPK</a> en Android) o como un acceso directo agregado a la pantalla de tu dispositivo. Esta guía explica cómo se realiza la instalación, qué significa y qué debes hacer como desarrollador para que los usuarios la aprovechen.</p> + +<h2 id="¿Por_qué_la_instalación">¿Por qué la instalación?</h2> + +<p>La opción de instalar una aplicación web es parte de la filosofía {{web.link("/es/docs/Web/Progressive_web_apps", "Aplicación web progresiva")}}, que proporciona a las aplicaciones web las mismas ventajas de experiencia de usuario que las aplicaciones nativas para que puedan ser competitivas. Las aplicaciones instaladas se invocan de manera más conveniente ya que tienen presencia en la pantalla de inicio de un dispositivo o en la lista o barra de aplicaciones. Esto facilita que un usuario utilice un gesto para acceder a una aplicación tocando o haciendo clic en su icono. La aplicación en sí misma, se puede manifestar como en una vista sin bordes (sin el navegador Chrome completo) pero, no obstante, se está ejecutando de manera efectiva como una pestaña dentro del navegador.</p> + +<p>Para los usuarios, la experiencia de una PWA aparentemente nativa es más cómoda y conveniente que un sitio web típico. Al reducir la diferencia de experiencia del usuario entre la aplicación web y las aplicaciones nativas en el dispositivo del usuario, reduce tanto la pérdida de cualquier memoria muscular que tenga relacionada con la interfaz nativa del dispositivo como la sensación de que "algo no va del todo bien" que los usuarios pueden experimentar al cambiar entre aplicaciones nativas y basadas en web.</p> + +<h2 id="¿Qué_navegadores_admiten_la_instalación">¿Qué navegadores admiten la instalación?</h2> + +<p>La instalación es compatible con Chrome para Android y Android WebView versión 31 y posteriores, Opera para Android 32 en adelante, Samsung Internet a partir de la versión 4 y Firefox para Android {{web.link("/es/docs/Mozilla/Firefox/Releases/58", "versión 58")}} y posteriores.</p> + +<p>Safari en iOS es un poco diferente. Algunas partes del ecosistema de PWA son compatibles, mientras que otras no. iOS 13 introdujo una experiencia de instalación mucho más comparable, que también se describe aquí.</p> + +<h2 id="La_instalación_en_la_experiencia_del_usuario">La instalación en la experiencia del usuario</h2> + +<p>Hemos escrito un sitio web de ejemplo muy simple (<a href="https://mdn.github.io/pwa-examples/a2hs/">ve nuestra demostración en vivo</a>, y también <a href="https://github.com/mdn/pwa-examples/tree/master/a2hs">ve el código fuente</a>) que no hace mucho, pero fue desarrollado con el código necesario para permitir su instalación, así como un servicio <em>worker> para permitir su uso sin conexión. El ejemplo muestra una serie de imágenes de zorros. Si tienes un dispositivo compatible con la aplicación web disponible, utilízalo para navegar a nuestra demostración en <code>https://mdn.github.io/pwa-examples/a2hs/</code>. Verás imágenes de zorros, pero lo que es más importante, habrá alguna forma de interfaz de usuario disponible para permitirte instalar el sitio como una aplicación web.</em></p> + +<p><em>La interfaz de usuario para esto varía de un navegador a otro, pero la idea general es la misma. Desafortunadamente, no existe un estándar para los iconos y símbolos utilizados para operaciones como esta.</em></p> + +<h3 id="Firefox_para_Android"><em>Firefox para Android</em></h3> + +<p><em>En un dispositivo Android que usa Firefox, verás un ícono de "inicio" con un ícono más (+) en su interior; este es el ícono "Agregar a la pantalla de inicio" que se muestra para cualquier sitio que tenga las características necesarias en su lugar.</em></p> + +<p><em><strong id="docs-internal-guid-7d1a3d87-7fff-4a7b-6728-ae4999c46dd4"><img alt="Una captura de pantalla de un navegador web que muestra el ícono Agregar a la pantalla de inicio en la parte superior" src="https://mdn.mozillademos.org/files/17158/android-a2hs-icon.png " style="height: 64px; width: 500px;"></strong></em></p> + +<p><em>Al tocar este, se mostrará un pasquín de confirmación; al presionar el botón grande "+ AGREGAR A LA PANTALLA DE INICIO", se completa la acción y se agrega la aplicación a la pantalla de inicio. Ten en cuenta que en Android 8 y versiones posteriores, se mostrará primero un cuadro de diálogo de permiso "Agregar a la pantalla de inicio" a nivel del sistema.</em></p> + +<p><em><img alt="Una captura de pantalla de Firefox para Android que solicita confirmación antes de instalar una aplicación web" src="https://mdn.mozillademos.org/files/17160/fx-a2hs-banner.png" style="height: 301px; width: 500px;"></em></p> + +<h3 id="Navegador_de_Internet_Samsung"><em>Navegador de Internet Samsung</em></h3> + +<p><em>Si tiene Samsung Internet en tu dispositivo móvil, verás un icono diferente.</em></p> + +<p><em><img alt="Una captura de pantalla del navegador de Internet de Samsung que muestra su icono Agregar a la pantalla de inicio" src="https://mdn.mozillademos.org/files/17161/samsung-internet-add-app.png" style="height: 247px; width: 500px;"></em></p> + +<p><em>Tocar ese ícono debería llevarte al mismo pasquín de confirmación que se muestra en Firefox arriba.</em></p> + +<h3 id="Google_Chrome_para_Android"><em>Google Chrome para Android</em></h3> + +<p><em>Si tienes Google Chrome para Android disponible, la experiencia es ligeramente diferente; al cargar nuestro sitio, verás un pasquín de instalación emergente que te preguntará si deseas agregar esta aplicación a tu pantalla de inicio.</em></p> + +<p><em><img alt="Captura de pantalla de un pasquín de Chrome que solicita permiso para instalar la aplicación de muestra Foxes" src="https://mdn.mozillademos.org/files/17159/chrome-a2hs-banner.png" style="height: 301px; width: 500px;"></em></p> + +<div class="blockIndicator note"> +<p><em><strong>Nota</strong>: Puedes obtener más información sobre los paquínes de instalación de Chrome en el artículo <a href="https://developers.google.com/web/fundamentals/app-install-banners/">Pasquínes de instalación de aplicaciones web</a>.</em></p> +</div> + +<p><em>Si eliges no agregarlo a tu pantalla de inicio en este momento, los puedes hacer más tarde usando el ícono "Agregar a la pantalla de inicio" en el menú principal de Chrome.</em></p> + +<h3 id="Safari_para_iOSiPhoneOSiPadOS"><em>Safari para iOS/iPhoneOS/iPadOS</em></h3> + +<p><em>En iOS de Apple (incluidos iPhoneOS y iPadOS), el navegador Safari integrado en el dispositivo tiene cierto soporte para aplicaciones web, incluido el soporte para agregar a la función de pantalla de inicio. Para agregar una aplicación web a la pantalla de inicio (también conocida como lanzador o trampolín), toca el botón para compartir (<img alt="Icono de compartir cuadrado y flecha desde iOS y macOS" src="https://mdn.mozillademos.org/files/17156/square.svg" style="height: 18px; width: 14px;">) en la parte inferior de la pantalla:</em></p> + +<p><em><img alt="Captura de pantalla que muestra la ubicación del botón Compartir en Safari en iOS 13" src="https://mdn.mozillademos.org/files/17163/safari-ios-a2hs-icon.png" style="height: 617px; width: 500px;"></em></p> + +<p><em>Esto llama al panel para compartir. Entre las opciones debe estar la opción "Agregar a la pantalla de inicio", a menos que el usuario la haya eliminado específicamente de la lista al editar las opciones mostradas:</em></p> + +<p><em><img alt="Captura de pantalla del panel para compartir de Safari iOS, que muestra la opción" src="https://mdn.mozillademos.org/files/17165/safari-ios-share-menu.png" style="height: 551px; width: 500px;"></em></p> + +<p><em>Al elegir "Agregar a la pantalla de inicio" aquí se presenta el cuadro de diálogo de confirmación, que no solo confirma que el usuario desea agregar la aplicación a la pantalla de inicio, sino que también le permite personalizar su nombre.</em></p> + +<p><em><img alt='Una captura de pantalla de iOS Safari que muestra su panel de configuración y confirmación "Agregar a la pantalla de inicio"' src="https://mdn.mozillademos.org/files/17167/safari-ios-a2hs-banner.png" style="height: 439px; width: 500px;"></em></p> + +<p><em>Al hacer clic en "Agregar", la aplicación se incluye en la pantalla de inicio.</em></p> + +<h3 id="La_aplicación_web_instalada"><em>La aplicación web instalada</em></h3> + +<p><em>Independientemente del navegador y el dispositivo que estés utilizando, cuando eliges agregar la aplicación a tu pantalla de inicio o al iniciador de aplicaciones, aparecerá allí con el mismo aspecto que cualquier aplicación. Normalmente, esto significa que verás el icono de la aplicación junto con un título corto.</em></p> + +<p><em><img alt='Captura de pantalla de una pantalla de inicio de Android con la aplicación "Foxes" mostrada' src="https://mdn.mozillademos.org/files/17157/a2hs-on-home-screen.png" style="height: 304px; width: 500px;"></em></p> + +<p><em>Cuando tocas el icono de la aplicación web en la pantalla de inicio, se abre en un entorno web de pantalla completa, sin la interfaz de usuario del navegador a su alrededor.</em></p> diff --git a/files/es/web/progressive_web_apps/index.html b/files/es/web/progressive_web_apps/index.html new file mode 100644 index 0000000000..10a3638497 --- /dev/null +++ b/files/es/web/progressive_web_apps/index.html @@ -0,0 +1,107 @@ +--- +title: Aplicaciones Web Progresivas +slug: Web/Progressive_web_apps +tags: + - Aplicaciones Web + - Aplicaciones web modernas + - Aplicación Web Progresiva + - Aplicación web + - PWA + - aplicación +translation_of: Web/Progressive_web_apps +--- +<div>{{draft}}</div> + +<p class="summary"><img alt="Logotipo de la comunidad PWA" src="https://mdn.mozillademos.org/files/16742/pwa.png" style="display: block; float: left; height: 188px; margin: 0px auto; padding-bottom: 1em; padding-right: 2em; width: 350px;">Las <strong><em>aplicaciones web progresivas</em></strong> (mejor conocidas como <strong>PWA</strong>s por «<em><strong>P</strong>rogressive <strong>W</strong>eb <strong>A</strong>pps</em>») son aplicaciones web que utilizan APIs y funciones emergentes del navegador web junto a una estrategia tradicional de mejora progresiva para ofrecer una aplicación nativa —como la experiencia del usuario para aplicaciones web multiplataforma. Las aplicaciones web progresivas son un patrón de diseño útil, aunque no son un estándar formalizado. Se puede pensar que PWA es similar a AJAX u otros patrones similares que abarcan un conjunto de atributos de aplicación, incluido el uso de tecnologías y técnicas web específicas. Este conjunto de documentos te dice todo lo que necesitas saber sobre ellas.</p> + +<p>Para poder llamar PWA a una aplicación web, técnicamente hablando debe tener las siguientes características: {{web.link("/es/docs/Web/Security/Secure_Contexts", "Contexto seguro")}} (<strong>{{Glossary("HTTPS")}}</strong>), uno o más {{web.link("/es/docs/Web/API/Service_Worker_API", "Servicio Workers")}} y un {{web.link("/es/docs/Web/Manifest", "archivo de manifiesto")}}.</p> + +<dl> + <dt>{{web.link("/es/docs/Web/Security/Secure_Contexts", "Contexto seguro")}} ({{Glossary("HTTPS")}})</dt> + <dd>La aplicación web se debe servir a través de una red segura. Ser un sitio seguro no solo es una buena práctica, sino que también establece tu aplicación web como un sitio confiable, especialmente si los usuarios necesitan realizar transacciones seguras. La mayoría de las funciones relacionadas con una PWA, como la geolocalización e incluso los servicios <em>workers</em>, solamente están disponibles cuando la aplicación se ha cargado mediante HTTPS.</dd> + <dt>{{web.link("/es/docs/Web/API/Service_Worker_API", "Servicio workers")}}</dt> + <dd>Un servicio <em>worker</em> es un script que permite interceptar y controlar cómo un navegador web maneja tus solicitudes de red y el almacenamiento en caché de activos. Con los servicios <em>worker</em>, los desarrolladores web pueden crear páginas web rápidas y fiables junto con experiencias fuera de línea.</dd> + <dt>{{web.link("/es/docs/Web/Manifest", "El archivo manifest")}}</dt> + <dd>Un archivo {{Glossary("JSON")}} que controla cómo se muestra tu aplicación al usuario y garantiza que las aplicaciones web progresivas sean detectables. Describe el nombre de la aplicación, la URL de inicio, los iconos y todos los demás detalles necesarios para transformar el sitio web en un formato similar al de una aplicación.</dd> +</dl> + +<h2 id="Ventajas_de_PWA">Ventajas de PWA</h2> + +<p>Las PWA deben ser detectables, instalables, enlazables, independientes de la red, progresivas, reconectables, responsivas y seguras. Para obtener más información sobre lo que esto significa, lee {{web.link("/es/docs/Web/Progressive_web_apps/Advantages", "Ventajas de las aplicaciones web progresivas")}}.</p> + +<p>Para saber cómo implementar PWA, lee la {{web.link("/es/docs/Web/Progressive_web_apps/Developer_guide", "guía para desarrolladores de PWA")}}.</p> + +<h2 id="Documentación">Documentación</h2> + +<p><strong><-- La lista automática temporal a continuación se reemplazará pronto --></strong></p> + +<p>{{LandingPageListSubpages}}</p> + +<div class="blockIndicator warning"> +<p><strong>Todo lo que se encuentra debajo de este punto es un remanente de la versión anterior de esta página y se renovará a medida que se revise el resto del contenido.</strong></p> +</div> + +<h2 id="Guías_del_núcleo_de_PWA">Guías del núcleo de PWA</h2> + +<p>Las siguientes guías te muestran lo que debes hacer para implementar una PWA, examinando un ejemplo simple y mostrándote cómo funcionan todas las piezas.</p> + +<ol> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Introduction", "Introducción a las aplicaciones web progresivas")}}</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/App_structure", "Estructura de la aplicación web progresiva")}}</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Offline_Service_workers", "Hacer que las PWAs funcionen sin conexión con el servicio de workers")}}</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Installable_PWAs", "Cómo hacer que las PWAs se puedan instalar")}}</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Re-engageable_Notifications_Push", "Cómo hacer que las PWAs puedan volver a interactuar usando Notificaciones y Push")}}</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Loading", "Carga progresiva")}}</li> +</ol> + +<div class="column-container"> +<div class="column-half"> +<h2 id="Guías_tecnológicas">Guías tecnológicas</h2> + +<ul> + <li>{{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage", "Almacenamiento del lado del cliente")}} — una extensa guía que muestra cómo y cuándo utilizar el almacenamiento web, <code>IndexedDB</code> y el servicio <em>workers</em>.</li> + <li>{{web.link("/es/docs/Web/API/Service_Worker_API/Using_Service_Workers", "Uso del servicio workers")}} — una guía más detallada que cubre la API del servicio <em>workers</em>.</li> + <li>{{web.link("/es/docs/Web/API/IndexedDB_API/Using_IndexedDB", "Uso de IndexedDB")}} — los fundamentos de <code>IndexedDB</code>, explicados en detalle.</li> + <li>{{web.link("/es/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API", "Uso de la API de almacenamiento web")}} — la API de almacenamiento web simplificada.</li> + <li><a class="external external-icon" href="https://developers.google.com/web/updates/2015/11/app-shell" rel="noopener">Aplicaciones web de carga instantánea con una arquitectura de intérprete de aplicaciones</a> — una guía para usar el patrón de codificación de intérprete de App para crear aplicaciones que se cargan rápidamente.</li> + <li>{{web.link("/es/docs/Web/API/Push_API/Using_the_Push_API", "Uso de la API Push")}} — aprende los conceptos básicos de la API Web <code>Push</code>.</li> + <li>{{web.link("/es/docs/Web/API/Notifications_API/Using_the_Notifications_API", "Uso de la API de notificaciones")}} — notificaciones web en pocas palabras.</li> + <li>{{web.link("/es/docs/Web/Apps/Modern/Responsive/responsive_design_building_blocks", "Los componentes básicos del diseño responsivo")}} — aprende los conceptos básicos del diseño responsivo, un tema esencial para el diseño de aplicaciones modernas.</li> + <li>{{web.link("/es/docs/Web/Apps/Modern/Responsive/Mobile_first", "Primero móvil")}} — a menudo, al crear diseños de aplicaciones adaptables, tiene sentido crear el diseño móvil como predeterminado y construir diseños más anchos en la parte superior.</li> + <li>{{web.link("/es/docs/Web/Apps/Progressive/Add_to_home_screen", "Guía para agregar la pantalla de inicio")}} — aprende cómo tus aplicaciones pueden aprovechar agregar la pantalla de inicio (A2HS).</li> +</ul> +</div> + +<div class="column-half"> +<h2 id="Herramientas">Herramientas</h2> + +<ul> + <li><a class="external external-icon" href="https://localforage.github.io/localForage/" rel="noopener">localForage</a> — una biblioteca de JavaScript sencilla y agradable para almacenar datos en el lado del cliente de manera realmente simple, usa <code>IndexedDB</code> y recurre a <code>Web SQL</code>/<code>Web Storage</code> si es necesario.</li> + <li><a class="external external-icon" href="https://github.com/fxos-components/serviceworkerware" rel="noopener"><code>ServiceWorkerWare</code></a> — un <em>microframework tipo Express</em> para facilitar el desarrollo del Servicio <em>Worker</em>.</li> + <li><a class="external external-icon" href="https://github.com/mozilla/oghliner" rel="noopener"><code>oghliner</code></a> — no solo es una plantilla, sino una herramienta para implementar aplicaciones web sin conexión para Páginas de GitHub.</li> + <li><a class="external external-icon" href="https://github.com/GoogleChrome/sw-precache" rel="noopener"><code>sw-precache</code></a> — un módulo de <code>node</code> para generar código del servicio <em>worker que precargará recursos específicos.</em></li> + <li><em><a class="external external-icon" href="https://github.com/GoogleChrome/workbox" rel="noopener">workbox</a>: sucesor espiritual de "sw-precache" con estrategias de almacenamiento en caché más avanzadas y sencillas precargas.</em></li> + <li><em><a class="external external-icon" href="https://www.talater.com/upup/" rel="noopener">upup</a>: un diminuto script que garantiza que tu sitio siempre esté disponible para tus usuarios.</em></li> + <li><em><a class="external external-icon" href="https://serviceworke.rs/" rel="noopener">El libro de recetas para servicios <em>worker</em></a>: una serie de excelentes recetas de servicios <em>worker</em> que muestran cómo implementar una aplicación sin conexión, además de otros muchos concejos.</em></li> + <li><em><a href="https://marketplace.visualstudio.com/items?itemName=mayeedwin.vscode-pwa">Extensión PWA de VS Code</a>: una colección de todos los fragmentos de código esenciales que necesitas para crear aplicaciones web progresivas correctamente allí en tu entorno de VS Code.</em></li> +</ul> +</div> +</div> + +<ul> + <li><em><a href="https://developers.google.com/web/progressive-web-apps">Aplicaciones web progresivas</a> en Google Developers.</em></li> + <li><em><a href="https://medium.com/@slightlylate/progressive-apps-escaping-tabs-without-losing-our-soul-3b93a8561955#.6czgj0myh">Aplicaciones web progresivas: escapar de las pestañas sin perder el alma</a> de Alex Russell.</em></li> + <li><em><a href="https://developers.google.com/web/progressive-web-apps/checklist">Lista de verificación de aplicaciones web progresivas</a>.</em></li> + <li><em><a href="https://developers.google.com/web/tools/lighthouse">La herramienta Lighthouse</a> de Google.</em></li> + <li><em><a href="https://github.com/angular/mobile-toolkit">Herramientas para crear aplicaciones web progresivas con Angular</a>.</em></li> + <li><em><a href="#" title="https://github.com/codebusking/react-pwa-guide-kit">Kit de guía de React PWA</a>.</em></li> + <li><em><a href="https://pokedex.org/">Sitio web de la Pokedex sin conexión</a>.</em></li> + <li><em><a href="https://hnpwa.com/">Lectores de noticias Hacker como aplicaciones web progresivas</a>.</em></li> + <li><em><a href="https://goingmeta.io/progressive-web-app/">Aplicación web progresiva: ventajas en pocas palabras</a></em></li> + <li><em><a href="https://ymedialabs.com/progressive-web-apps">Por qué las aplicaciones web progresivas son el futuro de la web móvil (investigación de 2019)</a>.</em></li> + <li><em><a href="https://www.csschopper.com/blog/progressive-web-apps-everything-you-need-to-know/">Aplicaciones web progresivas: todo lo que necesitas saber</a></em></li> + <li><em><a href="https://pwafire.org">Colección de recursos, laboratorios de código y herramientas que necesitas para crear PWAs por parte del equipo de pwafire.org</a></em></li> + <li><em><a href="https://github.com/pwafire/pwadev-tips">Configuración de tu entorno de desarrollo de aplicaciones web progresivas</a></em></li> +</ul> + +<div><em>{{QuickLinksWithSubpages("/es/docs/Web/Progressive_web_apps/")}}</em></div> diff --git a/files/es/web/progressive_web_apps/installable_pwas/index.html b/files/es/web/progressive_web_apps/installable_pwas/index.html new file mode 100644 index 0000000000..8994574904 --- /dev/null +++ b/files/es/web/progressive_web_apps/installable_pwas/index.html @@ -0,0 +1,130 @@ +--- +title: Cómo hacer PWAs instalables +slug: Web/Progressive_web_apps/Installable_PWAs +tags: + - Instalable + - PWAs + - aapi + - agregar a pantalla de inicio + - aplicaciones web progresivas + - js13kGames + - progresiva +translation_of: Web/Progressive_web_apps/Installable_PWAs +--- +<div>{{PreviousMenuNext("Web/Apps/Progressive/Offline_Service_workers", "Web/Apps/Progressive/Re-engageable_Notifications_Push", "Web/Apps/Progressive")}}</div> + +<p class="summary">En el último artículo, leímos cómo la aplicación de ejemplo, <a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a>, funciona sin conexión gracias a su {{web.link("/es/docs/Web/API/Service_Worker_API", "servicio worker")}}, pero podemos ir aún más lejos y permitir que los usuarios instalen la aplicación web en los navegadores móviles y de escritorio que lo admitan. Los usuarios pueden iniciar la aplicación web instalada como si fuera una aplicación nativa. Este artículo explica cómo lograr esto usando el manifiesto de la aplicación web.</p> + +<p>Estas tecnologías permiten que la aplicación se inicie directamente desde la pantalla de inicio del dispositivo, en lugar de que el usuario tenga que abrir el navegador y luego navegar al sitio utilizando un marcador o escribiendo la URL. Tu aplicación web se puede sentar junto a aplicaciones nativas como ciudadanos de primera clase. Esto facilita el acceso a la aplicación web; Además, puedes especificar que la aplicación se inicie en modo de pantalla completa o independiente, eliminando así la interfaz de usuario predeterminada del navegador que de otro modo estaría presente, creando una sensación aún más fluida y similar a la nativa.</p> + +<h2 id="Requisitos">Requisitos</h2> + +<p>Para que el sitio web sea instalable, necesitas lo siguiente:</p> + +<ul> + <li>Un manifiesto web, con los {{web.link("/es/Apps/Progressive/Add_to_home_screen#Manifest", "campos correctos completados")}}</li> + <li>Que sitio web se sirva desde un dominio seguro (HTTPS)</li> + <li>Un icono para representar la aplicación en el dispositivo.</li> + <li>Un {{web.link("/es/docs/Web/API/Service_Worker_API", "servicio worker")}} registrado para permitir que la aplicación funcione sin conexión (actualmente, esto solo lo requiere Chrome para Android)</li> +</ul> + +<div class="blockIndicator note"> +<p>Actualmente, solo los navegadores basados en Chromium tal como Chrome, Edge y Samsung Internet requieren el servicio <em>worker</em>. Si desarrollas tu aplicación con Firefox, ten en cuenta que necesitarás un servicio <em>worker</em> para que sea compatible con los navegadores basados en Chromium.</p> +</div> + +<h3 id="El_archivo_de_manifiesto">El archivo de manifiesto</h3> + +<p dir="ltr">El elemento clave es un archivo de manifiesto web, que enumera toda la información sobre el sitio web en formato JSON.</p> + +<p dir="ltr">Suele residir en el directorio raíz de una aplicación web. Contiene información útil, como el título de la aplicación, rutas a iconos de diferentes tamaños que se pueden usar para representar la aplicación en un sistema operativo (como un icono en la pantalla de inicio, una entrada en el menú Inicio o un icono en el escritorio) y un color de fondo para usar en las pantallas de carga o de presentación. Esta información es necesaria para que el navegador presente la aplicación web correctamente durante el proceso de instalación, así como dentro de la interfaz de inicio de la aplicación del dispositivo, como la pantalla de inicio de un dispositivo móvil.</p> + +<p>El archivo <code>js13kpwa.webmanifest</code> de la aplicación web <a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a> se incluye en el bloque {{HTMLElement("head")}} del archivo <code>index.html</code> de la aplicación web usando la siguiente línea de código:</p> + +<pre class="brush: html notranslate"><link rel="manifest" href="js13kpwa.webmanifest"></pre> + +<div class="note"> +<p>Hay algunos tipos comunes de archivos de manifiesto que se han utilizado en el pasado: <code>manifest.webapp</code> era popular en los manifiestos de aplicaciones de Firefox OS, y muchos usan <code>manifest.json</code> para manifestar aplicaciones web ya que el contenido está organizado en una estructura JSON. Sin embargo, el formato de archivo <code>.webmanifest</code> se menciona explícitamente en la <a href="https://w3c.github.io/manifest/">especificación del manifiesto W3C</a>, por lo tanto ese es el que usaremos aquí.</p> +</div> + +<p>El contenido del archivo se ve así:</p> + +<pre class="brush: json notranslate">{ + "name": "js13kGames Progressive Web App", + "short_name": "js13kPWA", + "description": "Aplicación web progresiva que enumera los juegos enviados a la categoría del marco A en la competencia js13kGames del 2017.", + "icons": [ + { + "src": "icons/icon-32.png", + "sizes": "32x32", + "type": "image/png" + }, + // ... + { + "src": "icons/icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "start_url": "/pwa-examples/js13kpwa/index.html", + "display": "fullscreen", + "theme_color": "#B12A34", + "background_color": "#B12A34" +} +</pre> + +<p>La mayoría de los campos se explican por sí mismos, pero para estar seguros de que estamos en la misma página:</p> + +<ul> + <li><code>name</code>: El nombre completo de tu aplicación web.</li> + <li><code>short_name</code>: Nombre corto que se mostrará en la pantalla de inicio.</li> + <li><code>description</code>: Una o dos frases que explican lo que hace tu aplicación.</li> + <li><code>icons</code>: Gran cantidad de información de íconos — URLs de origen, tamaños y tipos. Asegúrate de incluir al menos algunos, de modo que se elija el que mejor se adapte al dispositivo del usuario.</li> + <li><code>start_url</code>: El documento <code>index</code> que se iniciará al arrancar la aplicación.</li> + <li><code>display</code>: Cómo se muestra la aplicación; puede ser <code>fullscreen</code> (pantalla completa), <code>standalone</code> (independiente), <code>minimal-ui</code> (interfaz de usuario mínima) o <code>browser</code> (navegador).</li> + <li><code>theme_color</code>: Un color primario para la interfaz de usuario, utilizado por el sistema operativo.</li> + <li><code>background_color</code>: Un color que se utiliza como fondo predeterminado de la aplicación, usado durante la instalación y en la pantalla de bienvenida.</li> +</ul> + +<p>Un manifiesto web mínimo debe tener al menos un <code>name</code> y un campo <code>icons</code> con al menos un icono definido; ese icono debe tener al menos los subcampos <code>src</code>, <code>sizes</code> y <code>type</code> también. Más allá de eso, todo es opcional, aunque se recomiendan los campos <code>description</code>, <code>short_name</code> y <code>start_url</code>. Incluso, hay más campos que puedes usar de los que se enumeran anteriormente; asegúrate de consultar la {{web.link("/es/docs/Web/Manifest", "referencia del manifiesto de la aplicación web")}} para obtener más detalles.</p> + +<h2 id="Agregar_a_la_pantalla_inicial">Agregar a la pantalla inicial</h2> + +<p>"Agregar a la pantalla de inicio" (o <em>aapi</em> para abreviar) es una función implementada por los navegadores móviles que toma la información que se encuentra en el manifiesto de una aplicación web y la usa para representar la aplicación en la pantalla de inicio del dispositivo con un icono y un nombre. Esto solo funciona si la aplicación cumple con todos los requisitos necesarios, como se describió anteriormente.</p> + +<p>Cuando el usuario visita la PWA con un navegador móvil compatible, debe mostrar una notificación (como un pasquín o un cuadro de diálogo) que indique que es posible instalar la aplicación como una PWA.</p> + +<p><img alt="Agregar a la ventana emergente de la pantalla de inicio de js13kPWA." src="https://mdn.mozillademos.org/files/15928/js13kpwa-icon.png" style="border-style: solid; border-width: 1px; display: block; height: 640px; margin: 0px auto; width: 360px;"></p> + +<p>Una vez que el usuario indica que desea continuar con la instalación, se muestra el pasquín de instalación. Ese pasquín es creado automáticamente por el navegador, basado en la información del archivo de manifiesto. Por ejemplo, el mensaje incluye el nombre y el icono de la aplicación.</p> + +<p><img alt="Pancarta de instalación de js13kPWA." src="https://mdn.mozillademos.org/files/15927/js13kpwa-banner.png" style="border-style: solid; border-width: 1px; display: block; height: 640px; margin: 0px auto; width: 360px;"></p> + +<p>Si el usuario hace clic en el botón, hay un paso final que muestra cómo se verá la aplicación y permite que el usuario elija si definitivamente desea agregar la aplicación.</p> + +<p><img alt="Agregar a la ventana emergente de la pantalla de inicio de js13kPWA." src="https://mdn.mozillademos.org/files/15926/js13kpwa-add.png" style="border-style: solid; border-width: 1px; display: block; height: 640px; margin: 0px auto; width: 360px;"></p> + +<p>Cuando se confirme, la aplicación se instalará en la pantalla de inicio.</p> + +<p><img alt="Pantalla de inicio" src="https://mdn.mozillademos.org/files/15834/js13kpwa-installed.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Ahora el usuario puede iniciar y utilizar la aplicación web como cualquier otra aplicación en su dispositivo. Dependiendo del dispositivo y el sistema operativo, el icono de la aplicación web puede tener una insignia con un pequeño icono que indica que se trata de una aplicación web. En la captura de pantalla anterior, por ejemplo, la aplicación tiene un pequeño icono de Firefox, lo cual indica que es una aplicación web que usa el entorno de ejecución de Firefox.</p> + +<h3 id="Pantalla_de_bienvenida">Pantalla de bienvenida</h3> + +<p>En algunos navegadores, también se genera una pantalla de bienvenida a partir de la información del manifiesto, que se muestra cuando se inicia la PWA y mientras se carga.</p> + +<p><img alt="Pantalla de bienvenida" src="https://mdn.mozillademos.org/files/15835/js13kpwa-splash.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>El icono y los colores del tema y fondo se utilizan para crear esta pantalla.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>En este artículo, aprendimos cómo podemos hacer que las PWAs se puedan instalar con un manifiesto web correctamente configurado, y cómo el usuario puede luego instalar la PWA con la función "agregar a la pantalla de inicio" de su navegador.</p> + +<p>Para obtener más información sobre <em>aapi</em>, asegúrate de leer nuestra {{web.link("/es/docs/Web/Apps/Progressive/Add_to_home_screen", "guía para agregar a la pantalla de inicio")}}. La compatibilidad con el navegador se limita actualmente a Firefox para Android 58+, Mobile Chrome y Android Webview 31+, y Opera para Android 32+, pero esto debería mejorar en un próximo futuro.</p> + +<p>Ahora pasemos a la última pieza del rompecabezas de PWA: usar notificaciones automáticas para compartir anuncios con el usuario y ayudarlo a volver a interactuar con tu aplicación.</p> + +<p>{{PreviousMenuNext("Web/Apps/Progressive/Offline_Service_workers", "Web/Apps/Progressive/Re-engageable_Notifications_Push", "Web/Apps/Progressive")}}</p> + +<p>{{QuickLinksWithSubpages("/es/docs/Web/Progressive_web_apps/")}}</p> diff --git a/files/es/web/progressive_web_apps/introduction/index.html b/files/es/web/progressive_web_apps/introduction/index.html new file mode 100644 index 0000000000..266c602c8c --- /dev/null +++ b/files/es/web/progressive_web_apps/introduction/index.html @@ -0,0 +1,169 @@ +--- +title: Introducción a aplicaciones web progresivas +slug: Web/Progressive_web_apps/Introduction +tags: + - Aplicaciones web prograsivas + - Guía + - Intermedio + - Intruducción + - PWA + - Servicio Worker + - aplicaciones + - js13kGames + - manifiesto web + - progresiva +translation_of: Web/Progressive_web_apps/Introduction +--- +<div>{{NextMenu("Web/Progressive_web_apps/App_structure", "Web/Progressive_web_apps")}}</div> + +<p class="summary"><span class="seoSummary">Este articulo provee una introducción a las Aplicaciones web progresivas (PWAs), explica qué son, y las ventajas que brindan sobre las aplicaciones web convencionales.</span></p> + +<h2 id="¿Qué_es_una_aplicación_web_progresiva">¿Qué es una aplicación web progresiva?</h2> + +<div class="callout-box">El término "Aplicación web progresiva" no es un nombre formal u oficial. Solo es una abreviatura utilizada inicialmente por Google para el concepto de crear una aplicación flexible y adaptable utilizando solo tecnologías web.</div> + +<p>Las PWA son aplicaciones web desarrolladas con una serie de tecnologías específicas y patrones estándar que les permiten aprovechar las funciones de las aplicaciones nativas y web. Por ejemplo, las aplicaciones web son más fáciles de detectar que las aplicaciones nativas; es mucho más fácil y rápido visitar un sitio web que instalar una aplicación, y también puedes compartir aplicaciones web simplemente enviando un enlace.</p> + +<p>Por otro lado, las aplicaciones nativas están mejor integradas con el sistema operativo y, por lo tanto, ofrecen una experiencia más fluida para los usuarios. Puedes instalar una aplicación nativa para que funcione sin conexión, y a los usuarios les encanta tocar sus íconos para acceder fácilmente a sus aplicaciones favoritas, en lugar de navegar a través de un navegador.</p> + +<p>Las PWA brindan la capacidad de crear aplicaciones web que pueden disfrutar de estas mismas ventajas.</p> + +<p>No es un concepto completamente nuevo; estas ideas se han revisado muchas veces en la plataforma web con varios enfoques en el pasado. La mejora progresiva y el diseño adaptable ya te permiten crear sitios web compatibles con dispositivos móviles.</p> + +<p>Sin embargo, las PWA brindan todo esto y más sin perder ninguna de las características existentes que hacen que la web sea excelente.</p> + +<h2 id="¿Qué_hace_que_una_aplicación_sea_una_PWA">¿Qué hace que una aplicación sea una PWA?</h2> + +<p>Como dijimos anteriormente, las PWA no se crean con una sola tecnología. Representan una nueva filosofía para la creación de aplicaciones web, que incluye algunos patrones específicos, API y otras características. A primera vista, <em>no</em> es tan obvio si una aplicación web es una PWA o no. Una aplicación se podría considerar una PWA cuando cumple con ciertos requisitos o implementa un conjunto de características determinadas — funciona sin conexión, es instalable, es fácil de sincronizar, puede enviar notificaciones automáticas, etc.</p> + +<p>Además, existen herramientas para medir qué tan completa (como porcentaje) es una aplicación web, como <a href="https://developers.google.com/web/tools/lighthouse/">Lighthouse</a>. Al implementar varias ventajas tecnológicas, podemos hacer que una aplicación sea más progresiva, y así terminar con una puntuación de Lighthouse más alta. Pero este es solo un indicador aproximado.</p> + +<p>Hay algunos principios clave que una aplicación web debe tratar de observar para ser identificada como PWA. Estos deben ser:</p> + +<ul> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Advantages", "Detectable", "#Discoverable")}}, por lo que el contenido se puede encontrar a través de motores de búsqueda.</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Advantages", "Instalable", "#Instalable")}}, por lo que puede estar disponible en la pantalla de inicio del dispositivo o en el lanzador de aplicaciones.</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Advantages", "Enlazable", "#Enlazable")}}, para que puedas compartirla simplemente enviando una URL.</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Advantages", "Independiente de la red", "#Independiente_de_la_red")}}, por lo que funciona sin conexión o con una deficiente conexión de red.</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Advantages", "Progresiva", "#Progresiva")}}, por lo que todavía se puede utilizar en un nivel básico en los navegadores más antiguos, pero completamente funcional en los más recientes.</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Advantages", "Reconectable", "#Reconectable")}}, por lo que puede enviar notificaciones cuando haya contenido nuevo disponible.</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Advantages", "Adaptable", "#Adaptable")}}, por lo tanto se puede utilizar en cualquier dispositivo con pantalla y navegador: teléfonos móviles, tabletas, computadoras portátiles, televisores, refrigeradores, etc.</li> + <li>{{web.link("/es/docs/Web/Progressive_web_apps/Advantages", "Segura", "#Segura")}} por lo que las conexiones entre el usuario, la aplicación y tu servidor están protegidos contra terceros que intenten acceder a datos sensibles.</li> +</ul> + +<p>Ofrecer estas funciones y hacer uso de todas las {{anch("Ventajas_de_las_aplicaciones_web", "Ventajas que ofrecen las aplicaciones web")}} puede crear una oferta atractiva y altamente flexible para tus usuarios y clientes.</p> + +<h3 id="¿Vale_la_pena_hacer_todo_eso">¿Vale la pena hacer todo eso?</h3> + +<p>¡Absolutamente! Con un esfuerzo relativamente pequeño para implementar las características principales de las PWAs, los beneficios son enormes. Por ejemplo:</p> + +<ul> + <li>Una disminución en los tiempos de carga después de la instalación de la aplicación, gracias al almacenamiento en caché con el {{web.link("/es/docs/Web/API/Service_Worker_API", "servicio workers")}}, además de ahorrar un valioso ancho de banda y tiempo. Los PWAs tienen una carga casi instantánea (a partir de la segunda visita).</li> + <li>La capacidad de actualizar solo el contenido que ha cambiado cuando hay disponible una actualización de la aplicación. En contraste, con una aplicación nativa, incluso la más mínima modificación puede obligar al usuario a descargar la aplicación completa nuevamente.</li> + <li>Una apariencia que está más integrada con la plataforma nativa: íconos de aplicaciones en la pantalla de inicio o el lanzador de aplicaciones, aplicaciones que se ejecutan automáticamente en modo de pantalla completa, etc.</li> + <li>Reconectable para interactuar con los usuarios mediante el uso de notificaciones del sistema y mensajes <code>push</code>, lo cual genera usuarios más comprometidos y mejores tasas de conversión.</li> +</ul> + +<h3 id="Historias_de_éxito">Historias de éxito</h3> + +<p>Hay muchas historias de éxito de empresas que probaron la ruta PWA, optaron por una experiencia de sitio web mejorada en lugar de una aplicación nativa y, como resultado, obtuvieron importantes beneficios medibles. El sitio web <a href="https://www.pwastats.com/">Estadísticas PWA</a> comparte muchos estudios de casos que indican estos beneficios.</p> + +<p>La historia de éxito más conocida probablemente es la de <a href="https://stories.flipkart.com/introducing-flipkart-lite/">Flipkart Lite</a>. El sitio de comercio electrónico más grande de la India se reconstruyó como una aplicación web progresiva en 2015, lo que resultó en un aumento del 70% en las conversiones. La PWA <a href="https://m.aliexpress.com/">AliExpress</a> también ha obtenido resultados mucho mejores que la web o la aplicación nativa, con un aumento del 104% en las tasas de conversión para los nuevos usuarios. Dado el aumento de sus ganancias y la cantidad relativamente baja de trabajo requerida para la conversión de estas aplicaciones a PWA, la ventaja es clara.</p> + +<p>Las puestas en marcha emergentes en etapa temprana como <a href="https://www.couponmoto.com/">couponmoto</a> también han comenzado a usar aplicaciones web progresivas para impulsar una mayor participación de los consumidores, lo que demuestra que pueden ayudar tanto a pequeñas como a grandes empresas para (re)involucrar a los usuarios de manera más eficaz.</p> + +<p>Puedes consultar la lista en <a href="#" title="https://pwa.rocks/">pwa.rocks</a> para obtener más ejemplos. Vale la pena mencionar en particular la página <a href="https://hnpwa.com/">hnpwa.com</a>, que muestra una implementación de ejemplo del sitio web de Hacker News (en lugar de la aplicación habitual TodoMVC), en la que puedes ver el uso de varios marcos de desarrollo de la interfaz de usuario web.</p> + +<p>Incluso puedes generar PWA en línea utilizando el sitio web <a href="https://www.pwabuilder.com/">PWABuilder</a>.</p> + +<p>Para obtener información específica sobre el servicio <em>worker</em> y la inserción, asegúrate de consultar el <a href="https://serviceworke.rs/">Libro de recetas del servicio <em>worker</em></a>, una colección de recetas que utilizan los servicios <em>worker</em> en sitios modernos.</p> + +<p>Vale la pena probar un enfoque de PWA, para que puedas ver por ti mismo si funciona para tu aplicación.</p> + +<h2 id="Ventajas_de_las_aplicaciones_web">Ventajas de las aplicaciones web</h2> + +<p>Una aplicación web progresiva totalmente capaz debería proporcionar todas las siguientes ventajas al usuario.</p> + +<h3 id="Reconocible">Reconocible</h3> + +<p><img alt="Detectabilidad" src="https://mdn.mozillademos.org/files/12654/discoverable.svg" style="float: left; height: 60px; margin-right: 1em; width: 50px;">El objetivo final es que las aplicaciones web tengan una mejor representación en los motores de búsqueda, sean más fáciles de exponer, catalogar y clasificar, y tener metadatos utilizables por los navegadores para brindarles capacidades especiales.</p> + +<p>Algunas de las capacidades ya se han habilitado en ciertas plataformas basadas en web mediante tecnologías patentadas como <a href="http://ogp.me/">Open Graph</a>, que proporciona un formato para especificar metadatos similares en el bloque {{HTMLElement("head")}} de {{Glossary("HTML")}} con etiquetas {{HTMLElement("meta")}}.</p> + +<p>El estándar web relevante aquí es el {{web.link("/es/docs/Web/Manifest", "manifiesto de la aplicación web")}}, que define las características de una aplicación, como el nombre, el icono, la pantalla de presentación y los colores del tema en un archivo de manifiesto con formato {{Glossary("JSON")}}. Esto es para usar en contextos como listas de aplicaciones y pantallas de inicio de dispositivos.</p> + +<h3 id="Instalable">Instalable</h3> + +<p><img alt="Instalabilidad" src="https://mdn.mozillademos.org/files/12656/installable.svg" style="float: left; height: 60px; margin-right: 1em; width: 60px;"></p> + +<p>Una parte fundamental de la experiencia de la aplicación web es que los usuarios tengan iconos de aplicaciones en su pantalla de inicio y los puedan tocar para abrir aplicaciones en su propio contenedor nativo que se sienta bien integrado con la plataforma subyacente.</p> + +<p>Las aplicaciones web modernas pueden hacer que esta aplicación nativa se sienta a través de las propiedades establecidas dentro del manifiesto de la aplicación web y mediante una función disponible en los navegadores de teléfonos inteligentes modernos llamada {{web.link("/es/docs/Web/Progressive_web_apps/Developer_guide/Installing", "instalación de la aplicación web")}}.</p> + +<h3 id="Enlazable">Enlazable</h3> + +<p><img alt="Enlazable" src="https://mdn.mozillademos.org/files/12658/linkable.svg" style="float: left; height: 60px; margin-right: 1em; width: 60px;"></p> + +<p>Una de las características más poderosas de la web es la capacidad de vincularse a una aplicación en una URL específica sin la necesidad de una tienda de aplicaciones o un proceso de instalación complejo. Así ha sido siempre.</p> + +<h3 id="Independiente_de_la_red">Independiente de la red</h3> + +<p><img alt="Independencia de la red" src="https://mdn.mozillademos.org/files/12660/network-independent.svg" style="float: left; height: 60px; margin-right: 1em; width: 60px;"></p> + +<p>Las aplicaciones web modernas pueden funcionar cuando hay mala (o incluso inexistente) conectividad con la red. Las ideas básicas detrás de la independencia de la red son poder:</p> + +<ul> + <li>Volver a visitar un sitio y obtener su contenido incluso si no hay una red disponible.</li> + <li>Explorar cualquier tipo de contenido que el usuario haya visitado anteriormente al menos una vez, incluso en situaciones de mala conectividad.</li> + <li>Controlar lo que se muestra al usuario en situaciones donde no hay conectividad.</li> +</ul> + +<p>Esto se consigue mediante una combinación de tecnologías: el {{web.link("/es/docs/Web/API/Service_Worker_API", "servicio Workers")}} para controlar las solicitudes de página (por ejemplo, almacenarlas sin conexión), la {{web.link("/es/docs/Web/API/Cache", "API de caché")}} para almacenar respuestas a solicitudes de red sin conexión (muy útil para almacenar activos del sitio) y tecnologías de almacenamiento de datos secundarios como {{web.link("/es/docs/Web/API/Web_Storage_API", "Almacenamiento Web")}} y {{web.link("/es/docs/Web/API/IndexedDB_API", "IndexedDB")}} para almacenar datos de aplicaciones sin conexión.</p> + +<h3 id="Compatibilidad_de_mejora_progresiva">Compatibilidad de mejora progresiva</h3> + +<p><img alt="Mejora progresiva" src="https://mdn.mozillademos.org/files/12662/progressive.svg" style="float: left; height: 60px; margin-right: 1em; width: 60px;"></p> + +<p>Se pueden desarrollar aplicaciones web modernas para proporcionar una experiencia excelente a los navegadores totalmente compatibles y una experiencia aceptable (aunque no tan brillante) a los navegadores menos capaces. Hemos estado haciendo esto durante años con las mejores prácticas, como la mejora progresiva. Al utilizar {{Glossary("Progressive_Enhancement", "Mejora progresiva")}}, las PWAs se utilizan en varios navegadores. Esto significa que los desarrolladores deben tener en cuenta las diferencias en la implementación de algunas características y tecnologías PWA entre diferentes implementaciones de navegadores.</p> + +<h3 id="Reconectable">Reconectable</h3> + +<p><img alt="Reconectable" src="https://mdn.mozillademos.org/files/12666/re-engageable.svg" style="float: left; height: 60px; margin-right: 1em; width: 60px;"></p> + +<p>Una de las principales ventajas de las plataformas nativas es la facilidad con la que los usuarios pueden volver a interactuar con las actualizaciones y el contenido nuevo, incluso cuando no están mirando la aplicación o usando sus dispositivos. Las aplicaciones web modernas ahora también pueden hacer esto, utilizando nuevas tecnologías como Servicio <em>Workers</em> para controlar páginas, la {{web.link("/es/docs/Web/API/Push_API", "API Web Push")}} para enviar actualizaciones. directamente del servidor a la aplicación a través de un servicio <em>workers</em> y la {{web.link("/es/docs/Web/API/Notifications_API", "API de notificaciones")}} para generar notificaciones del sistema para ayudar a involucrar a los usuarios cuando no están utilizando activamente su navegador web.</p> + +<h3 id="Adaptable">Adaptable</h3> + +<p><img alt="Adaptable" src="https://mdn.mozillademos.org/files/12650/responsive.svg" style="float: left; height: 61px; margin-right: 1em; width: 60px;"></p> + +<p>Las aplicaciones web adaptables utilizan tecnologías como {{web.link("/es/docs/Web/CSS/Media_Queries", "consultas de medios")}} y {{web.link("/es/docs/Glossary/Viewport", "viewport")}} para asegurarte de que tu IU se ajuste a cualquier factor de forma: computadora de escritorio, dispositivo móvil, tableta o lo que venga a continuación.</p> + +<h3 id="Segura">Segura</h3> + +<p><img alt="Segura" src="https://mdn.mozillademos.org/files/12664/safe.svg" style="float: left; height: 74px; margin-right: 1em; width: 60px;"></p> + +<p><img alt='Captura de pantalla que muestra una gran cantidad de resultados al buscar "Messenger" al intentar encontrar Facebook Messenger. ¿Cuál es el correcto?' src="https://mdn.mozillademos.org/files/17175/InstalingMessengerSoManyOptionsEek.jpeg" style="border-style: solid; border-width: 1px; float: right; height: 267px; margin-left: 1em; width: 130px;">La plataforma web proporciona un mecanismo de entrega seguro que evita espionaje y, al mismo tiempo, garantiza que el contenido no haya sido manipulado, siempre que aproveche {{Glossary("HTTPS")}} y desarrolles tus aplicaciones pensando en la seguridad.</p> + +<p>También es fácil para los usuarios asegurarse de que están instalando la aplicación correcta, porque su URL coincidirá con el dominio de tu sitio. Esto es muy diferente de las aplicaciones en las tiendas de aplicaciones, que pueden tener varias aplicaciones con nombres similares, algunas de las cuales incluso pueden estar basadas en su propio sitio, lo que aumenta la confusión. Las aplicaciones web eliminan esa confusión y garantizan que los usuarios obtengan la mejor experiencia posible.</p> + +<h2 id="Compatibilidad_con_el_navegador">Compatibilidad con el navegador</h2> + +<p>Como se mencionó anteriormente, las PWAs no dependen de una sola API, sino que utilizan varias tecnologías para lograr el objetivo de brindar la mejor experiencia web posible.</p> + +<p>El ingrediente clave requerido para las PWAs es la asistencia de {{web.link("/es/docs/Web/API/Service_Worker_API", "servicio workers")}}. Afortunadamente, los servicios de <em>workers</em> <a href="https://jakearchibald.github.io/isserviceworkerready/">ahora son compatibles con los principales navegadores</a> en computadoras de escritorio y dispositivos móviles.</p> + +<p>Otras características como {{web.link("/es/docs/Web/Manifest", "manifiesto de App Web")}}, {{web.link("/es/docs/Web/API/Push_API", "Push")}}, {{web.link("/es/docs/Web/API/Notifications_API", "Notificaciones")}} y la funcionalidad {{web.link("/es/docs/Web/Progressive_web_apps/Add_to_home_screen", "Agregar a la pantalla de inicio")}} también tienen un amplio soporte. Actualmente, Safari tiene soporte limitado para el manifiesto de aplicaciones web y Agregar a la pantalla de inicio y no admite notificaciones <em>push web</em>. Sin embargo, otros navegadores importantes admiten todas estas funciones.</p> + +<p>Por encima de todo, debes seguir la regla de mejora progresiva: usa tecnologías que mejoren la apariencia y la utilidad de tu aplicación cuando estén disponibles, pero que sigan ofreciendo la funcionalidad básica de tu aplicación cuando esas funciones no estén disponibles. Presentar un sitio web confiable con un buen rendimiento es una consecuencia del uso de estas mejoras; esto, a su vez, significa crear aplicaciones web que sigan las mejores prácticas. De esta manera, todos podrán usar la aplicación, pero aquellos con navegadores modernos se beneficiarán aún más de las funciones de PWA.</p> + +<h2 id="Una_aplicación_de_ejemplo">Una aplicación de ejemplo</h2> + +<p>En esta serie de artículos, examinaremos el código fuente de un sitio web súper simple que enumera información sobre juegos enviados a la <a href="http://js13kgames.com/aframe">categoría A-Frame</a> en la Competición <a href="http://2017.js13kgames.com/">js13kGames 2017</a>. No tienes que pensar en cuál es el contenido real del sitio web; el punto principal es aprender a utilizar las funciones de PWA en sus propios proyectos.</p> + +<p>Puedes <a href="https://mdn.github.io/pwa-examples/js13kpwa/">ver esta aplicación en acción</a> en línea, y el código fuente está <a href="https://github.com/mdn/pwa-examples/tree/master/js13kpwa">disponible en GitHub</a>. Examinaremos este código detenidamente a lo largo de esta serie de artículos.</p> + +<p>Por ahora, ve a la segunda parte de esta serie, donde verás la estructura de la aplicación de ejemplo.</p> + +<p>{{NextMenu("Web/Progressive_web_apps/App_structure", "Web/Progressive_web_apps")}}</p> + +<div>{{QuickLinksWithSubpages("/es/docs/Web/Progressive_web_apps/")}}</div> diff --git a/files/es/web/progressive_web_apps/loading/index.html b/files/es/web/progressive_web_apps/loading/index.html new file mode 100644 index 0000000000..bc44773494 --- /dev/null +++ b/files/es/web/progressive_web_apps/loading/index.html @@ -0,0 +1,155 @@ +--- +title: Carga progresiva +slug: Web/Progressive_web_apps/Loading +tags: + - Cargar + - PWAs + - aplicaciones web progresivas + - js13kGames + - progresiva +translation_of: Web/Progressive_web_apps/Loading +--- +<div>{{PreviousMenu("Web/Progressive_web_apps/Re-engageable_Notifications_Push", "Web/Progressive_web_apps")}}</div> + +<p class="summary">En artículos anteriores cubrimos las API que nos ayudan a convertir nuestro ejemplo de <a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a> en una aplicación web progresiva: {{web.link("/es/docs/Web/Progressive_web_apps/Offline_Service_workers", "El servicio workers")}}, {{web.link("/es/docs/Web/Progressive_web_apps/Installable_PWAs", "Manifiestos web")}}, {{web.link("/es/docs/Web/Progressive_web_apps/Re-engagementable_Notifications_Push", "Notificaciones y Push")}}. En este artículo iremos aún más allá y mejoraremos el rendimiento de la aplicación cargando progresivamente sus recursos.</p> + +<h2 id="Primera_imagen_significativa">Primera imagen significativa</h2> + +<p>Es importante entregar algo significativo al usuario lo antes posible: cuanto más espere a que se cargue la página, mayor será la posibilidad de que se vaya antes de esperar a que todo termine. Deberíamos poder mostrarles al menos la vista básica de la página que quieren ver, con marcadores de posición en los lugares donde eventualmente se cargará más contenido.</p> + +<p>Esto se podría lograr mediante la carga progresiva, también conocida como <a href="https://en.wikipedia.org/wiki/Lazy_loading">carga diferida</a>. Se trata de aplazar la carga de recursos tanto como sea posible (HTML, CSS, JavaScript) y solo cargar inmediatamente los que realmente se necesitan para la primera experiencia.</p> + +<h2 id="Agrupar_versus_dividir">Agrupar versus dividir</h2> + +<p>Muchos visitantes no pasarán por todas las páginas de un sitio web, sin embargo, el enfoque habitual es agrupar todas las funciones que tenemos en un archivo grande. Un archivo <code>bundle.js</code> puede tener muchos megabytes, y un solo paquete <code>style.css</code> puede contener de todo, desde definiciones básicas de estructura CSS hasta todos los estilos posibles de cada versión del sitio: móvil, tableta, escritorio, solo impresión, etc.</p> + +<p>Es más rápido cargar toda esa información como un archivo en lugar de muchos archivos pequeños, pero si el usuario no necesita todo al principio, podríamos cargar solo lo que es crucial y luego gestionar otros recursos cuando sea necesario.</p> + +<h2 id="Recursos_que_bloquean_el_renderizado">Recursos que bloquean el renderizado</h2> + +<p>La agrupación es un problema, porque el navegador tiene que cargar HTML, CSS y JavaScript antes de poder pintar sus resultados renderizados en la pantalla. Durante los pocos segundos entre el acceso inicial al sitio web y la finalización de la carga, el usuario ve una página en blanco, lo cual es una mala experiencia.</p> + +<p>Para solucionarlo, podemos, por ejemplo, agregar <code>defer</code> a los archivos JavaScript:</p> + +<pre class="brush: html notranslate"><script src="app.js" defer></script> +</pre> + +<p>Se descargarán y ejecutarán <em>después</em> que el documento en sí haya sido procesado, por lo que no bloqueará la representación de la estructura HTML. También podemos dividir archivos css y agregarles tipos de medios:</p> + +<pre class="brush: html notranslate"><link rel="stylesheet" href="style.css"> +<link rel="stylesheet" href="print.css" media="print"> +</pre> + +<p>Esto le indicará al navegador que los cargue solo cuando se cumpla la condición.</p> + +<p>En nuestra aplicación de demostración js13kPWA, el CSS es lo suficientemente simple como para dejarlo todo en un solo archivo sin reglas específicas sobre cómo cargarlos. Podríamos ir aún más lejos y mover todo desde <code>style.css</code> a la etiqueta <code><style></code> en el <code><head></code> del <code>index.html</code>: esto mejoraría aún más el rendimiento, pero para la legibilidad del ejemplo también omitiremos este enfoque.</p> + +<h2 id="Imágenes">Imágenes</h2> + +<p>Además de JavaScript y CSS, es probable que los sitios web contengan varias imágenes. Cuando incluyes elementos {{HTMLElement("img")}} en tu HTML, todas las imágenes a las que se hace referencia se buscarán y descargarán durante el acceso inicial al sitio web. No es inusual tener megabytes de datos de imágenes para descargar antes de anunciar que el sitio está listo, pero esto nuevamente crea una mala percepción del rendimiento. No necesitamos todas las imágenes en la mejor calidad posible al comienzo de la visualización del sitio.</p> + +<p>Esto se puede optimizar. En primer lugar, debes utilizar herramientas o servicios similares a <a href="https://tinypng.com/">TinyPNG</a>, que reducirán el tamaño del archivo de tus imágenes sin alterar demasiado la calidad. Si has superado ese punto, puede empezar a pensar en optimizar la carga de imágenes mediante JavaScript. Explicaremos esto a continuación.</p> + +<h3 id="Marcador_de_posición_de_imagen">Marcador de posición de imagen</h3> + +<p>En lugar de tener todas las capturas de pantalla de los juegos referenciados en los atributos del elemento <code><img></code> <code>src</code>, que obligarán al navegador a descargarlos automáticamente, podemos hacerlo de forma selectiva a través de JavaScript. En su lugar, la aplicación js13kPWA usa una imagen de marcador de posición, que es pequeña y liviana, mientras que las rutas finales a las imágenes de destino se almacenan en los atributos <code>data-src</code>:</p> + +<pre class="brush: html notranslate"><img src='data/img/placeholder.png' data-src='data/img/SLUG.jpg' alt='NAME'> +</pre> + +<p>Esas imágenes se cargarán mediante JavaScript <em>después</em> que el sitio termine de construir la estructura HTML. La imagen del marcador de posición se escala de la misma manera que las imágenes originales, por lo que ocupará el mismo espacio y no hará que el diseño se vuelva a pintar a medida que se cargan las imágenes.</p> + +<h3 id="Cargar_a_través_de_JavaScript">Cargar a través de JavaScript</h3> + +<p>El archivo <code>app.js</code> procesa los atributos <code>data-src</code> así:</p> + +<pre class="brush: js notranslate">let imagesToLoad = document.querySelectorAll('img[data-src]'); +const loadImages = (image) => { + image.setAttribute('src', image.getAttribute('data-src')); + image.onload = () => { + image.removeAttribute('data-src'); + }; +};</pre> + +<p>La variable <code>imagesToLoad</code> contiene referencias a todas las imágenes, mientras que la función <code>loadImages</code> mueve la ruta de <code>data-src</code> a <code>src</code>. Cuando cada imagen está realmente cargada, eliminamos su atributo <code>data-src</code> porque ya no es necesario. Luego recorremos cada imagen y la cargamos:</p> + +<pre class="brush: js notranslate">imagesToLoad.forEach((img) => { + loadImages(img); +});</pre> + +<h3 id="Desenfoque_en_CSS">Desenfoque en CSS</h3> + +<p>Para que todo el proceso sea más atractivo visualmente, el marcador de posición se difumina en CSS.</p> + +<p><img alt="Captura de pantalla de imágenes de marcador de posición en la aplicación js13kPWA." src="https://mdn.mozillademos.org/files/15992/js13kpwa-placeholders.png" style="height: 684px; width: 675px;"></p> + +<p>Renderizamos las imágenes con un desenfoque al principio, por lo que se puede lograr una transición hacia la nitidez:</p> + +<pre class="brush: css notranslate">article img[data-src] { + filter: blur(0.2em); +} + +article img { + filter: blur(0em); + transition: filter 0.5s; +}</pre> + +<p>Esto eliminará el efecto de desenfoque en medio segundo, el cual se ve lo suficientemente bien para el efecto de "carga".</p> + +<h2 id="Carga_bajo_demanda">Carga bajo demanda</h2> + +<p>El mecanismo de carga de imágenes explicado en la sección anterior funciona bien: carga las imágenes después de renderizar la estructura HTML y aplica un agradable efecto de transición en el proceso. El problema es que todavía carga <em>todas</em> las imágenes simultáneamente, aunque el usuario solo verá las dos o tres primeras al cargar la página.</p> + +<p>Este problema se puede resolver con la nueva {{web.link("/es/docs/Web/API/Intersection_Observer_API", "API observador de intersecciones")}}; con esto nos podemos asegurar de que las imágenes se carguen solo cuando aparezcan en la ventana gráfica.</p> + +<h3 id="Observador_de_intersecciones">Observador de intersecciones</h3> + +<p>Esta es una mejora progresiva del ejemplo de uso anterior: {{web.link("/es/docs/Web/API/Intersection_Observer_API", "Observador de intersección")}} cargará las imágenes destino solo cuando el usuario se desplaza hacia abajo, lo cual hace que se exhiban en la ventana gráfica.</p> + +<p>Así es como se ve el código relevante:</p> + +<pre class="brush: js notranslate">if('IntersectionObserver' in window) { + const observer = new IntersectionObserver((items, observer) => { + items.forEach((item) => { + if(item.isIntersecting) { + loadImages(item.target); + observer.unobserve(item.target); + } + }); + }); + imagesToLoad.forEach((img) => { + observer.observe(img); + }); +} else { + imagesToLoad.forEach((img) => { + loadImages(img); + }); +}</pre> + +<p>Si se admite el objeto {{DOMxRef("IntersectionObserver")}}, la aplicación crea una nueva instancia del mismo. La función pasada como parámetro está manejando el caso cuando uno o más elementos se cruzan con el observador (es decir, aparecen dentro de la ventana gráfica). Podemos iterar sobre cada caso y reaccionar en consecuencia: cuando una imagen es visible, cargamos la imagen correcta y dejamos de observarla porque ya no necesitamos observarla.</p> + +<p>Reiteremos nuestra mención anterior de la mejora progresiva: el código está escrito para que la aplicación funcione tanto si <code>Intersection Observer</code> es compatible como si no. Si no es así, simplemente cargamos las imágenes usando el enfoque más básico cubierto anteriormente.</p> + +<h2 id="Mejoras">Mejoras</h2> + +<p>Recuerda que hay muchas formas de optimizar los tiempos de carga, y este ejemplo explora solo uno de los enfoques. Puedes intentar hacer que tus aplicaciones sean más a prueba de balas haciéndolas funcionar sin JavaScript, ya sea utilizando {{HTMLElement("noscript")}} para mostrar la imagen con el <code>src</code> final ya asignado, o envolviendo <code>Etiquetas <img></code> con elementos {{HTMLElement("a")}} que apuntan a las imágenes destino, para que el usuario pueda hacer clic y acceder a ellas cuando lo desee.</p> + +<p>No lo haremos porque la aplicación en sí depende de JavaScript; sin él, la lista de juegos ni siquiera se cargaría y el código del servicio <em>worker</em> no se ejecutaría.</p> + +<p>Podríamos reescribir el proceso de carga para cargar no solo las imágenes, sino los elementos completos que consisten en descripciones completas y enlaces. Funcionaría como un desplazamiento infinito: cargar los elementos de la lista solo cuando el usuario desplaza la página hacia abajo. De esa manera, la estructura HTML inicial sería mínima, el tiempo de carga sería aún menor y tendríamos beneficios de rendimiento aún mayores.</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Menos archivos para cargar inicialmente, archivos más pequeños divididos en módulos, uso de marcadores de posición y carga de más contenido bajo demanda: esto ayudará a lograr tiempos de carga inicial más rápidos, lo que brinda beneficios al creador de la aplicación y ofrece una experiencia más fluida para el usuario.</p> + +<p>Recuerda el enfoque de mejora progresiva: ofrece un producto utilizable sin importar el dispositivo o la plataforma, pero asegúrate de enriquecer la experiencia a quienes utilizan navegadores modernos.</p> + +<h2 id="Pensamientos_finales">Pensamientos finales</h2> + +<p>Eso es todo por esta serie de tutoriales: revisamos el <a href="https://github.com/mdn/pwa-examples/tree/master/js13kpwa">código fuente de la aplicación de ejemplo js13kPWA</a> y aprendimos sobre el uso de funciones de aplicaciones web progresivas, incluida una {{web.link("/es/docs/Web/Progressive_web_apps/Introduction", "Introducción")}}, {{web.link("/es/docs/Web/Progressive_web_apps/App_structure", "estructura PWA")}}, {{web.link("/es/docs/Web/Progressive_web_apps/Offline_Service_workers", "disponibilidad sin conexión con servicio workers")}}, {{web.link("/es/docs/Web/Progressive_web_apps/Installable_PWAs", "PWAs instalables")}}, y finalmente notificaciones. También explicamos el <code>push</code> con la ayuda del <a href="https://serviceworke.rs/">Libro de recetas para el servicio <em>workers</em></a>. Y en este artículo, hemos analizado el concepto de carga progresiva, incluido un interesante ejemplo que hace uso de la {{web.link("/es/docs/Web/API/Intersection_Observer_API", "API de Intersection Observer")}}.</p> + +<p>No dudes en experimentar con el código, mejorar tu aplicación existente con funciones de PWA o crear algo completamente nuevo por tu cuenta. Las PWAs ofrecen una gran ventaja sobre las aplicaciones web habituales.</p> + +<p>{{PreviousMenu("Web/Progressive_web_apps/Re-engageable_Notifications_Push", "Web/Progressive_web_apps")}}</p> + +<p>{{QuickLinksWithSubpages("/es/docs/Web/Progressive_web_apps/")}}</p> diff --git a/files/es/web/progressive_web_apps/offline_service_workers/index.html b/files/es/web/progressive_web_apps/offline_service_workers/index.html new file mode 100644 index 0000000000..d7349b1a8a --- /dev/null +++ b/files/es/web/progressive_web_apps/offline_service_workers/index.html @@ -0,0 +1,208 @@ +--- +title: Hacer que las PWAs trabajen desconectadas con servicio workers +slug: Web/Progressive_web_apps/Offline_Service_workers +tags: + - Desconectada + - PWAs + - Servicio workers + - aplicaciones web progresivas + - js13kGames + - progresiva +translation_of: Web/Progressive_web_apps/Offline_Service_workers +--- +<div>{{PreviousMenuNext("Web/Progressive_web_apps/App_structure", "Web/Progressive_web_apps/Installable_PWAs", "Web/Progressive_web_apps")}}</div> + +<p class="summary">Ahora que hemos visto cómo se ve la estructura de js13kPWA y hemos visto el intérprete básico en funcionamiento, veamos cómo se implementan las capacidades sin conexión con el Servicio <em>Worker</em>. En este artículo, analizamos cómo se usa en nuestro <a href="https://mdn.github.io/pwa-examples/js13kpwa/">ejemplo de js13kPWA</a> (<a href="https: //github.com/mdn/pwa-examples/tree/master/js13kpwa">ve el código fuente también</a>). Examinamos cómo agregar funcionalidad fuera de línea.</p> + +<h2 id="El_servicio_workers_explicado">El servicio <em>workers</em> explicado</h2> + +<p>El servicio <em>workers</em> son un delegado virtual entre el navegador y la red. Finalmente, solucionan problemas con los que los desarrolladores de aplicaciones para el usuario han luchado durante años, en particular, cómo almacenar correctamente en caché los activos de un sitio web y ponerlos a disposición cuando el dispositivo del usuario está desconectado.</p> + +<p>Se ejecutan en un hilo separado del código JavaScript principal de nuestra página y no tienen acceso a la estructura DOM. Esto introduce un enfoque diferente al de la programación web tradicional — la API no bloquea y puede enviar y recibir comunicación entre diferentes contextos. Puede darle a un servicio <em>worker</em> algo en lo que trabajar y recibir el resultado cuando esté listo utilizando un enfoque basado en una {{JSxRef("Objetos_globales/Promise", "promesa")}}.</p> + +<p>Pueden hacer mucho más que "solo" ofrecer capacidades sin conexión, incluido el manejo de notificaciones, la realización de cálculos pesadosen un hilo separado, etc. El servicio <em>workers</em> es bastante poderoso, ya que pueden tomar el control de las solicitudes de red, modificarlas, entregar respuestas personalizadas recuperadas de la caché o sintetizar respuestas por completo.</p> + +<h3 id="Seguridad">Seguridad</h3> + +<p>Debido a que son tan poderosos, los Servicios <em>Workers</em> solo se pueden ejecutar en contextos seguros (es decir, HTTPS). Si deseas experimentar primero antes de enviar tu código a producción, siempre puedes probar en un anfitrión local o configurar las páginas de GitHub — ambas admiten HTTPS.</p> + +<h2 id="Desconectado_primero">Desconectado primero</h2> + +<p>El patrón "desconectado primero" o "primero caché" es la estrategia más popular para entregar contenido al usuario. Si un recurso está almacenado en caché y disponible sin conexión, devuélvelo primero antes de intentar descargarlo del servidor. Si aún no está en la caché, descárgalo y almacénalo para uso futuro.</p> + +<h2 id="Progresiva_en_PWA">"Progresiva" en PWA</h2> + +<p>Cuando se implementa correctamente como una mejora progresiva, el servicio <em>workers</em> puede beneficiar a los usuarios que tienen navegadores modernos que admiten la API al brindar soporte fuera de línea, pero no romperán nada para aquellos que usan navegadores heredados.</p> + +<h2 id="El_servicio_workers_en_la_aplicación_js13kPWA">El servicio <em>workers</em> en la aplicación <code>js13kPWA</code></h2> + +<p>Suficiente teoría, ¡veamos algo de código real!</p> + +<h3 id="Registrar_el_servicio_worker">Registrar el servicio <em>worker</em></h3> + +<p>Comenzaremos mirando el código que registra un nuevo Servicio <em>Worker</em>, en el archivo <code>app.js</code>:</p> + +<p><strong>Nota</strong>: Usamos la sintaxis de las <strong>funciones flecha</strong> de <a href="http://es6-features.org/">ES6</a> en la implementación del servicio <em>worker</em></p> + +<pre class="brush: js notranslate">if('serviceWorker' in navigator) { + navigator.serviceWorker.register('./pwa-examples/js13kpwa/sw.js'); +};</pre> + +<p>Si la API del servicio <em>worker</em> es compatible con el navegador, se registra en el sitio mediante el método {{DOMxRef("ServiceWorkerContainer.register()")}}. Su contenido reside en el archivo <code>sw.js</code> y se puede ejecutar después de que el registro sea exitoso. Es la única parte del código de servicio <em>worker</em> que se encuentra dentro del archivo <code>app.js</code>; todo lo demás que sea específico de servicio <em>worker</em> se escribe en el archivo <code>sw.js</code>.</p> + +<h3 id="Ciclo_de_vida_de_un_servicio_worker">Ciclo de vida de un servicio <em>worker</em></h3> + +<p>Cuando se completa el registro, el archivo <code>sw.js</code> se descarga automáticamente, luego se instala y finalmente se activa.</p> + +<h4 id="Instalación">Instalación</h4> + +<p>La API nos permite agregar escuchas de eventos para los eventos clave que nos interesan; el primero es el evento <code>install</code>:</p> + +<pre class="brush: js notranslate">self.addEventListener('install', (e) => { + console.log('[Service Worker] Install'); +});</pre> + +<p>En el escucha de <code>install</code>, podemos iniciar la caché y agregarle archivos para su uso sin conexión. Nuestra aplicación <em>js13kPWA</em> hace exactamente eso.</p> + +<p>Primero, se crea una variable para almacenar el nombre de la caché y los archivos del intérprete de la aplicación se enumeran en un arreglo.</p> + +<pre class="brush: js notranslate">var cacheName = 'js13kPWA-v1'; +var appShellFiles = [ + '/pwa-examples/js13kpwa/', + '/pwa-examples/js13kpwa/index.html', + '/pwa-examples/js13kpwa/app.js', + '/pwa-examples/js13kpwa/style.css', + '/pwa-examples/js13kpwa/fonts/graduate.eot', + '/pwa-examples/js13kpwa/fonts/graduate.ttf', + '/pwa-examples/js13kpwa/fonts/graduate.woff', + '/pwa-examples/js13kpwa/favicon.ico', + '/pwa-examples/js13kpwa/img/js13kgames.png', + '/pwa-examples/js13kpwa/img/bg.png', + '/pwa-examples/js13kpwa/icons/icon-32.png', + '/pwa-examples/js13kpwa/icons/icon-64.png', + '/pwa-examples/js13kpwa/icons/icon-96.png', + '/pwa-examples/js13kpwa/icons/icon-128.png', + '/pwa-examples/js13kpwa/icons/icon-168.png', + '/pwa-examples/js13kpwa/icons/icon-192.png', + '/pwa-examples/js13kpwa/icons/icon-256.png', + '/pwa-examples/js13kpwa/icons/icon-512.png' +];</pre> + +<p>A continuación, los enlaces a las imágenes que se cargarán junto con el contenido del archivo <code>data/games.js</code> se generan en el segundo arreglo. Después de eso, ambos arreglos se fusionan usando la función {{JSxRef("Array.prototype.concat()")}}.</p> + +<pre class="brush: js notranslate">var gamesImages = []; +for(var i=0; i<games.length; i++) { + gamesImages.push('data/img/'+games[i].slug+'.jpg'); +} +var contentToCache = appShellFiles.concat(gamesImages);</pre> + +<p>Entonces podemos manejar el evento <code>install</code> en sí mismo:</p> + +<pre class="brush: js notranslate">self.addEventListener('install', (e) => { + console.log('[Service Worker] Install'); + e.waitUntil( + caches.open(cacheName).then((cache) => { + console.log('[Servicio Worker] Almacena todo en caché: contenido e intérprete de la aplicación'); + return cache.addAll(contentToCache); + }) + ); +});</pre> + +<p>Aquí hay dos cosas que necesitan una explicación: qué hace {{DOMxRef("ExtendableEvent.waitUntil")}} y qué es el objeto {{DOMxRef("Caches", "caches")}}.</p> + +<p>El servicio <em>worker</em> no se instala hasta que se ejecuta el código dentro de <code>waitUntil</code>. Este devuelve una promesa — este enfoque es necesario porque la instalación puede llevar algún tiempo, por lo que tenemos que esperar a que finalice.</p> + +<p><code>caches</code> es un objeto {{DOMxRef("CacheStorage")}} especial disponible en el ámbito del servicio <em>worker</em> dado para permitir guardar datos, guardar en el {{web.link("/es/docs/Web/API/Web_Storage_API", "almacenamiento web")}} no funcionará porque el almacenamiento web es síncrono. Con el servicio <em>workers</em>, usamos la API de <code>Cache</code> en su lugar.</p> + +<p>Aquí, abrimos una caché con un nombre dado, luego agregamos a la caché todos los archivos que nuestra aplicación usa, para que estén disponibles la próxima vez que se cargue (identificado por la URL de la solicitud).</p> + +<h4 id="Activación">Activación</h4> + +<p>También hay un evento <code>activate</code>, que se usa de la misma manera que <code>install</code>. Este evento generalmente se usa para eliminar cualquier archivo que ya no sea necesario y limpiar después la aplicación en general. No es necesario que hagamos eso en nuestra aplicación, así que lo omitiremos.</p> + +<h3 id="Responder_a_las_recuperaciones">Responder a las recuperaciones</h3> + +<p>También tenemos un evento <code>fetch</code> a nuestra disposición, que se activa cada vez que se activa una solicitud HTTP desde nuestra aplicación. Esto es muy útil, ya que nos permite interceptar solicitudes y reaccionar con respuestas personalizadas. Aquí hay un sencillo ejemplo de uso:</p> + +<pre class="brush: js notranslate">self.addEventListener('fetch', (e) => { + console.log('[Servicio Worker] Recurso obtenido ' + e.request.url); +});</pre> + +<p>La respuesta puede ser cualquier cosa que queramos: el archivo solicitado, su copia en caché o un fragmento de código JavaScript que hará algo específico; las posibilidades son infinitas.</p> + +<p>En nuestra aplicación de ejemplo, servimos contenido de la caché en lugar de la red siempre que el recurso realmente esté en la caché. Hacemos esto tanto si la aplicación está en línea como si está fuera de línea. Si el archivo no está en la caché, la aplicación primero lo agrega allí antes de servirlo:</p> + +<pre class="brush: js notranslate">self.addEventListener('fetch', (e) => { + e.respondWith( + caches.match(e.request).then((r) => { + console.log('[Servicio Worker] Obteniendo recurso: '+e.request.url); + return r || fetch(e.request).then((response) => { + return caches.open(cacheName).then((cache) => { + console.log('[Servicio Worker] Almacena el nuevo recurso: '+e.request.url); + cache.put(e.request, response.clone()); + return response; + }); + }); + }) + ); +});</pre> + +<p>Aquí, respondemos al evento <code>fetch</code> con una función que intenta encontrar el recurso en la caché y devolver la respuesta si está allí. Si no es así, usamos otra solicitud de recuperación para obtenerla de la red, luego almacenamos la respuesta en la caché para que esté disponible allí la próxima vez que se solicite.</p> + +<p>El método {{DOMxRef("FetchEvent.respondWith")}} toma el control; esta es la parte que funciona como un servidor delegado entre la aplicación y la red. Esto nos permite responder a cada solicitud con cualquier cosa que queramos: preparada por el servicio <em>worker</em>, tomada de la caché o modificada si es necesario.</p> + +<p>¡Eso es! Nuestra aplicación almacena en caché sus recursos al instalarlos y los sirve con la recuperación de la caché, por lo tanto, funciona incluso si el usuario está desconectado. También almacena en caché contenido nuevo cada vez que se agrega.</p> + +<h2 id="Actualizaciones">Actualizaciones</h2> + +<p>Todavía hay un punto que cubrir: ¿cómo se actualiza un servicio <em>worker</em> cuando hay disponible una nueva versión de la aplicación que contiene nuevos activos? El número de versión en el nombre de la caché es clave para esto:</p> + +<pre class="brush: js notranslate">var cacheName = 'js13kPWA-v1';</pre> + +<p>Cuando esto se actualice a v2, podemos agregar todos nuestros archivos (incluidos nuestros archivos nuevos) a una nueva caché:</p> + +<pre class="brush: js notranslate">contentToCache.push('/pwa-examples/js13kpwa/icons/icon-32.png'); + +// ... + +self.addEventListener('install', (e) => { + e.waitUntil( + caches.open('js13kPWA-v2').then((cache) => { + return cache.addAll(contentToCache); + }) + ); +});</pre> + +<p>Se instala un nuevo servicio <em>worker</em> en segundo plano y el anterior (v1) funciona correctamente hasta que no hay páginas que lo utilicen; el nuevo servicio <em>worker</em> se activa y se hace cargo de la administración de la página desde el anterior.</p> + +<h2 id="Limpiar_la_caché">Limpiar la caché</h2> + +<p>¿Recuerdas el evento <code>active</code> que omitimos?, se puede usar para borrar la antigua caché que ya no necesitamos:</p> + +<pre class="brush: js notranslate">self.addEventListener('activate', (e) => { + e.waitUntil( + caches.keys().then((keyList) => { + return Promise.all(keyList.map((key) => { + if(key !== cacheName) { + return caches.delete(key); + } + })); + }) + ); +});</pre> + +<p>Esto asegura que solo tengamos los archivos que necesitamos en la caché, por lo que no dejamos basura; el <a href="/es/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria">espacio de caché disponible en el navegador es limitado</a>, por lo que es una buena idea limpiarlo nosotros mismos después.</p> + +<h2 id="Otros_casos_de_uso">Otros casos de uso</h2> + +<p>Servir archivos desde la caché no es la única característica que ofrece el servicio <em>worker</em>. Si tienes que hacer cálculos pesados, los puedes descargar del hilo principal y hacerlos en el <em>worker</em>, y recibir el resultado tan pronto como estén disponibles. En cuanto al rendimiento, puedes obtener recursos que no se necesitan en este momento, pero que podrían serlo en un futuro cercano, por lo que la aplicación será más rápida cuando realmente los necesite.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>En este artículo, analizamos cómo puedes hacer que tu PWA funcione sin conexión con el servicio <em>workers</em>. Asegúrate de consultar nuestra documentación adicional si deseas obtener más información sobre los conceptos detrás de la {{web.link("/es/docs/Web/API/Service_Worker_API", "API de Service Worker")}} y cómo usarla con más detalle.</p> + +<p>El servicio <em>workers</em> también se utilizan cuando se trata de {{web.link("/es/docs/Web/API/Push_API", "notificaciones push")}}; esto se explicará en un artículo posterior.</p> + +<p>{{PreviousMenuNext("Web/Progressive_web_apps/App_structure", "Web/Progressive_web_apps/Installable_PWAs", "Web/Progressive_web_apps")}}</p> + +<div>{{QuickLinksWithSubpages("/es/docs/Web/Progressive_web_apps/")}}</div> diff --git a/files/es/web/progressive_web_apps/re-engageable_notifications_push/index.html b/files/es/web/progressive_web_apps/re-engageable_notifications_push/index.html new file mode 100644 index 0000000000..0c03dfb151 --- /dev/null +++ b/files/es/web/progressive_web_apps/re-engageable_notifications_push/index.html @@ -0,0 +1,251 @@ +--- +title: >- + Cómo hacer que las PWAs se puedan volver a conectar usando Notificaciones y + Push +slug: Web/Progressive_web_apps/Re-engageable_Notifications_Push +tags: + - Notificaciones + - PWAs + - Push + - aplicaciones web progresivas + - js13kGames + - progresiva +translation_of: Web/Progressive_web_apps/Re-engageable_Notifications_Push +--- +<div>{{PreviousMenuNext("Web/Apps/Progressive/Installable_PWAs", "Web/Apps/Progressive/Loading", "Web/Apps/Progressive")}}</div> + +<p class="summary">Tener la capacidad de almacenar en caché el contenido de una aplicación para que funcione sin conexión es una gran característica. Permitir que el usuario instale la aplicación web en su pantalla de inicio es aún mejor. Pero en lugar de depender solo de las acciones del usuario, podemos hacer más, utilizando mensajes <code>push</code> y notificaciones para volver a interactuar automáticamente y entregar contenido nuevo siempre que esté disponible.</p> + +<h2 id="Dos_APIs_un_objetivo">Dos APIs, un objetivo</h2> + +<p>{{web.link("/es/docs/Web/API/Push_API", "API Push")}} y {{web.link("/es/docs/Web/API/Notifications_API", "API de notificaciones")}} son dos APIs independientes, pero funcionan bien juntas cuando deseas proporcionar una funcionalidad atractiva en tu aplicación. <code>Push</code> se utiliza para entregar contenido nuevo desde el servidor a la aplicación sin ninguna intervención del lado del cliente, y su operación es manejada por el servicio <em>worker</em> de la aplicación. El servicio <em>worker</em> puede utilizar las notificaciones para mostrar nueva información al usuario, o al menos alertarlo cuando algo se haya actualizado.</p> + +<p>Funcionan fuera de la ventana del navegador, al igual que el servicio <em>worker</em>, por lo que se pueden enviar actualizaciones y se pueden mostrar notificaciones cuando la página de la aplicación está desenfocada o incluso cerrada.</p> + +<h2 id="Notificaciones">Notificaciones</h2> + +<p>Comencemos con las notificaciones: pueden funcionar sin <code>push</code>, pero son muy útiles cuando se combinan con ellas. Para empezar, veámoslo de forma aislada.</p> + +<h3 id="Pedir_permiso">Pedir permiso</h3> + +<p>Para mostrar una notificación, primero debes solicitar permiso. Sin embargo, en lugar de mostrar la notificación de inmediato, la mejor práctica dicta que deberíamos mostrar la ventana emergente cuando el usuario la solicite haciendo clic en un botón:</p> + +<pre class="brush: js notranslate">var button = document.getElementById("notifications"); +button.addEventListener('click', function(e) { + Notification.requestPermission().then(function(result) { + if(result === 'granted') { + randomNotification(); + } + }); +});</pre> + +<p>Esto muestra una ventana emergente usando el propio servicio de notificaciones del sistema operativo:</p> + +<p><img alt="Notificación de js13kPWA." src="https://mdn.mozillademos.org/files/15930/js13kpwa-notification.png" style="display: block; height: 640px; margin: 0px auto; width: 360px;"></p> + +<p>Cuando el usuario confirma recibir notificaciones, la aplicación las puede mostrar. El resultado de la acción del usuario puede ser predeterminada, otorgada o denegada. La opción predeterminada se elige cuando el usuario no hace una elección, y las otras dos se establecen cuando el usuario hace clic en sí o no, respectivamente.</p> + +<p>Cuando se acepta, el permiso funciona tanto para notificaciones como para <code>push</code>.</p> + +<h3 id="Crea_una_notificación">Crea una notificación</h3> + +<p>La aplicación de ejemplo crea una notificación a partir de los datos disponibles: se elige un juego al azar y el elegido alimenta la notificación con el contenido — establece el nombre del juego como título, menciona al autor en el cuerpo y muestra la imagen como un icono:</p> + +<pre class="brush: js notranslate">function randomNotification() { + var randomItem = Math.floor(Math.random()*games.length); + var notifTitle = games[randomItem].name; + var notifBody = 'Creado por '+games[randomItem].author+'.'; + var notifImg = 'data/img/'+games[randomItem].slug+'.jpg'; + var options = { + body: notifBody, + icon: notifImg + } + var notif = new Notification(notifTitle, options); + setTimeout(randomNotification, 30000); +}</pre> + +<p>Se crea una nueva notificación aleatoria cada 30 segundos hasta que se vuelve demasiado molesta y el usuario la desactiva. (En una aplicación real, las notificaciones deberían ser mucho menos frecuentes y más útiles). La ventaja de la API de notificaciones es que utiliza la funcionalidad de notificación del sistema operativo. Esto significa que las notificaciones se pueden mostrar al usuario incluso cuando no están mirando la aplicación web, y las notificaciones son similares a las que muestran las aplicaciones nativas.</p> + +<h2 id="Push"><code>Push</code></h2> + +<p><code>Push</code> es más complicado que las notificaciones: necesitamos suscribirnos a un servidor que luego enviará los datos a la aplicación. El servicio <em>worker</em> de la aplicación recibirá datos <code>push</code> del servidor, que luego se pueden mostrar usando el sistema de notificaciones u otro mecanismo si lo deseas.</p> + +<p>La tecnología aún se encuentra en una etapa muy temprana; algunos ejemplos de uso utilizan la plataforma de mensajería en la nube de Google, pero se están reescribiendo para admitir <a href="#" title="https://blog.mozilla.org/services/2016/08/23/sending-vapid-protected-webpush-Notifications-via-mozillas-push-service/">IDVAP</a> (<strong>Id</strong>entificación <strong>vo</strong>luntaria de la <strong>ap</strong>licación), que ofrece una capa adicional de seguridad para tu aplicación. Puedes examinar los <a href="https://serviceworke.rs/push-payload.html">ejemplos del libro de recetas del servicio <em>workers</em></a>, intenta configurar un servidor de mensajería <code>push</code> usando <a href="https://firebase.google.com/">Firebase</a>, o crea tu propio servidor (utilizando Node.js, por ejemplo).</p> + +<p>Como se mencionó anteriormente, para poder recibir mensajes <code>push</code>, debes tener un servicio <em>worker</em>, cuyos conceptos básicos ya se explican en {{web.link("/es/docs/Web/Apps/Progressive/Offline_Service_workers", "Cómo hacer que las PWAs funcionen sin conexión con el servicio workers")}}. Dentro del servicio <em>workers</em>, se crea un mecanismo de suscripción del servicio <code>push</code>.</p> + +<pre class="brush: js notranslate">registration.pushManager.getSubscription() .then( /* ... */ );</pre> + +<p>Una vez que el usuario está suscrito, puede recibir notificaciones automáticas del servidor.</p> + +<p>Desde el lado del servidor, todo el proceso tiene que estar encriptado con claves públicas y privadas por razones de seguridad — permitir que todos envíen mensajes <code>push</code> sin seguridad usando tu aplicación sería una idea terrible. Consulta la <a href="https://jrconlin.github.io/WebPushDataTestPage/">página de prueba de encriptación de datos <code>Push</code> en la Web</a> para obtener información detallada sobre cómo proteger el servidor. El servidor almacena toda la información recibida cuando el usuario se suscribió, por lo que los mensajes se pueden enviar más tarde cuando sea necesario.</p> + +<p>Para recibir mensajes <code>push</code>, podemos escuchar el evento {{event("push")}} en el archivo <code>Service Worker</code>:</p> + +<pre class="brush: js notranslate">self.addEventListener('push', function(e) { /* ... */ });</pre> + +<p>Los datos se pueden recuperar y luego mostrar como una notificación al usuario inmediatamente. Esto, por ejemplo, se puede usar para recordarle algo al usuario o para informarle sobre contenido nuevo disponible en la aplicación.</p> + +<h3 id="Ejemplo_push">Ejemplo <code>push</code></h3> + +<p><code>Push</code> necesita que la parte del servidor funcione, por lo que no podemos incluirla en el ejemplo js13kPWA alojado en las páginas de GitHub, ya que solo ofrece alojamiento de archivos estáticos. Todo se explica en el <a href="https://serviceworke.rs/">Libro de recetas para servicios <em>worker</em></a>; consulta el <a href="https://serviceworke.rs/push-payload.html">Demo de carga <code>push</code></a>.</p> + +<p>Esta demostración consta de tres archivos:</p> + +<ul> + <li><a href="https://github.com/mozilla/serviceworker-cookbook/blob/master/push-payload/index.js">index.js</a>, que contiene el código fuente de nuestra aplicación</li> + <li><a href="https://github.com/mozilla/serviceworker-cookbook/blob/master/push-payload/server.js">server.js</a>, que contiene la parte del servidor (escrito en Node.js)</li> + <li><a href="https://github.com/mozilla/serviceworker-cookbook/blob/master/push-payload/service-worker.js">service-worker.js</a>, que contiene el código específico de <code>Service Worker</code>.</li> +</ul> + +<p>Exploremos todos estos</p> + +<h4 id="index.js"><code>index.js</code></h4> + +<p>El archivo <code>index.js</code> comienza registrando el servicio <code>worker</code>:</p> + +<pre class="brush: js notranslate">navigator.serviceWorker.register('service-worker.js') +.then(function(registration) { + return registration.pushManager.getSubscription() + .then(async function(subscription) { + // parte de registro + }); +}) +.then(function(subscription) { + // parte de la suscripción +});</pre> + +<p>Es un poco más complicado que el servicio <em>worker</em> que vimos en la <a href="https://mdn.github.io/pwa-examples/js13kpwa/">demostración de js13kPWA</a>. En este caso particular, después de registrarse, usamos el objeto de registro para suscribirnos y luego usamos el objeto de suscripción resultante para completar todo el proceso.</p> + +<p>En la parte de registro, el código se ve así:</p> + +<pre class="brush: js notranslate">if(subscription) { + return subscription; +}</pre> + +<p>Si el usuario ya se ha suscrito, devolvemos el objeto de suscripción y pasamos a la parte de suscripción. Si no, iniciamos una nueva suscripción:</p> + +<pre class="brush: js notranslate">const response = await fetch('./vapidPublicKey'); +const vapidPublicKey = await response.text(); +const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);</pre> + +<p>La aplicación obtiene la clave pública del servidor y convierte la respuesta en texto; luego se debe convertir a un Uint8Array (para admitir Chrome). Para obtener más información sobre las claves <em>IDVAP</em>, puedes leer <a href="https://blog.mozilla.org/services/2016/08/23/sending-vapid-identified-webpush-notifications-via-mozillas-push-service/">Envío de notificaciones <em>WebPush</em> identificadas por <em>IDVAP</em> a través de la publicación de blog del servicio <code>Push</code> de Mozilla</a>.</p> + +<p>La aplicación ahora puede usar {{DOMxRef("PushManager")}} para suscribir al nuevo usuario. Hay dos opciones pasadas al método {{DOMxRef("PushManager.subscribe()")}} — la primera es <code>userVisibleOnly: true</code>, lo cual significa que todas las notificaciones enviadas al usuario serán visibles para ellos, y el segundo es <code>applicationServerKey</code>, que contiene nuestra clave <em>IDVAP</em> adquirida y convertida con éxito.</p> + +<pre class="brush: js notranslate">return registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: convertedVapidKey +});</pre> + +<p>Ahora pasemos a la parte de la suscripción: la aplicación primero envía los detalles de la suscripción como JSON al servidor mediante <code>Fetch</code>.</p> + +<pre class="brush: js notranslate">fetch('./register', { + method: 'post', + headers: { + 'Content-type': 'application/json' + }, + body: JSON.stringify({ + subscription: subscription + }), +});</pre> + +<p>Luego, se define la función {{DOMxRef("onclick", "GlobalEventHandlers.onclick")}} en el botón <em>Suscribirse</em>:</p> + +<pre class="brush: js notranslate">document.getElementById('doIt').onclick = function() { + const payload = document.getElementById('notification-payload').value; + const delay = document.getElementById('notification-delay').value; + const ttl = document.getElementById('notification-ttl').value; + + fetch('./sendNotification', { + method: 'post', + headers: { + 'Content-type': 'application/json' + }, + body: JSON.stringify({ + subscription: subscription, + payload: payload, + delay: delay, + ttl: ttl, + }), + }); +};</pre> + +<p>Cuando se hace clic en el botón, <code>fetch</code> solicita al servidor que envíe la notificación con los parámetros dados: <code>payload</code> es el texto que se mostrará en la notificación, <code>delay</code> define un retraso en segundos hasta que se muestra la notificación, y <code>ttl</code> es la configuración de tiempo de vida que mantiene la notificación disponible en el servidor durante un período de tiempo específico, también definido en segundos.</p> + +<p>Ahora, en el siguiente archivo JavaScript.</p> + +<h4 id="server.js"><code>server.js</code></h4> + +<p>La parte del servidor está escrita en Node.js y se debe alojar en un lugar adecuado, que es un tema de un artículo completamente separado. Aquí solo proporcionaremos una descripción general de alto nivel.</p> + +<p>El <a href="https://www.npmjs.com/package/web-push">módulo <code>web-push</code></a> se utiliza para configurar las claves <code>IDVAP</code> y, opcionalmente, generarlas si aún no están disponibles.</p> + +<pre class="brush: js notranslate">const webPush = require('web-push'); + +if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) { + console.log("Debes configurar las variables de entorno VAPID_PUBLIC_KEY y " + + "VAPID_PRIVATE_KEY. Puedes utilizar las siguientes: "); + console.log(webPush.generateVAPIDKeys()); + return; +} + +webPush.setVapidDetails( + 'https://serviceworke.rs/', + process.env.VAPID_PUBLIC_KEY, + process.env.VAPID_PRIVATE_KEY +); +</pre> + +<p>A continuación, un módulo define y exporta todas las rutas que una aplicación necesita manejar: obtener la clave pública <em>IDVAP</em>, registrarse y luego enviar notificaciones. Puedes ver las variables del archivo <code>index.js</code> que se está utilizando: <code>payload</code>, <code>delay</code> y <code>ttl</code>.</p> + +<pre class="brush: js notranslate">module.exports = function(app, route) { + app.get(route + 'vapidPublicKey', function(req, res) { + res.send(process.env.VAPID_PUBLIC_KEY); + }); + + app.post(route + 'register', function(req, res) { + + res.sendStatus(201); + }); + + app.post(route + 'sendNotification', function(req, res) { + const subscription = req.body.subscription; + const payload = req.body.payload; + const options = { + TTL: req.body.ttl + }; + + setTimeout(function() { + webPush.sendNotification(subscription, payload, options) + .then(function() { + res.sendStatus(201); + }) + .catch(function(error) { + console.log(error); + res.sendStatus(500); + }); + }, req.body.delay * 1000); + }); +};</pre> + +<h4 id="service-worker.js"><code>service-worker.js</code></h4> + +<p>El último archivo que veremos es el del servicio <em>worker</em>:</p> + +<pre class="brush: js notranslate">self.addEventListener('push', function(event) { + const payload = event.data ? event.data.text() : 'no payload'; + event.waitUntil( + self.registration.showNotification('ServiceWorker Cookbook', { + body: payload, + }) + ); +});</pre> + +<p>Todo lo que hace es agregar un escucha para el evento {{Event("push")}}, crear la variable de carga útil que consiste en el texto tomado de los datos (o crear una cadena para usar si los datos están vacíos), y luego esperar hasta la notificación se muestra al usuario.</p> + +<p>No dudes en explorar el resto de los ejemplos en el <a href="https://serviceworke.rs/">Libro de recetas para el servicio <em>workers</em></a> si deseas saber cómo se manejan: el <a href="https://github.com/mozilla/serviceworker-cookbook/">código fuente completo está disponible en GitHub</a>. Hay una gran colección de ejemplos de uso que muestran el uso general, pero también la inserción web, las estrategias de almacenamiento en caché, el rendimiento, el trabajo sin conexión y más.</p> + +<p>{{PreviousMenuNext("Web/Apps/Progressive/Installable_PWAs", "Web/Apps/Progressive/Loading", "Web/Apps/Progressive")}}</p> + +<div>{{QuickLinksWithSubpages("/es/docs/Web/Progressive_web_apps/")}}</div> diff --git a/files/es/web/progressive_web_apps/ventajas/index.html b/files/es/web/progressive_web_apps/ventajas/index.html new file mode 100644 index 0000000000..2268f23321 --- /dev/null +++ b/files/es/web/progressive_web_apps/ventajas/index.html @@ -0,0 +1,62 @@ +--- +title: Ventajas de una aplicación web progresiva (AWP) +slug: Web/Progressive_web_apps/Ventajas +tags: + - AWP + - aplicaciones web progresivas + - conceptos + - ventajas +translation_of: Web/Progressive_web_apps/Introduction#Advantages_of_web_applications +--- +<p class="summary">Las Aplicaciones Web Progresivas deben tener todas las ventajas enumeradas en las siguientes secciones a continuación.</p> + + + +<h2 id="Reconocible">Reconocible<img alt="" src="https://mdn.mozillademos.org/files/12654/discoverable.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>El objetivo final es que las aplicaciones web deben tener una mejor representación en los motores de búsqueda, ser más fáciles de exponer, catalogar y clasificar, y tener metadatos que los navegadores puedan utilizar para darles capacidades especiales.</p> + +<p>Algunas de las capacidades ya se han habilitado en ciertas plataformas basadas en la web mediante tecnologías patentadas como <a href="http://ogp.me/">Open Graph</a>, que proporciona un formato para especificar metadatos similares en el <code><head></code> de HTML usando metaetiquetas.</p> + +<p>El estándar web relevante aquí es el <a href="/en-US/docs/Web/Manifest">Manifiesto de aplicación web</a>, que define las características de una aplicación, como el nombre, el icono, la pantalla de presentación y los colores del tema en un archivo de manifiesto con formato JSON. Esto es para usar en contextos como listados de aplicaciones y pantallas de inicio de dispositivos.</p> + +<ul> +</ul> + +<h2 id="Instalable">Instalable<img alt="" src="https://mdn.mozillademos.org/files/12656/installable.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>Una parte central de la experiencia de aplicaciones es que los usuarios tengan iconos de aplicaciones en su pantalla de inicio, y ser capaz de pulsar para abrir aplicaciones en su propio contenedor nativo que se siente bien integrado con la plataforma subyacente.</p> + +<p>Las aplicaciones web modernas pueden tener esta sensación de aplicación nativa a través de las propiedades establecidas dentro del manifiesto de la aplicación web, y a través de una función disponible en los navegadores de teléfonos inteligentes modernos llamada <a href="/en-US/docs/Web/Apps/Progressive/Add_to_home_screen">Añadir a la página de inicio</a>.</p> + +<h2 id="Enlazable">Enlazable<img alt="" src="https://mdn.mozillademos.org/files/12658/linkable.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>Una de las características más potentes de la Web es ser capaz de enlazar a una aplicación en una URL específica. No necesita tienda de aplicaciones, ningún proceso de instalación complejo. Así es como siempre ha sido.</p> + +<h2 id="Independencia_de_la_red">Independencia de la red<img alt="" src="https://mdn.mozillademos.org/files/12660/network-independent.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>Las aplicaciones web modernas pueden funcionar cuando la red no es confiable, o incluso inexistente. Las ideas básicas detrás de la independencia de la red son:</p> + +<ul> + <li>Volver a visitar un sitio y obtener sus contenidos, incluso si no hay una conexión red disponible.</li> + <li>Explore cualquier tipo de contenido que el usuario haya visitado anteriormente al menos una vez, incluso en situaciones de poca conectividad.</li> + <li>Controlar lo que se muestra al usuario en situaciones en las que no hay conectividad.</li> +</ul> + +<p>Esto se logra mediante una combinación de tecnologías: <a href="/en-US/docs/Web/API/Service_Worker_API">Service Workers</a> para controlar las solicitudes de página (por ejemplo, almacenarlas sin conexión), la <a href="/en-US/docs/Web/API/Cache">Cache API</a> para almacenar respuestas a solicitudes de red fuera de línea (muy útil para almacenar recursos del sitio) y tecnologías de almacenamiento de datos del lado del cliente como <a href="/en-US/docs/Web/API/Web_Storage_API">Web Storage</a> y <a href="/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a> para almacenar datos de la aplicación sin conexión.</p> + +<h2 id="Progresiva">Progresiva<img alt="" src="https://mdn.mozillademos.org/files/12662/progressive.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>Las aplicaciones web modernas se pueden desarrollar para proporcionar una experiencia súper genial a los navegadores totalmente capaces, y una experiencia aceptable (aunque no tan brillante) para los navegadores menos capaces. Hemos estado haciendo esto durante años con las mejores prácticas como <a href="/en-US/docs/Glossary/Progressive_Enhancement">mejora progresiva</a>.</p> + +<h2 id="Reconectable">Reconectable<img alt="" src="https://mdn.mozillademos.org/files/12666/re-engageable.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>Una de las principales ventajas de las plataformas nativas es la facilidad con la que los usuarios pueden volver a participar mediante actualizaciones y contenido nuevo, incluso cuando no están mirando la aplicación o utilizando sus dispositivos. Las aplicaciones web modernas ahora también pueden hacer esto, utilizando nuevas tecnologías como <a href="/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers">Service Workers</a> para controlar páginas, el <a href="/en-US/docs/Web/API/Push_API">Web Push API</a> para enviar actualizaciones directamente del servidor a la aplicación a través de un service worker, y la <a href="/en-US/docs/Web/API/Notifications_API">API de notificaciones</a> para generar notificaciones del sistema para ayudar a atraer a los usuarios cuando no están en el navegador.</p> + +<h2 id="Adaptable">Adaptable<img alt="" src="https://mdn.mozillademos.org/files/12650/responsive.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>Las aplicaciones web adaptables usan tecnologías como consultas de media y viewport para asegurarse de que sus interfaces se ajusten a cualquier factor de forma: escritorio, móvil, tableta o lo que sea que venga después.</p> + +<h2 id="Seguro">Seguro<img alt="" src="https://mdn.mozillademos.org/files/12664/safe.svg" style="float: right; height: 47px; width: 38px;"></h2> + +<p>La plataforma web proporciona un mecanismo de entrega seguro que evita la intromisión y garantiza que el contenido no haya sido alterado, siempre que aproveche de HTTPS y desarrolle sus aplicaciones teniendo en cuenta la seguridad. Además, puede verificar la verdadera naturaleza de una AWP confirmando que está en la URL correcta, mientras que las aplicaciones en las tiendas de aplicaciones a menudo pueden parecer una cosa, pero ser otra (<a href="https://twitter.com/andreasbovens/status/926965095296651264">ejemplo</a>).</p> |
