¿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
setupSlots, 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.
Sigue leyendo
Una idea lleva a otra.
)
Guía práctica de Vue 3: Cómo usar <Teleport> para modales, tooltips y notificaciones adaptativas
)
defineModel() en Vue 3.4+: La evolución elegante del v-model en componentes
)
)