Entrega un producto como un único shell pulido, pero constrúyelo como muchas
aplicaciones pequeñas, cada una con su equipo dueño de extremo a extremo.
Frame es la arquitectura de micro-frontend que lo hace posible: una página
anfitriona compone aplicaciones web independientes en una sola experiencia, y un
SDK tipado mantiene ambos lados conversando — sin compartir jamás un bundle.
Publicado como @zomme/frame, es el shell de micro-frontends de
Buntime.
El problema que resuelve
Dividir un frontend en aplicaciones independientes suele significar renunciar al aislamiento o a la integración. Comparte un bundle y la actualización de un equipo rompe el build de otro; aísla todo en iframes y pierdes la comunicación tipada y bidireccional que exige un producto de verdad. Frame conserva ambas: cada aplicación sigue siendo un deploy separado tras un iframe, mientras un canal tipado permite que anfitriona e hija intercambien props, llamen métodos e intercambien eventos como si fueran una sola aplicación.
Cómo funciona
flowchart LR host["Host page · z-frame"] -->|"props · theme · apiUrl"| child["Embedded app · frame SDK"] child -->|"events · emit (postMessage)"| host
La anfitriona declara un elemento <z-frame> que apunta a una aplicación hija,
define props, llama métodos y escucha eventos. La hija importa el SDK, se
inicializa, lee sus props (incluidos callbacks) y emite o escucha de vuelta hacia
la anfitriona.
// Página anfitriona
const frame = document.querySelector("z-frame");
frame.apiUrl = "https://api.example.com";
frame.theme = "dark";
frame.onSuccess = user => console.log("creado", user);
frame.addEventListener("ready", () =>
frame.emit("theme-change", { theme: "dark" })
);
frame.addEventListener("user-created", e => console.log(e.detail));
// Aplicación hija
import { frameSDK } from "@zomme/frame/sdk";
await frameSDK.initialize();
frameSDK.props.onSuccess({ id: 1 });
frameSDK.on("theme-change", ({ theme }) => applyTheme(theme));
frameSDK.watch(["apiUrl", "theme"], changes => reconfigure(changes));
frameSDK.emit("user-created", { id: 1 });
<z-frame
name="admin"
src="https://apps.example.com/admin"
base="/admin"
></z-frame>
Lo que obtienes
- Elemento anfitrión —
<z-frame name src base>: define props (frame.apiUrl,frame.theme,frame.onSuccess), llama métodos (frame.emit('theme-change', {...}), con alias en camelCase comoframe.themeChange({...})) y escucha eventos (frame.addEventListener('ready', ...), además de personalizados como'user-created'). - SDK hijo —
@zomme/frame/sdk:await frameSDK.initialize(), lectura deframeSDK.props(incluidos callbacks),frameSDK.emit()/frameSDK.on()yframeSDK.watch([...], changes => {...})para reaccionar a cambios de props. - Inyección de base-path — las SPA embebidas siguen funcionando bajo un
sub-path, así que una hija servida en
/adminenruta correctamente sin reescrituras por aplicación.
Stack
Un monorepo Bun en TypeScript, con aplicaciones de ejemplo (incluyendo Vue) compiladas a bundles estáticos — prueba de que la anfitriona se mantiene agnóstica de framework mientras cada hija elige el suyo.
Disponibilidad
- Código: github.com/djalmajr/frame
- Relacionado: Buntime — usa Frame como shell
Open source bajo la licencia Apache 2.0.