feat: app instalable desde el navegador (PWA)
vite-plugin-pwa genera manifest.webmanifest + service worker en el build. Iconos nuevos generados a partir del logo actual (192, 512, maskable para Android). El service worker precachea solo assets estaticos (JS/CSS/iconos) -- /api nunca se cachea, siempre va a la red, asi los datos no quedan desactualizados. Se actualiza solo (autoUpdate) sin pedirle nada al usuario. Probado: build genera sw.js/manifest correctamente, el service worker registra y activa en un browser real, y la app (login, listado de proyectos, llamadas a /api) sigue funcionando igual que antes -- sin regresiones. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,16 @@
|
|||||||
# Changelog - project.linkedcorp.net
|
# Changelog - project.linkedcorp.net
|
||||||
|
|
||||||
|
## [1.22.0] - 2026-09-17
|
||||||
|
### Added
|
||||||
|
- La app ahora es instalable desde el navegador (PWA): ícono propio, se abre en su propia ventana
|
||||||
|
sin barra del navegador, con `manifest.webmanifest` + service worker (`vite-plugin-pwa`). El
|
||||||
|
service worker precachea solo los assets estáticos del build (JS/CSS/íconos) — las llamadas a
|
||||||
|
`/api` nunca se cachean, siempre van a la red, así los datos nunca quedan desactualizados. Se
|
||||||
|
actualiza solo (`autoUpdate`) en cuanto hay una versión nueva desplegada, sin pedirle nada al
|
||||||
|
usuario.
|
||||||
|
- Íconos nuevos generados a partir del logo actual: `pwa-192x192.png`, `pwa-512x512.png` y una
|
||||||
|
versión "maskable" (con zona de seguridad) para Android.
|
||||||
|
|
||||||
## [1.21.1] - 2026-09-17
|
## [1.21.1] - 2026-09-17
|
||||||
### Added
|
### Added
|
||||||
- Filtro por severidad (Alta/Media/Baja) en el panel "Errores del sistema", además del filtro por
|
- Filtro por severidad (Alta/Media/Baja) en el panel "Errores del sistema", además del filtro por
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "project-linkedcorp-backend",
|
"name": "project-linkedcorp-backend",
|
||||||
"version": "1.21.1",
|
"version": "1.22.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/server.js",
|
"main": "src/server.js",
|
||||||
|
|||||||
Generated
+4178
-3
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "project-linkedcorp-frontend",
|
"name": "project-linkedcorp-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.21.1",
|
"version": "1.22.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"vite": "^6.4.3"
|
"vite": "^6.4.3",
|
||||||
|
"vite-plugin-pwa": "^1.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 149 KiB |
@@ -1,11 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import { registerSW } from 'virtual:pwa-register';
|
||||||
import App from './app/App.jsx';
|
import App from './app/App.jsx';
|
||||||
import { installGlobalErrorReporter } from './utils/errorReporter.js';
|
import { installGlobalErrorReporter } from './utils/errorReporter.js';
|
||||||
import './styles/tokens.css';
|
import './styles/tokens.css';
|
||||||
import './styles/app.css';
|
import './styles/app.css';
|
||||||
|
|
||||||
installGlobalErrorReporter();
|
installGlobalErrorReporter();
|
||||||
|
// autoUpdate: toma la version nueva del service worker sola en cuanto esta lista, sin pedirle
|
||||||
|
// nada al usuario (no hay riesgo de mostrar una version vieja de la UI por mucho tiempo).
|
||||||
|
registerSW({ immediate: true });
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
|||||||
+32
-1
@@ -1,8 +1,39 @@
|
|||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { VitePWA } from 'vite-plugin-pwa';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [
|
||||||
|
react(),
|
||||||
|
VitePWA({
|
||||||
|
registerType: 'autoUpdate',
|
||||||
|
includeAssets: ['favicon.svg', 'favicon.png', 'apple-touch-icon.png'],
|
||||||
|
manifest: {
|
||||||
|
id: '/',
|
||||||
|
lang: 'es-EC',
|
||||||
|
name: 'LinkedCorp Proyectos',
|
||||||
|
short_name: 'LinkedCorp',
|
||||||
|
description: 'Gestión de proyectos y actividades de TI',
|
||||||
|
theme_color: '#0078d4',
|
||||||
|
background_color: '#202020',
|
||||||
|
display: 'standalone',
|
||||||
|
start_url: '/',
|
||||||
|
icons: [
|
||||||
|
{ src: 'pwa-192x192.png', sizes: '192x192', type: 'image/png' },
|
||||||
|
{ src: 'pwa-512x512.png', sizes: '512x512', type: 'image/png' },
|
||||||
|
{ src: 'pwa-maskable-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
workbox: {
|
||||||
|
// El service worker nunca debe interceptar /api — siempre a la red, nunca cache de
|
||||||
|
// respuestas viejas (datos de proyectos/actividades desactualizados seria peor que no
|
||||||
|
// tener PWA). navigateFallback (para que recargar una ruta como /proyectos/5 sirva el
|
||||||
|
// index.html cacheado) queda excluido de /api de forma explicita, aunque de por si esas
|
||||||
|
// llamadas no son navegaciones de pagina.
|
||||||
|
navigateFallbackDenylist: [/^\/api\//],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
server: {
|
server: {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
port: 5196,
|
port: 5196,
|
||||||
|
|||||||
Reference in New Issue
Block a user