¿Y si Vue.js también hablara Web Components? La magia de defineCustomElement

Si eres fan de Vue.js como yo, seguramente has creado componentes reutilizables una y otra vez. Pero… ¿alguna vez te preguntaste cómo compartir tus componentes Vue fuera de una app Vue? ¿Qué pasaría si pudieras usarlos en React, Angular o incluso en HTML puro? La respuesta está en los Web Components y Vue tiene una herramienta poderosa para eso: defineCustomElement. Hoy te voy a contar cómo Vue y los Web Components pueden ser mejores amigos. Te prometo que al final vas a querer probarlo en tu próximo proyecto (o experimento).

¿Qué es un WC?

Un Web Component es básicamente un componente hecho con estándares del navegador. Vive felizmente en cualquier parte: no necesita que uses un framework específico. Son componentes nativos, encapsulados y portables.

Ejemplos reales:

  • YouTube usa Web Components para renderizar botones, menús y otros elementos interactivos de su UI.

  • Google utiliza Web Components internamente en muchos de sus productos, incluyendo partes de Gmail y Google Maps, gracias a su librería Lit.

  • Salesforce, IKEA, y Adobe también han adoptado este enfoque para crear design systems compartidos entre múltiples equipos y stacks tecnológicos distintos.

Vue + Web Components: defineCustomElement al rescate

Vue ofrece una función muy poderosa llamada defineCustomElement, que te permite registrar tu componente como un elemento personalizado del navegador. Así, puedes usarlo como <mi-componente></mi-componente> en cualquier HTML.

Veamos un ejemplo básico:

// MyComponent.ce.ts
import { defineCustomElement } from 'vue'
import MyComponent from './MyComponent.vue'

const MyCustomElement = defineCustomElement(MyComponent)

customElements.define('mi-componente', MyCustomElement)

Ahora puedes usar <mi-componente></mi-componente> en cualquier parte, sin importar si estás en una app Vue o no.

¿Y si tu app tiene mil tecnologías distintas?

En empresas grandes o proyectos legacy, es común ver entornos con:

  • Páginas construidas en PHP o Django

  • Apps hechas con React, Angular y Vue

  • Widgets aislados en jQuery

  • Y muchas veces... todo junto al mismo tiempo

Aquí es donde los Web Components brillan: puedes crear un componente de Vue 3, empacarlo con defineCustomElement, y luego usarlo como si fuera HTML en cualquier página, sin importar la tecnología que tenga debajo.

¿Quieres un dropdown con lógica avanzada en una app legacy que no puedes migrar aún? Créalo con Vue, expórtalo como Web Component, y reutilízalo en toda tu plataforma.

¿Qué se mantiene y qué cambia?

Lo que sigue funcionando:

  • Reactividad de Vue

  • Ciclo de vida completo (onMounted, onUpdated, etc.)

  • Composición con setup

  • Slots, props, y eventos personalizados

Opciones adicionales con defineCustomElement:

Vue ahora permite configurar detalles específicos al momento de crear tu Web Component:

defineCustomElement(MyComponent, {
  shadowRoot: false, // ❌ No encapsula con Shadow DOM
  styles: [/* CSS inyectado */],
  configureApp(app) {
    // configuración personalizada del app Vue
  },
})

¿Shadow DOM o no?

Por defecto, Vue encapsula tu componente usando Shadow DOM, lo que protege tus estilos de interferencias externas. Pero si necesitas mayor integración con estilos globales (por ejemplo, para heredar estilos de un CMS o diseño corporativo), puedes desactivarlo:

const MyCustomElement = defineCustomElement(MyComponent, {
  shadowRoot: false
})

Ten en cuenta que al desactivarlo, los estilos en tu SFC (<style>) ya no estarán aislados.

Casos de uso reales

  • Crear un design system agnóstico de framework, que puedas usar en cualquier producto de tu empresa.

  • Inyectar componentes Vue en un CMS que solo permite HTML o JS (como WordPress).

  • Agregar funcionalidades modernas en apps legacy sin necesidad de migrar todo.

  • Empaquetar tus widgets como componentes distribuidos para terceros, sin obligarles a usar Vue.

Conclusión: Vue nunca fue tan portable

Con defineCustomElement, Vue se vuelve aún más versátil. Ya no es solo para tus SPA, también puede ser parte de páginas estáticas, CMS, otras apps... y sin pedir permiso.

Vue ahora habla Web Components, y eso lo convierte en una herramienta ideal para equipos modernos, proyectos híbridos y soluciones verdaderamente escalables.