Actualiza sin recargar,
siente la fluidez
Librería JavaScript ligera para actualizar contenido HTML sin recargar la página. Navegación fluida con precarga inteligente y zero-config.
Características principales
Todo lo que necesitas para crear experiencias de navegación modernas y fluidas
Actualización parcial del DOM
Reemplaza solo los elementos que necesitas usando identificadores únicos (handles). Sin recargas innecesarias.
Tres formas de uso
API JavaScript, links automáticos con data-swappit-handle, o componente <swappit-instance>. Elige tu favorito.
Precarga inteligente
Configura precarga instantánea o al hacer hover. A nivel global o por link individual.
Navegación con historial
Soporte completo para botones adelante/atrás del navegador. URLs actualizadas automáticamente.
Sistema de caché
Controla cuándo usar caché o forzar nuevas descargas. Rendimiento optimizado desde el primer click.
Detección automática
Observador de DOM que configura nuevos links dinámicamente. Perfecto para contenido cargado después.
Sistema de eventos
Escucha eventos antes/después de actualizar y al reiniciar. Control total sobre el ciclo de vida.
Logging colorido
Sistema de debugging con 4 niveles (info, success, warning, error). Desarrollo más fácil.
Zero-config
Funciona con configuración mínima, personalizable según necesites. Empieza en segundos.
Instalación
Elige el método que prefieras para integrar Swappit en tu proyecto
NPM
npm install @soyleninjs/swappit
// ES modules
import Swappit from '@soyleninjs/swappit';
// O desde CDN
import Swappit from "https://esm.sh/@soyleninjs/swappit";
// CommonJS
const Swappit = require('@soyleninjs/swappit');
CDN
<script src="https://cdn.jsdelivr.net/npm/@soyleninjs/swappit/swappit.min.js"></script>
Descarga directa
Descarga swappit.min.js desde GitHub Releases
<script src="ruta/a/tu/proyecto/swappit.min.js"></script>
Ejemplos de uso
Descubre las tres formas de trabajar con Swappit
1. Usando el componente <swappit-instance>
Recomendado para configuración declarativa. Define todo con atributos HTML.
<!-- Elementos que se actualizarán -->
<div data-mi-handle-update="header">Contenido original del header</div>
<div data-mi-handle-update="main">Contenido original del main</div>
<!-- Crear instancia con configuración declarativa -->
<swappit-instance
data-handle="mi-handle"
data-log
data-update-url
data-enable-history
data-preload="hover">
</swappit-instance>
<!-- Links que usarán esta instancia -->
<a href="./pagina1.html" data-swappit-handle="mi-handle">Página 1</a>
<a href="./pagina2.html" data-swappit-handle="mi-handle">Página 2</a>
2. Usando links con data-swappit-handle
Los links se configuran automáticamente. Solo agrega el atributo data.
<!-- Elementos que se actualizarán -->
<div data-mi-handle-update="header">Contenido original</div>
<div data-mi-handle-update="main">Contenido original</div>
<!-- Links con configuración individual -->
<a href="./pagina1.html" data-swappit-handle="mi-handle">
Página 1
</a>
<a href="./pagina2.html" data-swappit-handle="mi-handle" data-preload="hover">
Página 2 (Precarga al pasar el mouse)
</a>
<a href="./pagina3.html" data-swappit-handle="mi-handle" data-preload="instant">
Página 3 (Precarga instantánea)
</a>
<script>
// Crear instancia
const swappit = new Swappit('mi-handle', true);
// Los links se configuran automáticamente
</script>
3. Usando la API de JavaScript directamente
Control completo programático para casos avanzados.
const swappit = new Swappit('mi-handle', true);
// Actualizar contenido (usa caché por defecto)
swappit.update('./contenido-demo.html');
// Forzar nueva descarga
swappit.update('./contenido-demo.html', false);
// Precargar múltiples URLs
swappit.preloadContents([
'./header.html',
'./main.html',
'./footer.html'
]);
// Escuchar eventos
window.addEventListener('swappit:mi-handle:afterUpdate', (e) => {
console.log('Contenido actualizado:', e.detail);
});
Flujo Completo de Funcionamiento
Entiende cómo funciona Swappit de principio a fin con un ejemplo práctico
Página Principal (index.html)
Configura tu página principal con los elementos que se actualizarán
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Mi Aplicación con Swappit</title>
</head>
<body>
<!-- Elementos que se actualizarán -->
<header data-mi-app-update="header">
<h1>Bienvenido a Mi App</h1>
<nav>
<!-- Links con data-swappit-handle -->
<a href="./about.html" data-swappit-handle="mi-app">Acerca de</a>
<a href="./contact.html" data-swappit-handle="mi-app">Contacto</a>
</nav>
</header>
<main data-mi-app-update="content">
<h2>Página de Inicio</h2>
<p>Este es el contenido principal de la página de inicio.</p>
</main>
<footer data-mi-app-update="footer">
<p>© 2025 Mi Aplicación</p>
</footer>
<!-- Cargar Swappit -->
<script src="https://cdn.jsdelivr.net/npm/@soyleninjs/swappit/swappit.min.js"></script>
<!-- Inicializar Swappit -->
<script>
const app = new Swappit('mi-app', true, {
updateUrl: true,
enableHistory: true,
preload: 'hover'
});
// Opcional: Escuchar eventos
window.addEventListener('swappit:mi-app:afterUpdate', (e) => {
console.log('Contenido actualizado desde:', e.detail.url);
});
</script>
</body>
</html>
Página de Destino (about.html)
Crea las páginas de destino con los MISMOS atributos data
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Acerca de - Mi Aplicación</title>
</head>
<body>
<!-- Mismo handle y nombres de atributos -->
<header data-mi-app-update="header">
<h1>Acerca de Nosotros</h1>
<nav>
<a href="./index.html" data-swappit-handle="mi-app">Inicio</a>
<a href="./about.html" data-swappit-handle="mi-app">Acerca de</a>
<a href="./contact.html" data-swappit-handle="mi-app">Contacto</a>
</nav>
</header>
<main data-mi-app-update="content">
<h2>Sobre Nuestra Empresa</h2>
<p>Somos una empresa dedicada a crear soluciones innovadoras.</p>
<p>Nuestro equipo trabaja con las mejores tecnologías.</p>
</main>
<footer data-mi-app-update="footer">
<p>© 2025 Mi Aplicación - Todos los derechos reservados</p>
</footer>
<!-- Swappit se carga automáticamente desde la página principal -->
<script src="https://cdn.jsdelivr.net/npm/@soyleninjs/swappit/swappit.min.js"></script>
<script>
const app = new Swappit('mi-app', true, {
updateUrl: true,
enableHistory: true,
preload: 'hover'
});
</script>
</body>
</html>
¿Qué Sucede al Hacer Click?
Flujo de ejecución cuando el usuario navega
1. Usuario hace click en el link
Swappit detecta el click en <a data-swappit-handle="mi-app"> y previene la recarga de la página
2. Se emite el evento beforeUpdate
window.dispatchEvent('swappit:mi-app:beforeUpdate')
3. Fetch del contenido
Swappit hace fetch('./about.html') y parsea el HTML con DOMParser
4. Actualización del DOM
Busca elementos con data-mi-app-update="header", data-mi-app-update="content", etc., y reemplaza su contenido
5. Actualización de URL
Si updateUrl: true, la URL del navegador cambia a /about.html
6. Se emite el evento afterUpdate
window.dispatchEvent('swappit:mi-app:afterUpdate') - Aquí puedes ejecutar scripts o animaciones
📌 Puntos Clave
-
Mismos atributos: Las páginas de destino deben tener los mismos
data-[handle]-updateque la página principal - Solo coincidencias: Solo se actualizan elementos que existen en ambas páginas
- Sin recarga: La página no se recarga, solo se actualiza el contenido específico
- Caché automático: El contenido se almacena en caché para navegación más rápida
-
Historial del navegador: Los botones adelante/atrás funcionan si
enableHistory: true
Configuración
Opciones, atributos y métodos disponibles para personalizar Swappit
Constructor
new Swappit(handle, log = false, options = {})
Opciones disponibles (options)
Atributos data para elementos
Métodos de instancia
Sistema de Eventos
Swappit emite eventos personalizados que puedes escuchar para ejecutar código en momentos específicos
Eventos disponibles
Ejemplo de uso
// Escuchar evento antes de actualizar
window.addEventListener('swappit:mi-handle:beforeUpdate', (e) => {
console.log('Comenzando actualización', e.detail);
// e.detail = { handle: 'mi-handle', url: './pagina.html' }
});
// Escuchar evento después de actualizar
window.addEventListener('swappit:mi-handle:afterUpdate', (e) => {
console.log('Contenido actualizado', e.detail);
// Aquí puedes reinicializar scripts, ejecutar animaciones, etc.
});
// Escuchar evento de reinicio
window.addEventListener('swappit:mi-handle:reinit', (e) => {
console.log('Instancia reiniciada', e.detail);
});
Manejo de Scripts
Controla cómo y cuándo se ejecutan los scripts en el contenido actualizado
Importante
Los scripts dentro de los elementos actualizados NO se ejecutan automáticamente. Esto es intencional para darte control total sobre la ejecución de scripts.
Métodos estáticos disponibles
Ejecutar scripts inline
window.addEventListener('swappit:mi-app:afterUpdate', () => {
// Seleccionar scripts inline dentro de elementos actualizados
const scripts = document.querySelectorAll('[data-mi-app-update] script:not([src])');
// Ejecutarlos
Swappit.updateScriptByContent(Array.from(scripts));
});
Recargar scripts externos
window.addEventListener('swappit:mi-app:afterUpdate', () => {
// Recargar scripts que contengan "analytics" en su URL
// Se agregará un timestamp para forzar la recarga
Swappit.updateScriptBySrc('analytics.js');
// También puedes recargar múltiples scripts
Swappit.updateScriptBySrc('mi-libreria');
});
Solución de Problemas
Problemas comunes y sus soluciones
❌ No se actualiza el contenido
Causa: Atributos data incorrectos o handle distinto
Solución: Verifica que los atributos data-[handle]-update coincidan entre la página principal y las páginas de destino
❌ Error de URL inválida
Causa: URL externa o absoluta
Solución: Solo se permiten rutas relativas internas que empiecen con / o ./
❌ Links no funcionan automáticamente
Causa: Falta atributo data-swappit-handle
Solución: Agrega data-swappit-handle="tu-handle" a los links
❌ Handle ya está en uso
Causa: Intentas crear dos instancias con el mismo handle
Solución: Usa Swappit.instances.get('tu-handle') para reutilizar una instancia existente
❌ Los scripts no se ejecutan
Causa: Scripts deshabilitados por defecto
Solución: Usa Swappit.updateScriptByContent() o Swappit.updateScriptBySrc() en el evento afterUpdate
❌ Botones adelante/atrás no funcionan
Causa: Falta configuración de historial
Solución: Activa updateUrl: true y enableHistory: true en las opciones
❌ El caché no se actualiza
Causa: loadFromCache está en true
Solución: Usa update(url, false) para forzar nueva descarga, o llama a reinit() para limpiar la caché
¿No encuentras la solución a tu problema?
Reportar un problema en GitHub