Aplicación web Vue 3 convertida a PWA

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que se componga de CSS, JavaScript y HTML se puede convertir en una PWA, y ese también es el caso con Vue 3.

Aunque Vue 3 con Vite compila a CSS, HTML y JS que podemos convertir a PWA quise darme a la tarea de documentar el proceso de creación. Por favor toma en cuenta que te recomiendo revisar el siguiente artículo para saber lo básico sobre las PWA:

Crear y publicar Progressive Web App – Convertir app web en PWA

Veamos entonces cómo convertir una aplicación de Vue 3 con Vite en una PWA.

Aplicación de ejemplo

Este artículo fue usado para convertir una aplicación de Vue 3 en PWA. La PWA en cuestión es un montador de imágenes en lote que puedes usar en el siguiente enlace para comprobar que es una PWA en toda regla:

Creador de credenciales y etiquetas escolares

Aplicación web Vue 3 convertida a PWA
Aplicación web Vue 3 convertida a PWA

Esta no es la primera vez que convierto una app de Vue 3 en PWA, pues también lo hice con el Diseñador para impresoras térmicas.

Crear manifest.json agregando iconos y capturas de pantalla

Comencemos creando el manifest.json en la carpeta public. Su contenido queda así:

{
    "name": "Card ID creator",
    "description": "Batch card and ID creation",
    "short_name": "Card creator",
    "theme_color": "#2196f3",
    "background_color": "#2196f3",
    "display": "standalone",
    "orientation": "portrait",
    "scope": "./",
    "start_url": "./",
    "icons": [
        {
            "src": "./images/icono-512.png",
            "type": "image/png",
            "sizes": "512x512"
        }
    ],
    "screenshots": [
        {
            "src": "./images/screenshot.png",
            "type": "image/png",
            "sizes": "1920x1014",
            "form_factor": "wide"
        },
        {
            "src": "./images/screenshot.png",
            "type": "image/png",
            "sizes": "1920x1014"
        }
    ]
}

En esa misma carpeta public coloqué las imágenes (screenshot.png e icono-512.png) dentro de images. Luego hay que importar ese manifiesto en el index.html:

<link rel="manifest" href="./manifest.json">

Puedes aprender más sobre el formato del archivo de manifiesto en este enlace: https://web.dev/articles/add-manifest?hl=es

Creando service worker

Vamos a necesitar Comlink. Yo ejecuté workbox wizard y le dije que la carpeta que hay que convertir a PWA es dist, pues más adelante cuando se compile la app de Vue 3 con npm run build todo el resultado se colocará en dist.

Cuando el asistente terminó, generó un archivo llamado workbox-config.js que tuve que renombrar a workbox-config.cjs en la carpeta raíz porque si no lo renombraba me daba algunos errores.

Mi workbox-config.cjs ya completo queda como se ve a continuación:

module.exports = {
	globDirectory: 'dist/',
	globPatterns: [
		'**/*.{css,js,wasm,ico,html,png,jpg,json,svg}'
	],
	swDest: 'dist/sw.js',
	ignoreURLParametersMatching: [
		/^utm_/,
		/^fbclid$/
	],
	maximumFileSizeToCacheInBytes: 5000000,
	sourcemap: false,
	
};

Fíjate que swDest es el destino del service worker. Con la configuración actual, se va a crear un archivo llamado sw.js que después debemos importar en el index.html.

Modifiqué la propiedad maximumFileSizeToCacheInBytes porque tenía un archivo wasm que era muy pesado, y también modifiqué sourcemap porque no quiero archivos map.

Importando service worker en index.html

Hasta este punto ya existe:

  • Configuración de Workbox en workbox-config.cjs
  • El manifiesto en manifest.json
  • La importación de ese manifiesto en el index.html

Ahora falta agregar la importación del service worker en el index.html:

  <script type="text/javascript">
    if ("serviceWorker" in navigator) {
      navigator.serviceWorker.register("sw.js");
    }
  </script>

Aquí estamos suponiendo que sw.js va a ser hermano de index.html. En modo desarrollo nos va a mostrar un error porque sw.js no va a existir, pero cuando compilemos la app con npm run build y tanto el index.html como el sw.js estén en dist entonces todo va a funcionar.

Solo como referencia, aquí dejo mi index.html completo:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <link rel="icon" href="/favicon.ico">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Card creator - By Parzibyte</title>
  <link rel="manifest" href="./manifest.json">
  <script type="text/javascript">
    if ("serviceWorker" in navigator) {
      navigator.serviceWorker.register("sw.js");
    }
  </script>
  <link rel="icon" type="image/png" href="./favicon-48x48.png" sizes="48x48" />
  <link rel="icon" type="image/svg+xml" href="./favicon.svg" />
  <link rel="shortcut icon" href="./favicon.ico" />
  <link rel="apple-touch-icon" sizes="180x180" href="./apple-touch-icon.png" />
</head>

<body>
  <div id="app"></div>
  <script type="module" src="/src/main.ts"></script>
</body>

</html>

Compilando aplicación de Vue 3

Recapitulemos. Hasta este momento ya tenemos:

  • Configuración de Workbox para generar el Service Worker y colocarlo en la carpeta dist
  • Manifiesto para la PWA en manifest.json
  • Importación del manifiesto e instalación del ServiceWorker en el index.html

Ahora solo falta crear la carpeta dist, y eso lo hará automáticamente el comando npm run build. Así que ejecutamos:

npm run build

Y eso creará la carpeta dist con el siguiente contenido:

total 388
-rw-r--r-- 1 parzibyte parzibyte  44630 oct. 23 03:38 apple-touch-icon.png
drwxr-xr-x 1 parzibyte parzibyte      0 nov.  5 11:03 assets
-rw-r--r-- 1 parzibyte parzibyte  15086 oct. 23 03:38 favicon.ico
-rw-r--r-- 1 parzibyte parzibyte 313683 oct. 23 03:38 favicon.svg
-rw-r--r-- 1 parzibyte parzibyte   4751 oct. 23 03:38 favicon-48x48.png
drwxr-xr-x 1 parzibyte parzibyte      0 nov.  5 11:03 images
-rw-r--r-- 1 parzibyte parzibyte    896 nov.  5 11:03 index.html
-rw-r--r-- 1 parzibyte parzibyte    792 oct. 22 21:36 manifest.json

Fíjate en que el index.html y el manifest.json son hermanos, así como la carpeta images y todo lo demás, pero todavía nos falta el sw.js así que vamos al último paso.

Generar Service Worker con Workbox después de compilar

Ahora que la carpeta dist ya existe podemos ejecutar workbox generateSW workbox-config.cjs en donde workbox-config.cjs es el archivo que el wizard ha creado por nosotros.

Una vez ejecutado nos va a aparecer una salida como la siguiente:

C:\xampp\htdocs\credenciales>workbox generateSW workbox-config.cjs
Using configuration from C:/xampp/htdocs/credenciales/workbox-config.cjs.
Browserslist: caniuse-lite is outdated. Please run:
  npx update-browserslist-db@latest
  Why you should do it regularly: https://github.com/browserslist/update-db#readme
The service worker files were written to:
  • C:/xampp/htdocs/credenciales/dist/sw.js
  • C:/xampp/htdocs/credenciales/dist/workbox-ea0bf025.js
The service worker will precache 15 URLs, totaling 7.15 MB.

Lo importante es el archivo sw.js y workbox-ea0bf025.js (mismo que puede cambiar su nombre en cada generación). Esos archivos fueron copiados a la carpeta dist automáticamente o mejor dicho fueron generados dentro de esa carpeta.

Ahora veamos de nuevo el contenido de dist:

total 408
-rw-r--r-- 1 parzibyte parzibyte  44630 oct. 23 03:38 apple-touch-icon.png
drwxr-xr-x 1 parzibyte parzibyte      0 nov.  5 11:03 assets
-rw-r--r-- 1 parzibyte parzibyte  15086 oct. 23 03:38 favicon.ico
-rw-r--r-- 1 parzibyte parzibyte 313683 oct. 23 03:38 favicon.svg
-rw-r--r-- 1 parzibyte parzibyte   4751 oct. 23 03:38 favicon-48x48.png
drwxr-xr-x 1 parzibyte parzibyte      0 nov.  5 11:03 images
-rw-r--r-- 1 parzibyte parzibyte    896 nov.  5 11:03 index.html
-rw-r--r-- 1 parzibyte parzibyte    792 oct. 22 21:36 manifest.json
-rw-r--r-- 1 parzibyte parzibyte   1961 nov.  5 11:06 sw.js
-rw-r--r-- 1 parzibyte parzibyte  14273 nov.  5 11:06 workbox-ea0bf025.js

Los archivos fueron agregados correctamente. Y ahora sí ya podemos distribuir el contenido de dist, pues ya es una PWA.

Compilando más adelante

La configuración de Workbox para generar el workbox-config.cjs, la importación del sw.js, la importación del manifiest.json y la creación del manifiesto solo se hace una vez. Después, cada vez que hagas cambios a tu aplicación web con Vue 3 y quieras convertirla a PWA ejecuta:

npm run build

Luego:

workbox generateSW workbox-config.cjs

Y distribuye todo lo que existe dentro de dist. Con “distribuir” me refiero a subir el contenido de dist a un servidor local o de internet que pueda servir archivos estáticos.

Distribuir aplicación

Puedes alojar la PWA en cualquier lugar, incluso en las GitHub pages. Yo tengo un tutorial para desplegarla en un servidor con Apache.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

Dejar un comentario

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