PWA es f谩cil. Hola habr

Continuando con nuestro conocimiento de las aplicaciones web progresivas. Despu茅s de la 煤ltima parte te贸rica , es hora de pasar a la pr谩ctica.

Hoy construiremos un PWA simple pero completo "Hello Habr".




La aplicaci贸n est谩 disponible en https://altrusl.imtqy.com/habr-pwa/hello-habr/ . Cuando se abre en un navegador en un dispositivo m贸vil, es posible agregar un acceso directo a la pantalla de inicio y comenzar en modo de pantalla completa.

Si alguien quiere probar el ejemplo en cuesti贸n en su computadora, Chrome le permite trabajar localmente con aplicaciones PWA simples sin instalar servidores web de terceros con certificados SSL.
Instrucciones para ejecutar "Hello Habr" localmente
Debe instalar esta o una extensi贸n similar desde Chrome Web Store, que es el servidor web local. Sin soporte PHP, por supuesto.



Los archivos Hello Habr se pueden tomar de GitHub-a - https://github.com/altrusl/habr-pwa/tree/master/hello-habr

Ponga todo en un directorio y ap煤ntelo al servidor web.


"Hola Habr" consta de una p谩gina. 脡l muestra en ella una imagen (logotipo) y una inscripci贸n animada.

C贸digo "Hola Habr"

index.html


<html> <head> <title>Hello Habr</title> <script src="hh.js"></script> <link rel="stylesheet" href="hh.css" /> <script type="text/javascript"> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(function(registration) { console.log('Registration successful, scope is:', registration.scope); }) .catch(function(error) { console.log('Service worker registration failed, error:', error); }); } </script> </head> <body> <div class="center"> <p id="text"></p> </div> <div id="logo"></div> </body> </html> 

hh.css


 @font-face { font-family: Zaplyv-Heavy; src: url(Zaplyv-Heavy.otf); } body { display: flex; align-items: center; align-content: center; justify-content: center; overflow: auto; } .center { font-family: Zaplyv-Heavy; font-size: 8vmax; } #logo { background-image: url(logo.jpg); background-size: 100%; width: 100px; height: 100px; position: absolute; top: 0; right: 0; margin: 10px; } 

hh.js


 window.onload = function() { fetch("hh.txt?mode=nocache").then(data => data.text()).then(data => { animateText(data) }); } function animateText(data) { var ele = document.getElementById("text"), txt = data.split(""); var interval = setInterval(function(){ if(!txt[0]){ return clearInterval(interval); }; ele.innerHTML += txt.shift(); }, 150); } 

hh.txt


 Hello Hubr 


La fuente personalizada tambi茅n est谩 presente. Total: el conjunto completo m铆nimo de recursos de un sitio web promedio. Si abre index.html en un navegador, se muestran una imagen y una inscripci贸n. La inscripci贸n se carga mediante javascript a trav茅s de la b煤squeda desde el archivo hh.txt, el modelo m谩s simple de una aplicaci贸n PWA general.

Si abre sin sw.js, este ser谩 un sitio web normal. Agregue Service Worker a nuestros archivos.

sw.js
 // Caches var CURRENT_CACHES = { font: 'font-cache-v1', css:'css-cache-v1', js:'js-cache-v1', site: 'site-cache-v1', image: 'image-cache-v1' }; self.addEventListener('install', (event) => { self.skipWaiting(); console.log('Service Worker has been installed'); }); self.addEventListener('activate', (event) => { var expectedCacheNames = Object.keys(CURRENT_CACHES).map(function(key) { return CURRENT_CACHES[key]; }); // Delete out of date caches event.waitUntil( caches.keys().then(function(cacheNames) { return Promise.all( cacheNames.map(function(cacheName) { if (expectedCacheNames.indexOf(cacheName) == -1) { console.log('Deleting out of date cache:', cacheName); return caches.delete(cacheName); } }) ); }) ); console.log('Service Worker has been activated'); }); self.addEventListener('fetch', function(event) { console.log('Fetching:', event.request.url); event.respondWith(async function() { const cachedResponse = await caches.match(event.request); if (cachedResponse) { console.log("\tCached version found: " + event.request.url); return cachedResponse; } else { console.log("\tGetting from the Internet:" + event.request.url); return await fetchAndCache(event.request); } }()); }); function fetchAndCache(request) { return fetch(request) .then(function(response) { // Check if we received a valid response if (!response.ok) { return response; // throw Error(response.statusText); } var url = new URL(request.url); if (response.status < 400 && response.type === 'basic' && url.search.indexOf("mode=nocache") == -1 ) { var cur_cache; if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("application/javascript") >= 0) { cur_cache = CURRENT_CACHES.js; } else if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("text/css") >= 0) { cur_cache = CURRENT_CACHES.css; } else if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("font") >= 0) { cur_cache = CURRENT_CACHES.font; } else if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("image") >= 0) { cur_cache = CURRENT_CACHES.image; } else if (response.headers.get('content-type') && response.headers.get('content-type').indexOf("text") >= 0) { cur_cache = CURRENT_CACHES.site; } if (cur_cache) { console.log('\tCaching the response to', request.url); return caches.open(cur_cache).then(function(cache) { cache.put(request, response.clone()); return response; }); } } return response; }) .catch(function(error) { console.log('Request failed for: ' + request.url, error); throw error; }); } 


Como puede ver, creamos cinco cach茅s para cada tipo de recurso. La cach茅 del sitio es para archivos html. Todos los recursos se almacenan en cach茅, con la excepci贸n de aquellos que tienen "mode = nocache" en la consulta GET, y esta es nuestra solicitud para el archivo hh.txt con una l铆nea para la inscripci贸n.
A veces puede ver que el recurso se toma de la memoria cach茅 del disco. Este es un problema com煤n al desarrollar aplicaciones con Service Worker, por lo que es mejor deshabilitar el cach茅 de disco (cach茅 del navegador). Y no en mi navegador, sino en el servidor, por ejemplo, en
.htaccess
 # Cache-Control Headers <ifModule mod_headers.c> <FilesMatch (\.css|\.js|sprites\.png)$> Header unset ETag Header unset Expires Header set Cache-Control "no-cache" </FilesMatch> </IfModule> 

La l贸gica detr谩s de sw.js es simple: "Cach茅 recurriendo a la red". Primero, el recurso solicitado se verifica en la memoria cach茅; si est谩 all铆, se toma y se devuelve al navegador desde all铆. Si no, se obtiene de la red, se devuelve al navegador y se almacena en cach茅 una copia del recurso.

Despu茅s de la primera apertura de la p谩gina index.html en la consola de Chrom-a, los registros sobre la instalaci贸n y activaci贸n del Service Worker son visibles. Despu茅s de la segunda apertura, nuestras cach茅s se crean en el almacenamiento y nuestros recursos se colocan en ellas. Tambi茅n se ve que durante las aperturas posteriores, solo las solicitudes de hh.txt van al servidor web, todos los dem谩s recursos se toman del Service Worker-a.

Captura de pantalla


Index.html, hh.css, hh.js, hh.otf, logo.jpg almacenados localmente: este es el shell de la aplicaci贸n, un shell de recursos y datos est谩ticos, que act煤a como un shell de programa en el cliente. Toda la informaci贸n din谩mica necesaria para que el sitio funcione se obtiene mediante solicitudes de JavaScript al servidor y la visualizaci贸n de los datos recibidos en la aplicaci贸n shell-e. En nuestro caso, esta es una solicitud de text.txt.

Para ser llamado PWA completamente funcional, "Hello Habr" carece de una cosa: los 铆conos en la pantalla de inicio de los tel茅fonos inteligentes y se inician en modo de pantalla completa.

Para hacer esto, debe conectar el manifiesto de la aplicaci贸n en index.html:
manifest.json
 { "short_name": "Hello Habr", "name": "Hello Habr - PWA example", "icons": [ { "src": "logo3.jpg", "type": "image/jpg", "sizes": "192x192" }, { "src": "logo2.jpg", "type": "image/jpg", "sizes": "512x512" } ], "start_url": "index.html", "background_color": "#3367D6", "display": "standalone", "scope": "/habr-pwa/hello-habr/", "theme_color": "#3367D6" } 

Est谩 conectado en index.html:
 <link rel="manifest" href="manifest.json"> 


Despu茅s de eso, los navegadores m贸viles (cada uno a su manera) ofrecer谩n crear un acceso directo para la aplicaci贸n en la pantalla de inicio. Cuando se inicia mediante un acceso directo, la aplicaci贸n se abrir谩 en modo independiente , sin controles del navegador. Hay m谩s detalles sobre las opciones de manifiesto en Google Developers .

La aplicaci贸n Hello Habr posee m铆nimamente todas las caracter铆sticas de PWA y lo es esencialmente. Como puede ver, para transferir un sitio simple a PWA, solo necesita conectar el manifiesto y el archivo de Service Worker. Usado por sw.js es bastante universal.

La pr贸xima vez transferiremos el sitio terminado a PWA a CMS Joomla (el sitio est谩 "listo para usar" con los datos de demostraci贸n iniciales). Adem谩s, sw.js permanecer谩 casi igual.

Source: https://habr.com/ru/post/es419585/


All Articles