Sebastian Gomez
Profundizando en un stack tecnológico para aplicaciones en Tiempo Real como Uber
Las aplicaciones estilo "Uber Like" (como Uber) o "Rappi Like" han ganado muchísima popularidad en los últimos años. Varias soluciones tecnológicas intentan emular el comportamiento y la funcionalidad de este tipo de aplicaciones. Esto ocurre porque muchas compañías incursionan en el mundo del delivery y los ecommerce, buscando replicar casos de éxito ya establecidos.
Es sorprendente ver al conductor de Uber en tiempo real acercándose a nuestra ubicación y poder estar preparados casi con exactitud para subirnos al vehículo. Del mismo modo, nos gusta saber cuándo el repartidor ha recogido nuestro pedido y visualizar su ubicación en cada momento.
En este artículo exploraremos cómo funcionan las aplicaciones que rastrean objetos en tiempo real y aprenderemos a visualizarlos utilizando Google Maps, Angular y Firebase. A diferencia de la versión original de este post, aquí ya no te mando a un enlace externo: vamos a construir un ejemplo mínimo y funcional, paso a paso. Vamos a empezar!
La idea detrás del tiempo real
El truco de estas aplicaciones es más simple de lo que parece. Hay dos piezas que conversan entre sí:
- Un backend en tiempo real que guarda la posición de cada objeto (un conductor, un repartidor, tu pedido) y avisa a quien esté escuchando cada vez que esa posición cambia. Aquí entra Firebase: tanto Firestore como la Realtime Database ofrecen listeners que se disparan automáticamente cuando el dato cambia, sin que tengas que preguntar una y otra vez.
- Un mapa que dibuja esa posición y la mueve suavemente en pantalla. Aquí entra Google Maps, integrado en Angular mediante el paquete oficial `@angular/google-maps`.
El conductor (u otro proceso) escribe su coordenada en Firebase cada pocos segundos, y tu aplicación, que está suscrita a ese documento, recibe el nuevo valor y reubica el marcador en el mapa. Eso es, en esencia, el "tiempo real" que ves en Uber o Rappi.
Preparando el proyecto en Angular
Vamos a trabajar con Angular moderno: componentes standalone (sin NgModule) y signals para el estado reactivo, que es el enfoque idiomático hoy. Crea el proyecto e instala las dependencias:
ng new uber-like-tracker
cd uber-like-tracker
# Integración oficial de Google Maps para Angular
npm install @angular/google-maps
# SDK de Firebase (modular, v9+)
npm install firebaseNota: El paquete @angular/google-maps reemplaza a las viejas librerías de terceros como @agm/core (AngularJS Google Maps), que está descontinuado. Para Firebase, el SDK modular firebase ya no requiere @angular/fire para casos sencillos; lo usaremos directamente.
Carga el script de la API de Google Maps en tu index.html (necesitas una API key desde la consola de Google Cloud con la Maps JavaScript API habilitada):
<!-- index.html -->
<script
src="https://maps.googleapis.com/maps/api/js?key=TU_API_KEY&loading=async"
async
></script>Configurando Firebase y el listener en tiempo real
Inicializa Firebase con la configuración de tu proyecto y crea un servicio que escuche la posición del objeto. Usamos onSnapshot, que es la pieza clave: cada vez que el documento cambia en Firestore, nuestro callback se ejecuta con el dato fresco.
// firebase.config.ts
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: 'TU_API_KEY',
authDomain: 'tu-proyecto.firebaseapp.com',
projectId: 'tu-proyecto',
// ...resto de tu configuración
};
export const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);// driver-location.service.ts
import { Injectable, signal } from '@angular/core';
import { doc, onSnapshot } from 'firebase/firestore';
import { db } from './firebase.config';
export interface LatLng {
lat: number;
lng: number;
}
@Injectable({ providedIn: 'root' })
export class DriverLocationService {
// Un signal con la posición actual; el mapa reacciona a sus cambios.
readonly position = signal<LatLng>({ lat: 4.711, lng: -74.0721 });
// Nos suscribimos a un documento de Firestore: cada actualización
// dispara onSnapshot y movemos el marcador.
trackDriver(driverId: string): void {
const ref = doc(db, 'drivers', driverId);
onSnapshot(ref, (snapshot) => {
const data = snapshot.data();
if (data?.['lat'] != null && data?.['lng'] != null) {
this.position.set({ lat: data['lat'], lng: data['lng'] });
}
});
}
}Fíjate en el detalle importante: no hacemos polling (preguntar cada X segundos "cambió?"). onSnapshot mantiene un canal abierto y nos empuja el nuevo valor en cuanto el conductor actualiza su coordenada. Eso es lo que hace que la experiencia se sienta instantánea.
Mostrando la posición en el mapa
Ahora el componente standalone que une todo: importa GoogleMap y MapAdvancedMarker desde @angular/google-maps, lee el signal de posición y centra el mapa en el objeto.
// app.component.ts
import { Component, computed, inject, OnInit } from '@angular/core';
import { GoogleMap, MapAdvancedMarker } from '@angular/google-maps';
import { DriverLocationService } from './driver-location.service';
@Component({
selector: 'app-root',
standalone: true,
imports: [GoogleMap, MapAdvancedMarker],
template: `
<google-map
height="100vh"
width="100%"
[center]="center()"
[zoom]="15"
>
<map-advanced-marker [position]="center()" title="Conductor" />
</google-map>
`,
})
export class AppComponent implements OnInit {
private readonly locationService = inject(DriverLocationService);
// computed deriva el centro del mapa directamente del signal de posición.
readonly center = computed(() => this.locationService.position());
ngOnInit(): void {
this.locationService.trackDriver('driver-123');
}
}Nota: en las versiones recientes de @angular/google-maps, MapAdvancedMarker (selector map-advanced-marker, basado en AdvancedMarkerElement de Google) reemplaza al antiguo MapMarker/google.maps.Marker, que Google marcó como legacy. El marcador avanzado requiere un Map ID configurado en tu proyecto de Google Cloud (atributo mapId en el GoogleMap padre).
Con esto, cada vez que el documento drivers/driver-123 cambie en Firestore, el signal se actualiza, center se recomputa y el marcador se reubica solo. No escribiste ni una línea de código para "refrescar" el mapa.
Conclusiones
- Las aplicaciones "Uber Like" y "Rappi Like" han revolucionado el mundo del delivery y los ecommerce ofreciendo seguimiento en tiempo real a los usuarios.
- Visualizar la ubicación y el movimiento de conductores y repartidores en tiempo real es posible gracias a tecnologías como Google Maps, Angular y Firebase, y la pieza central es un listener (
onSnapshot) que empuja los cambios en lugar de hacer polling. - Profundizar en este stack tecnológico, hoy con Angular standalone, signals y los SDK modulares, puede permitirnos crear aplicaciones similares o incluso mejorar las existentes.
Ejercicios propuestos
- Crea una aplicación básica con Angular y
@angular/google-mapsque muestre la ubicación de un objeto en el mapa a partir de un signal. - Conecta Firestore con
onSnapshotpara que la ubicación del objeto se actualice en tiempo real, y escribe un pequeño script que actualice el documento cada pocos segundos para simular el movimiento. - Diseña una interfaz que permita a los usuarios interactuar con la aplicación: solicitar un vehículo, ordenar un producto o incluso chatear con el conductor o repartidor.
Resumen en 3 puntos
- Las aplicaciones "Uber Like" y "Rappi Like" son populares y han cambiado la forma en que los usuarios interactúan con los servicios de delivery y ecommerce.
- Para crear aplicaciones de seguimiento en tiempo real podemos combinar Google Maps, Angular y Firebase, apoyándonos en los listeners de Firestore para recibir cada cambio de posición al instante.
- Profundizar en este stack tecnológico, con Angular moderno y los SDK actuales, nos permite desarrollar aplicaciones similares o mejorar las ya existentes.
Eso es todo, espero que este post te sea de utilidad y lo puedas aplicar a algún proyecto que tengas en mente. Si tienes alguna duda, no dudes en dejarme un comentario en la parte de abajo. Recuerda que si te gustó, también puedes compartirlo usando los enlaces a las redes sociales aquí abajo. Buena suerte!
Sebastian Gomez
Creador de contenido principalmente acerca de tecnología.