¿Cómo desarrollar una aplicación web progresiva usando ReactJS?

Las aplicaciones Progressive React responden muy rápido a las acciones del usuario. Se cargan rápido y son atractivos como una aplicación móvil. Pueden acceder a funciones de dispositivos móviles, aprovechar el sistema operativo y tener un alcance muy alto. Habilita la instalación, la sincronización en segundo plano, el almacenamiento en caché y el soporte fuera de línea y otras funciones como las notificaciones automáticas. Con React, podemos mejorar muy fácilmente las aplicaciones web progresivamente para que se vean y se sientan como aplicaciones móviles nativas.

Ahora veamos la implementación paso a paso sobre cómo desarrollar una aplicación web progresiva usando React.

Paso 1: con ReactJS, es aún más fácil crear una aplicación web progresiva o incluso convertir un proyecto React existente en uno. En la terminal de su editor de texto, ingrese el siguiente comando. CRA crea un modelo para Progressive Web App que puede modificar fácilmente según sus necesidades.

npx create-react-app reaccionar-pwa –template cra-template-pwa

cd reaccionar-pwa

Este comando crea una nueva aplicación React llamada react-pwa y navega hasta el directorio de su aplicación. Puede modificar aún más su archivo manifest.json y otros archivos como el logotipo para personalizar la aplicación y personalizarla.

Paso 2:  implementemos las funcionalidades de una PWA y agreguemos más funciones a nuestra aplicación. En la terminal de su editor de texto, ingrese el siguiente comando para instalar algunos paquetes de terceros y npm.

npm install –save web-push reaccionar-enrutador-dom bootstrap reaccionar-bootstrap

Estructura del proyecto: agregue worker.js y feed.js en su carpeta pública y una carpeta de componentes dentro de su carpeta src , para que se vea así.

Estructura del proyecto

Paso 3: Registre un Service Worker: un Service Worker es un tipo especial de archivo de secuencia de comandos que funciona entre el navegador y la red. Nos ayuda a realizar funcionalidades únicas y se registra cada vez que se carga una página. Para registrar un nuevo trabajador de servicio en su aplicación React, en el archivo worker.js en su carpeta pública ( public/worker.js ), agregue el siguiente código.

Javascript

var STATIC_CACHE_NAME = "gfg-pwa";
var DYNAMIC_CACHE_NAME = "dynamic-gfg-pwa";
  
// Add Routes and pages using React Browser Router
var urlsToCache = ["/", "/search", "/aboutus", "/profile"];
  
// Install a service worker
self.addEventListener("install", (event) => {
  
  // Perform install steps
  event.waitUntil(
    caches.open(STATIC_CACHE_NAME).then(function (cache) {
      console.log("Opened cache");
      return cache.addAll(urlsToCache);
    })
  );
});
  
// Cache and return requests
self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((cacheRes) => {
  
      // If the file is not present in STATIC_CACHE,
      // it will be searched in DYNAMIC_CACHE
      return (
        cacheRes ||
        fetch(event.request).then((fetchRes) => {
          return caches.open(DYNAMIC_CACHE_NAME).then((cache) => {
            cache.put(event.request.url, fetchRes.clone());
            return fetchRes;
          });
        })
      );
    })
  );
});
  
// Update a service worker
self.addEventListener("activate", (event) => {
  var cacheWhitelist = ["gfg-pwa"];
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames.map((cacheName) => {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

Paso 4:  Es posible que algunos navegadores antiguos no sean compatibles con los trabajadores del servicio. Sin embargo, la mayoría de los navegadores modernos como Google Chrome tienen soporte incorporado para trabajadores de servicios. En caso de ausencia de soporte, la aplicación se ejecutará como una aplicación web normal. Para asegurarnos de que no nos encontramos con un error o que la aplicación no falla, debemos verificar si el estado de soporte de los trabajadores del servicio en el navegador del cliente. Para hacerlo, actualice su archivo index.html en la carpeta pública ( public/index.html) con el siguiente código.

Javascript

<script>
  if ("serviceWorker" in navigator) {
  
    window.addEventListener("load", function () {
      navigator.serviceWorker
        .register("/worker.js")
        .then(
          function (registration) {
            console.log(
              "Worker registration successful",
              registration.scope);
          },
          function (err) {
            console.log("Worker registration failed", err);
          }
        )
        .catch(function (err) {
          console.log(err);
        });
    });
  } else {
    console.log("Service Worker is not"
      + " supported by browser.");
  }
</script>

Paso 5:  Ahora que tenemos el código para las funcionalidades básicas de un service worker. Necesitamos registrarlo. Para hacerlo, cambie una línea en index.js en la carpeta src ( src/index.js ) de

service-worker.unregister()

a

serviceWorker.register()

Nuestro trabajador de servicio, es decir, worker.js, ahora se registrará con éxito.

Paso para ejecutar la aplicación:  Ahora, ingresa el siguiente comando en la terminal de tu editor de texto.

npm start

Salida: Esto abrirá su aplicación React en localhost://3000 en el navegador. Y, en las Herramientas de desarrollo, en la pestaña Aplicación, puede ver que su trabajador de servicio está registrado con un mensaje de «Registro de trabajador exitoso» en su consola.

Trabajador de servicio registrado

Explicación: Ahora tenemos el trabajador de servicio básico funcionando de la manera que queremos. Para implementar otras funciones similares a las de un dispositivo nativo, implementemos el envío de una notificación en caso de que el usuario se desconecte mientras usa la aplicación. Además, para ver sus nuevas funciones, no es necesario volver a ejecutar la aplicación, bastará con hacer clic en el botón de recarga.

Paso 6: Envío de una notificación automática cuando está desconectado: las notificaciones automáticas son una característica móvil nativa. Y el navegador solicitará automáticamente el permiso del usuario en la configuración predeterminada. Web-push es un paquete de terceros que nos ayudará con las claves VAPID para enviar una notificación. Ahora, necesitamos tener una clave API VAPID para comenzar a implementar notificaciones Push en nuestra aplicación. Tenga en cuenta que cada CLAVE API VAPID es única para cada trabajador de servicio.

Para generar las claves API, escriba lo siguiente en la terminal:

./node_modules/.bin/web-push generate-vapid-keys

Ahora, en la terminal de su editor de texto, web-push proporciona dos de sus propias claves insípidas. Vamos a utilizar la clave pública vacía para generar notificaciones automáticas.

Modifique el script en index.html. Esto codificará su clave de API VAPID de string base64 y la conectará con el trabajador del servicio para que pueda enviar notificaciones.

Javascript

<script>
  if ("serviceWorker" in navigator) {
    function urlBase64ToUint8Array(base64String) {
      const padding = "=".repeat((4 - 
          (base64String.length % 4)) % 4);
      const base64 = (base64String + padding)
        .replace(/\-/g, "+")
        .replace(/_/g, "/");
  
      const rawData = window.atob(base64);
      const outputArray = new Uint8Array(rawData.length);
  
      for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
      }
      return outputArray;
    }
  
    function determineAppServerKey() {
      var vapidPublicKey =
        "YOUR_PUBLIC_KEY";
      return urlBase64ToUint8Array(vapidPublicKey);
    }
  
    window.addEventListener("load", function () {
      navigator.serviceWorker
        .register("/worker.js")
        .then(
          function (registration) {
            console.log(
              "Worker registration successful",
              registration.scope
            );
            return registration.pushManager
              .getSubscription()
              .then(function (subscription) {
                registration.pushManager.subscribe({
                  userVisibleOnly: true,
                  applicationServerKey: determineAppServerKey(),
                });
              });
          },
          function (err) {
            console.log("Worker registration failed", err);
          }
        )
        .catch(function (err) {
          console.log(err);
        });
    });
  } else {
    console.log("Service Worker is not supported by browser.");
  }
</script>

Paso 7:  usemos esta nueva funcionalidad para enviar notificaciones automáticas cada vez que nos desconectemos. En worker.js, modifique el evento fetch y agregue el siguiente código. Dentro de la función de mostrar notificación, puede agregar más propiedades y modificarlas según sus deseos.

Javascript

self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((cacheRes) => {
      return (
        cacheRes ||
        fetch(event.request).then((fetchRes) => {
          return caches.open(DYNAMIC_CACHE_NAME)
          .then((cache) => {
            cache.put(event.request.url, fetchRes.clone());
            return fetchRes;
          });
        })
      );
    })
  );
  if (!navigator.onLine) {
    if (event.request.url === 
        "http://localhost:3000/static/js/main.chunk.js") {
      event.waitUntil(
        self.registration.showNotification("Internet", {
          body: "internet not working",
          icon: "logo.png",
        })
      );
    }
  }
});

La función self.registration.showNotification muestra la notificación deseada e incluso pide permiso antes de mostrar una.

Paso 8:  para verificar que la sincronización y el almacenamiento en caché funcionen sin conexión, puede cambiar el estado sobre su Service Worker en Dev Tools a ‘sin conexión’ o hacer lo mismo sobre la aplicación. Ahora, cada vez que se desconecte, verá una notificación automática que indica que se desconectó. 

Notificación push: Internet no funciona

Tenga en cuenta que aún puede ver las páginas, aunque es posible que se pierdan algunas funcionalidades. Esto se debe a que estas páginas y URL predeterminadas, una vez visitadas, se almacenan en la memoria caché. Por lo tanto, asegúrese de cancelar el registro y volver a registrarlo en la pestaña Aplicación cada vez que realice cambios en sus archivos durante el desarrollo.

Paso 9: agregar funciones nativas como cámara y geolocalización: PWA permite usar funciones nativas como acceder a la cámara web y averiguar la ubicación con la ayuda de los trabajadores del servicio. Comencemos con la creación de la interfaz de usuario para esto primero donde podemos usar estas funcionalidades, crear un archivo Profile.js en ‘src/Profile.js’ al que podemos navegar a través de /profile usando React Routes .

Javascript

import React from "react";
import { InputGroup, Button, Container } 
        from "react-bootstrap";
  
const Profile = () => {
  return (
    <>
      <Container className={style.styling}>
        <br></br>
        <InputGroup className="mb-3">
          <InputGroup.Text>Latitude</InputGroup.Text>
          <InputGroup.Text id="latitude">00</InputGroup.Text>
        </InputGroup>
        <br></br>
        <InputGroup className="mb-3">
          <InputGroup.Text>Longitude</InputGroup.Text>
          <InputGroup.Text id="longitude">00</InputGroup.Text>
        </InputGroup>
        <br></br>
        <InputGroup className="mb-3">
          <InputGroup.Text>Location</InputGroup.Text>
        </InputGroup>
        <Button variant="outline-secondary" id="locationBtn">
          Get Location
        </Button>
        <br></br>
        <br></br>
        <Button variant="outline-secondary" id="photoBtn">
          Take a Picture Now!
        </Button>
        <video id="player" autoPlay width="320px" 
            height="240px"></video>
        <canvas
          id="canvas"
          width="320px"
          height="240px"
          style={{ display: "none" }}
        ></canvas>
        <Button variant="outline-secondary" id="capture">
          Capture
        </Button>
        <br></br>
        <div id="pick-image">
          <h6>Pick an Image instead</h6>
          <input type="file" accept="image/*"
            id="image-picker"></input>
        </div>
        <br></br>
        <br></br>
      </Container>
    </>
  );
};
  
export default Profile;

Paso 10:  ahora agreguemos un archivo feed.js en public/feed.js para implementar la funcionalidad de ubicación y cámara.

Javascript

window.onload = function () {
  var photo = document.getElementById("photoBtn");
  var locationBtn = document.getElementById("locationBtn");
  locationBtn.addEventListener("click", handler);
  var capture = document.getElementById("capture");
  photo.addEventListener("click", initializeMedia);
  capture.addEventListener("click", takepic);
};
  
function initializeLocation() {
  if (!("geolocation" in navigator)) {
    locationBtn.style.display = "none";
  }
}
  
function handler(event) {
  if (!("geolocation" in navigator)) {
    return;
  }
  
  navigator.geolocation.getCurrentPosition(
  function (position) {
    console.log(position);
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
    console.log(lat);
    console.log(lon);
    latitude.innerHTML = lat;
    longitude.innerHTML = lon;
  });
}
  
function initializeMedia() {
  if (!("mediaDevices" in navigator)) {
    navigator.mediaDevices = {};
  }
  
  if (!("getUserMedia" in navigator.mediaDevices)) {
    navigator.mediaDevices.getUserMedia = 
    function (constraints) {
      var getUserMedia =
        navigator.webkitGetUserMedia 
        || navigator.mozGetUserMedia;
  
      if (!getUserMedia) {
        return Promise.reject(new Error(
            "getUserMedia is not implemented!"));
      }
  
      return new Promise(function (resolve, reject) {
        getUserMedia.call(navigator, 
            constraints, resolve, reject);
      });
    };
  }
  
  navigator.mediaDevices
    .getUserMedia({ video: true })
    .then(function (stream) {
      player.srcObject = stream;
      player.style.display = "block";
    })
    .catch(function (err) {
      console.log(err);
      imagePicker.style.display = "block";
    });
}
  
function takepic(event) {
  canvas.style.display = "block";
  player.style.display = "none";
  capture.style.display = "none";
  
  var context = canvas.getContext("2d");
  context.drawImage(
    player,
    0,
    0,
    canvas.width,
    player.videoHeight / (player.videoWidth / canvas.width)
  );
  player.srcObject.getVideoTracks().forEach(function (track) {
    track.stop();
  });
}

Paso 11:  Cree un nuevo archivo llamado feed.js en la carpeta ( /src/public ). En feed.js, usamos geolocalización y mediaDevices para implementar funcionalidades de ubicación y cámara respectivamente. También puede usar la API de Google Geocoder para convertir estas latitudes y longitudes en el nombre de un lugar.

Salida: ahora puede navegar a localhost: 3000/profile para tomar su foto y obtener la ubicación.

Funciones nativas habilitadas

Explicación: al hacer clic en el botón Obtener ubicación, se activará navigator.geolocation.getCurrentPosition dentro de la función del controlador, por lo que se llenarán los campos de latitud y longitud con los valores apropiados. Para obtener el nombre exacto de la ciudad, intente usar la API de Geocoder como se mencionó anteriormente. Del mismo modo, al hacer clic en el botón Tomar una foto, ahora se activará navigator.mediaDevices.getUserMedia dentro de la función initializeMedia, abriendo así la cámara frontal y tomando una foto. Ambas funciones primero agregarán permisos y luego se ejecutarán.

Publicación traducida automáticamente

Artículo escrito por sgshreya024 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *