Resolviendo el Problema de la Caché en Aplicaciones Web: Mi Solución
¡Hola a todos! Hoy quiero compartir una solución que desarrollé para abordar un problema común pero molesto en las aplicaciones web: la caché. La caché puede ser un dolor de cabeza, especialmente cuando los usuarios ven una versión desactualizada de la aplicación, lo que puede dar lugar a casos falsos o experiencias de usuario frustrantes.
El Desafío
Mi empresa se enfrentaba a este problema y necesitábamos una solución que fuera general, fácilmente integrable en nuestras aplicaciones y que nos permitiera mantener el control de las versiones de la aplicación en producción.
La Solución
Desarrollé un servicio que realiza una solicitud HTTP que sale de la aplicación para volver y encontrar un archivo .json
con información de versionado. Este archivo se compara con otro archivo .ts
importado en el servicio, esta es el que se queda “pegado” en la caché. Permítanme explicar cómo funciona:
- Archivos de versionado: crea dos archivos, uno
.json
y otro.ts
.
config.json
{
"version": "1.0.0"
}
config_version.ts
export const config_version = {
version: "1.0.0",
};
- Crea un servicio cache.service.ts: en el servicio
cache.service.ts
vas realizar una petición http que sale de la aplicación para volver y si hay diferencia entre el resultado de la petición aconfig.json
contra la importación de la versióncondig_version.ts
vas a hacer reload de la app.
cache.service.ts
import { Injectable } from "@angular/core";
import { HttpClient, HttpHeaders } from "@angular/common/http";
import { config_version } from "@assets/config_version";
import { CanActivate } from "@angular/router";
import { ToastrService } from "ngx-toastr";
@Injectable({
providedIn: "root",
})
export class CacheService implements CanActivate {
constructor(
private httpClient: HttpClient,
private toastrService: ToastrService
) {}
canActivate(): boolean {
this.getCache();
return true;
}
getCache() {
const headers = new HttpHeaders()
.set("Cache-Control", "no-cache")
.set("Pragma", "no-cache");
return this.httpClient
.get<any>(`assets/config.json`, { headers })
.subscribe((config) => {
if (config.version != config_version.version) {
this.toastrService.warning(
"Se ha detectado una nueva versión de la aplicación, se actualizará en breve.",
"Actualización",
{
progressBar: true,
progressAnimation: "increasing",
positionClass: "toast-bottom-full-width",
timeOut: 6000,
}
);
setTimeout(() => {
window.location.reload();
}, 7000);
}
});
}
}
La Integración
Para hacer que esta solución sea lo más general posible y evitar la necesidad de integrar código en cada controlador que utilice el servicio, implementé un guardián canActivate
en las rutas que requieren esta validación. Los guardianes actúan como middlewares y se ejecutan cada vez que intentamos cambiar de vista dentro de la aplicación. Esto garantiza que la verificación del versionado sea parte integral de la navegación en la aplicación.
- Integrar a app-routing.module.ts: Agrega el guardian canActivate a las rutas pasandole el servicios
cache.service.ts
.
app-routing.module.ts
import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { CacheService } from "./services/cache.service";
const routes: Routes = [
{
path: "",
canActivate: [AuthGuardService],
component: InicioComponent,
},
{
path: "inicio-sesion",
canActivate: [AuthGuardLoginService, CacheService], //CacheService en canActive
component: InicioSesionComponent,
},
{
path: "**",
redirectTo: "",
},
];
@NgModule({
imports: [RouterModule.forRoot(routes, { useHash: true })],
exports: [RouterModule],
})
export class AppRoutingModule {}
Conclusión
El problema de la caché puede ser uno de los más tediosos en el desarrollo de aplicaciones web, y encontrar soluciones efectivas puede ser un desafío. Espero que esta solución que compartí hoy sea útil para la comunidad. No pretendo venderla comercialmente, simplemente quiero aportar una solución que funcionó para nosotros y que puede ayudar a otros a evitar problemas de caché y mantener sus aplicaciones actualizadas. ¡Hagamos que la experiencia del usuario sea siempre la mejor posible!
Si tienen alguna pregunta o comentarios, no duden en compartirlos. ¡Juntos podemos mejorar nuestras aplicaciones web y hacer que la web sea un lugar mejor para todos!