[{"data":1,"prerenderedAt":930},["ShallowReactive",2],{"post-index":3,"post-vue-vapor-adopcion-interop-bundle":170},[4,15,25,33,41,49,63,75,87,99,109,121,131,141,150,160],{"slug":5,"title":6,"description":7,"excerpt":8,"category":9,"level":10,"publishedAt":11,"updatedAt":11,"readingTime":12,"image":13,"tags":14},"vue-vapor-adopcion-interop-bundle","Adoptar Vapor en una app Vue real: interop, componentes y bundle","Cómo migrar una app Vue a Vapor sin reescribirla: activar la interop, migrar componentes hoja, medir y entender el peso del bundle.","Migra una app Vue a Vapor sin reescribirla: activa la interop, migra componentes hoja, mide y entiende el peso del bundle.","performance","intermediate","2026-11-14T14:38:14.852Z",6,"",[10,9],{"slug":16,"title":17,"description":18,"excerpt":19,"category":20,"level":21,"publishedAt":22,"updatedAt":22,"readingTime":23,"image":13,"tags":24},"vue-3-6-reactividad-alien-signals","Reactividad de Vue 3.6: qué cambió con alien-signals y cómo medirlo","Qué cambió en el sistema de reactividad de Vue 3.6 con alien-signals, cuánto mejora medido en tu máquina y cómo comprobarlo en tu app.","Qué cambió en la reactividad de Vue 3.6 con alien-signals, cuánto mejora medido en tu máquina y cómo comprobarlo.","reactivity","advanced","2026-11-14T14:29:47.062Z",5,[21,9],{"slug":26,"title":27,"description":28,"excerpt":29,"category":9,"level":21,"publishedAt":30,"updatedAt":31,"readingTime":12,"image":13,"tags":32},"vue-vapor-compilador-v-if-v-for-v-model-slots","Dentro del compilador de Vapor: v-if, v-for, v-model y slots en Vue 3.6","Qué código genera Vapor para v-if, v-for, v-model y slots frente al Virtual DOM, leído con el compilador de Vue 3.6.","Compara el código que genera Vapor y Virtual DOM para v-if, v-for, v-model y slots, con el compilador de Vue 3.6.","2026-11-14T14:11:32.855Z","2026-11-14T14:18:07.483Z",[21,9],{"slug":34,"title":35,"description":36,"excerpt":37,"category":9,"level":21,"publishedAt":38,"updatedAt":38,"readingTime":39,"image":13,"tags":40},"vue-vapor-benchmark-metodologia","Medir sin engañarse: benchmark de Virtual DOM frente a Vapor en Vue 3.6","Cómo medir Virtual DOM frente a Vapor en Vue 3.6 sin engañarse: apps aisladas, calentamiento, orden alternado, mediana y medición en producción.","Mide Virtual DOM frente a Vapor sin engañarse: apps aisladas, calentamiento, orden alternado, mediana y pruebas en producción.","2026-11-14T14:07:52.145Z",7,[21,9],{"slug":42,"title":43,"description":44,"excerpt":45,"category":9,"level":10,"publishedAt":46,"updatedAt":46,"readingTime":47,"image":13,"tags":48},"vue-vapor-mode-sin-virtual-dom","Vapor Mode en Vue 3.6: Vue sin Virtual DOM, explicado y medido","Qué es Vapor Mode en Vue 3.6, cómo activarlo, qué código genera el compilador y cuánto mejora frente al Virtual DOM, con mediciones reales.","Activa Vapor Mode en Vue 3.6 con una sola palabra, mira qué compila y mide cuánto mejora frente al Virtual DOM, con cifras reales.","2026-11-14T14:01:56.481Z",9,[10,9],{"slug":50,"title":51,"description":52,"excerpt":53,"rank":54,"category":20,"level":10,"publishedAt":55,"updatedAt":56,"readingTime":39,"image":57,"tags":58},"watch-vs-watcheffect-cotizador-envios-vue-3","watch vs. watchEffect en Vue 3: evita cotizaciones de envío desactualizadas","Construye un cotizador de envíos con Vue 3.5+: usa watch, debounce y onWatcherCleanup para evitar tarifas obsoletas en un checkout real.","Evita respuestas HTTP desactualizadas con watch, debounce y cancelación en un cotizador de envíos.",1,"2026-09-27T18:12:58.826Z","2026-10-05T04:27:15.492Z","https://a-us.storyblok.com/f/1022875/1672x941/2033377396/watch-vs-watcheffect-cotizador-envios-vue-3.png",[59,60,10,61,62],"backend","composition-api","watch","watch-effect",{"slug":64,"title":65,"description":66,"excerpt":66,"rank":12,"category":67,"level":10,"publishedAt":68,"updatedAt":69,"readingTime":70,"image":71,"tags":72},"how-to-use-teleport-in-vue-3","Teleport en Vue 3: notificaciones con limpieza y claves estables","Mueve notificaciones al body con Teleport, claves estables y limpieza de temporizadores.","components","2025-07-26T01:49:43.552Z","2026-10-05T04:02:39.181Z",3,"https://a-us.storyblok.com/f/1022875/1376x768/9bbb639e1d/teleport.jpg",[67,10,73,74],"teleport","ui-patterns",{"slug":76,"title":77,"description":78,"excerpt":78,"rank":39,"category":67,"level":79,"publishedAt":80,"updatedAt":81,"readingTime":82,"image":83,"tags":84},"use-definemodel","defineModel() en Vue 3.4+: La evolución elegante del v-model en componentes","Crea un input reutilizable con defineModel y aplica un modificador personalizado sin duplicar el modelo.","beginner","2025-07-21T03:03:33.292Z","2026-10-05T03:55:33.832Z",2,"https://a-us.storyblok.com/f/1022875/1536x1024/7c8b51e1ae/definemodel2.png",[67,85,10,86],"define-model","v-model",{"slug":88,"title":89,"description":90,"excerpt":90,"rank":91,"category":92,"level":10,"publishedAt":93,"updatedAt":94,"readingTime":82,"image":95,"tags":96},"vue-fire","Autenticación con Google en Vue 3 y VueFire","Conecta Firebase Auth con VueFire y añade acceso con Google, cierre de sesión y errores visibles.",10,"integrations","2025-06-10T03:22:00.345Z","2026-10-05T04:03:20.036Z","https://a-us.storyblok.com/f/1022875/1376x768/9774bccf90/vuefire.jpg",[59,97,10,98],"firebase","vuefire",{"slug":100,"title":101,"description":102,"excerpt":102,"rank":47,"category":92,"level":21,"publishedAt":103,"updatedAt":104,"readingTime":70,"image":105,"tags":106},"web-components-with-modern-vue","Web Components con Vue 3: distribuye un contador con defineCustomElement","Publica un contador Vue como Custom Element con estilos encapsulados y eventos para HTML.","2025-04-15T02:46:47.631Z","2026-10-05T04:02:55.512Z","https://a-us.storyblok.com/f/1022875/1536x1024/7b5cd5a452/web-components.png",[21,67,107,108],"define-custom-element","interoperability",{"slug":110,"title":111,"description":112,"excerpt":112,"rank":113,"category":92,"level":10,"publishedAt":114,"updatedAt":115,"readingTime":82,"image":116,"tags":117},"tailwind-4-integration-with-vue-cli","Tailwind CSS 4 con Vue CLI: guía para proyectos existentes","Mantén un proyecto existente con Vue CLI y compila Tailwind 4 sin desactivar la optimización de producción.",11,"2025-03-16T16:48:02.739Z","2026-10-05T04:03:28.685Z","https://a-us.storyblok.com/f/1022875/1792x1024/71cb200538/vue-cli-and-tailwind-4.webp",[10,118,119,120],"styling","tailwind","vue-cli",{"slug":122,"title":123,"description":124,"excerpt":124,"rank":125,"category":67,"level":79,"publishedAt":126,"updatedAt":127,"readingTime":82,"image":128,"tags":129},"how-to-use-defineexpose","¿Cómo usar defineExpose?","Expón una API pequeña desde un modal y contrólala desde el padre con una referencia tipada.",4,"2025-02-26T02:23:58.312Z","2026-10-05T04:06:26.788Z","https://a-us.storyblok.com/f/1022875/1376x768/487e84614f/defineexpose.jpg",[79,67,60,130],"define-expose",{"slug":132,"title":133,"description":134,"excerpt":134,"rank":23,"category":9,"level":21,"publishedAt":135,"updatedAt":136,"readingTime":23,"image":137,"tags":138},"how-to-use-v-memo","Cómo usar v-memo en Vue 3: dependencias y medición de rendimiento","Optimiza una lista con v-memo, elige dependencias completas y compara el resultado antes de adoptarlo.","2025-02-08T18:55:25.441Z","2026-10-05T04:06:52.708Z","https://a-us.storyblok.com/f/1022875/1376x768/b989b9ebdf/v-memo-image.jpg",[139,10,9,140],"directives","v-memo",{"slug":142,"title":143,"description":144,"excerpt":144,"rank":70,"category":20,"level":10,"publishedAt":145,"updatedAt":146,"readingTime":70,"image":147,"tags":148},"what-is-a-composable","¿Qué es un Composable?","Extrae consultas HTTP a un composable tipado que cancela peticiones anteriores y maneja errores.","2025-02-05T03:00:11.569Z","2026-10-05T04:00:35.499Z","https://a-us.storyblok.com/f/1022875/1376x768/0c48bd03b4/vue-composables.jpg",[79,149,60],"composables",{"slug":151,"title":152,"description":153,"excerpt":153,"rank":82,"category":9,"level":10,"publishedAt":154,"updatedAt":155,"readingTime":70,"image":156,"tags":157},"use-defineasynccomponent","defineAsyncComponent en Vue 3: Implementación y casos de uso.","Carga componentes bajo demanda y muestra estados de carga y error con defineAsyncComponent.","2025-01-15T03:44:46.169Z","2026-10-05T04:01:11.606Z","https://a-us.storyblok.com/f/1022875/1376x768/ff546597c5/vue_defineasync_img.jpg",[67,158,10,159,9],"define-async-component","lazy-loading",{"slug":161,"title":162,"description":163,"excerpt":163,"rank":164,"category":92,"level":79,"publishedAt":165,"updatedAt":166,"readingTime":82,"image":167,"tags":168},"tailwind-4-integration-in-vue-js-3","¿Cómo integrar Tailwind 4 en Vue.js 3 + Vite?","Configura Tailwind CSS 4 en Vue 3 con los plugins de Vue y Tailwind para Vite.",8,"2025-01-12T02:34:06.176Z","2026-10-05T04:02:46.836Z","https://a-us.storyblok.com/f/1022875/1376x768/626e80a702/taiwlind4_vue_3.jpg",[10,118,119,169],"vite",{"name":6,"created_at":171,"published_at":11,"updated_at":172,"id":173,"uuid":174,"content":175,"slug":5,"full_slug":922,"sort_by_date":179,"position":923,"tag_list":924,"is_startpage":925,"parent_id":926,"meta_data":179,"group_id":927,"first_published_at":11,"release_id":179,"lang":928,"path":179,"alternates":929,"default_full_slug":179,"translated_slugs":179},"2026-11-14T14:15:35.475Z","2026-11-14T14:38:14.869Z",241566250931277,"2d527e82-3c24-4baf-9240-bbede1275ce1",{"_uid":176,"demo":177,"image":178,"level":10,"title":6,"video":182,"content":184,"excerpt":8,"category":9,"component":921,"description":7,"youtube_url":13,"editorial_rank":13},"f3d6cbc7-c0a0-4f3d-9c9c-add5f68927d1",[],{"id":179,"alt":179,"name":13,"focus":179,"title":179,"source":179,"filename":13,"copyright":179,"fieldtype":180,"meta_data":181},null,"asset",{},{"id":179,"alt":179,"name":13,"focus":179,"title":179,"source":179,"filename":13,"copyright":179,"fieldtype":180,"meta_data":183},{},{"type":185,"attrs":186,"content":187},"doc",{"backgroundColor":179},[188,195,201,219,225,248,253,258,263,345,350,355,371,376,381,392,397,402,407,429,439,444,459,464,469,474,479,484,494,617,622,659,664,681,686,754,759,764,812,817,868,873,908],{"type":189,"attrs":190,"content":191},"heading",{"level":82,"textAlign":179},[192],{"text":193,"type":194},"Objetivo y requisitos","text",{"type":196,"attrs":197,"content":198},"paragraph",{"textAlign":179},[199],{"text":200,"type":194},"Hasta aquí vimos qué es Vapor Mode, cómo se mide y qué código genera el compilador. La pregunta que sigue en un proyecto real es otra: ¿cómo lo adopto sin reescribir la aplicación, qué parte migro primero y cuánto peso agrego en el proceso?",{"type":196,"attrs":202,"content":203},{"textAlign":179},[204,206,211,213,217],{"text":205,"type":194},"Necesitas una aplicación Vue 3 con Vite y Vue Router, y la versión candidata ",{"text":207,"type":194,"marks":208},"3.6.0-rc.15",[209],{"type":210},"code",{"text":212,"type":194}," (la última RC al momento de escribir esto). Para el peso medido en este artículo usé ",{"text":214,"type":194,"marks":215},"3.6.0-rc.14",[216],{"type":210},{"text":218,"type":194},", indicado en la tabla correspondiente.",{"type":220,"attrs":221,"content":222},"code_block",{"class":179},[223],{"text":224,"type":194},"npm install vue@3.6.0-rc.15\n",{"type":196,"attrs":226,"content":227},{"textAlign":179},[228,230,234,236,240,242,246],{"text":229,"type":194},"Como vimos en el primer post, Vue Router 5 declara peer ",{"text":231,"type":194,"marks":232},"vue ^3.5.34",[233],{"type":210},{"text":235,"type":194},", y npm no acepta una RC dentro de ese rango. Si tu proyecto lo usa, añade un ",{"text":237,"type":194,"marks":238},"overrides",[239],{"type":210},{"text":241,"type":194}," en ",{"text":243,"type":194,"marks":244},"package.json",[245],{"type":210},{"text":247,"type":194},":",{"type":220,"attrs":249,"content":250},{"class":179},[251],{"text":252,"type":194},"{\n  \"overrides\": {\n    \"vue\": \"$vue\",\n    \"@vue/compiler-sfc\": \"$vue\"\n  }\n}\n",{"type":189,"attrs":254,"content":255},{"level":82,"textAlign":179},[256],{"text":257,"type":194},"Primero, decide qué no migrar",{"type":196,"attrs":259,"content":260},{"textAlign":179},[261],{"text":262,"type":194},"Vapor no soporta todo lo que hace Vue. Antes de tocar un componente, revisa si usa alguna de estas piezas. Si la usa, ese componente se queda en Virtual DOM por ahora:",{"type":264,"content":265},"bullet_list",[266,285,308,323,334],{"type":267,"content":268},"list_item",[269],{"type":196,"attrs":270,"content":271},{"textAlign":179},[272,277,279,283],{"text":273,"type":194,"marks":274},"Options API.",[275],{"type":276},"bold",{"text":278,"type":194}," Solo ",{"text":280,"type":194,"marks":281},"\u003Cscript setup>",[282],{"type":210},{"text":284,"type":194}," o un SFC con solo template.",{"type":267,"content":286},[287],{"type":196,"attrs":288,"content":289},{"textAlign":179},[290,294,296,300,302,306],{"text":291,"type":194,"marks":292},"getCurrentInstance()",[293],{"type":210},{"text":295,"type":194}," devuelve ",{"text":297,"type":194,"marks":298},"null",[299],{"type":210},{"text":301,"type":194},", y no existe ",{"text":303,"type":194,"marks":304},"app.config.globalProperties",[305],{"type":210},{"text":307,"type":194},".",{"type":267,"content":309},[310],{"type":196,"attrs":311,"content":312},{"textAlign":179},[313,316,318,322],{"text":140,"type":194,"marks":314},[315],{"type":210},{"text":317,"type":194}," y eventos ",{"text":319,"type":194,"marks":320},"@vue:xxx",[321],{"type":210},{"text":307,"type":194},{"type":267,"content":324},[325],{"type":196,"attrs":326,"content":327},{"textAlign":179},[328,332],{"text":329,"type":194,"marks":330},"Render functions y JSX.",[331],{"type":276},{"text":333,"type":194}," Son componentes Virtual DOM y necesitan interop.",{"type":267,"content":335},[336],{"type":196,"attrs":337,"content":338},{"textAlign":179},[339,343],{"text":340,"type":194,"marks":341},"Directivas personalizadas.",[342],{"type":276},{"text":344,"type":194}," Cambian de comportamiento en Vapor, así que revísalas una por una.",{"type":196,"attrs":346,"content":347},{"textAlign":179},[348],{"text":349,"type":194},"Esta lista sale de las notas de lanzamiento de Vue 3.6. Para tu caso concreto, lo que cuenta es lo que tu código usa.",{"type":189,"attrs":351,"content":352},{"level":82,"textAlign":179},[353],{"text":354,"type":194},"Paso 1: activa la interop en la app existente",{"type":196,"attrs":356,"content":357},{"textAlign":179},[358,360,364,366,370],{"text":359,"type":194},"La aplicación sigue montada con ",{"text":361,"type":194,"marks":362},"createApp",[363],{"type":210},{"text":365,"type":194},", y le agregas ",{"text":367,"type":194,"marks":368},"vaporInteropPlugin",[369],{"type":210},{"text":247,"type":194},{"type":220,"attrs":372,"content":373},{"class":179},[374],{"text":375,"type":194},"import { createApp, vaporInteropPlugin } from 'vue'\nimport App from './App.vue'\nimport router from './router'\n\ncreateApp(App).use(vaporInteropPlugin).use(router).mount('#app')\n",{"type":196,"attrs":377,"content":378},{"textAlign":179},[379],{"text":380,"type":194},"Con esto, cualquier componente Vapor puede vivir dentro de tu árbol Virtual DOM, y al revés. No cambias ninguna ruta ni ningún store.",{"type":196,"attrs":382,"content":383},{"textAlign":179},[384,386,390],{"text":385,"type":194},"Yo lo probé en un laboratorio con Vue Router: el shell de la aplicación es Virtual DOM, con rutas y navegación, y dentro de él un contador ",{"text":387,"type":194,"marks":388},"\u003Cscript setup vapor>",[389],{"type":210},{"text":391,"type":194}," funciona igual que cualquier componente. Al pulsar sus botones, el estado se actualiza y el resto del shell sigue igual.",{"type":189,"attrs":393,"content":394},{"level":82,"textAlign":179},[395],{"text":396,"type":194},"Paso 2: migra un componente hoja",{"type":196,"attrs":398,"content":399},{"textAlign":179},[400],{"text":401,"type":194},"El primer candidato es un componente hoja, sin muchos hijos y sin lógica compleja: una celda de tabla, un badge, un item de lista. Migrarlo es cambiar una palabra:",{"type":220,"attrs":403,"content":404},{"class":179},[405],{"text":406,"type":194},"\u003Cscript setup vapor lang=\"ts\">\nimport { ref } from 'vue'\n\nconst props = defineProps\u003C{ label: string }>()\nconst emit = defineEmits\u003C{ select: [id: string] }>()\nconst isOpen = ref(false)\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cbutton type=\"button\" @click=\"isOpen = !isOpen\" :aria-expanded=\"isOpen\">\n    {{ props.label }}\n  \u003C/button>\n\u003C/template>\n",{"type":196,"attrs":408,"content":409},{"textAlign":179},[410,412,416,418,422,423,427],{"text":411,"type":194},"La API se mantiene: ",{"text":413,"type":194,"marks":414},"defineProps",[415],{"type":210},{"text":417,"type":194},", ",{"text":419,"type":194,"marks":420},"defineEmits",[421],{"type":210},{"text":417,"type":194},{"text":424,"type":194,"marks":425},"ref",[426],{"type":210},{"text":428,"type":194},". Los componentes Virtual DOM que lo usan no necesitan saber que cambió.",{"type":196,"attrs":430,"content":431},{"textAlign":179},[432,434,437],{"text":433,"type":194},"Las notas de lanzamiento documentan que props, eventos y slots pasan entre los dos mundos. Eso no reemplaza tu prueba: antes de migrar un componente, verifica en tu app los casos que realmente usas, como un ",{"text":86,"type":194,"marks":435},[436],{"type":210},{"text":438,"type":194}," sobre un componente o un slot con scope.",{"type":189,"attrs":440,"content":441},{"level":82,"textAlign":179},[442],{"text":443,"type":194},"Paso 3: mide antes de seguir",{"type":196,"attrs":445,"content":446},{"textAlign":179},[447,449,457],{"text":448,"type":194},"Migrar no garantiza una mejora. Antes de seguir con más componentes, mide la pantalla concreta con la misma metodología del ",{"text":450,"type":194,"marks":451},"benchmark",[452],{"type":453,"attrs":454},"link",{"href":455,"uuid":179,"anchor":179,"target":179,"linktype":456},"https://elrincondevue.com/article-list/vue-vapor-benchmark-metodologia","url",{"text":458,"type":194},": build de producción, varias corridas, mediana, y la métrica que refleje lo que el usuario nota.",{"type":196,"attrs":460,"content":461},{"textAlign":179},[462],{"text":463,"type":194},"Si la mejora no aparece, deja el componente en Virtual DOM. Migrar sin medir agrega complejidad de interop sin beneficio.",{"type":189,"attrs":465,"content":466},{"level":82,"textAlign":179},[467],{"text":468,"type":194},"Regiones separadas, no anidamiento mixto",{"type":196,"attrs":470,"content":471},{"textAlign":179},[472],{"text":473,"type":194},"Una regla que sale de las recomendaciones del equipo: mantén las regiones Vapor separadas de las regiones Virtual DOM, en vez de alternarlas capa por capa. Un componente Vapor dentro de un componente Virtual DOM dentro de un componente Vapor funciona en teoría, pero es el caso donde más bordes aparecen.",{"type":196,"attrs":475,"content":476},{"textAlign":179},[477],{"text":478,"type":194},"En la práctica, esto significa migrar una tabla completa, un panel o un micro-frontend entero, no cada componente suelto.",{"type":189,"attrs":480,"content":481},{"level":82,"textAlign":179},[482],{"text":483,"type":194},"El peso: la trampa del modo mixto",{"type":196,"attrs":485,"content":486},{"textAlign":179},[487,489,492],{"text":488,"type":194},"Este es el dato más importante para una aplicación existente. Medí un contador mínimo, compilado con Vite y comprimido con gzip, en tres variantes (",{"text":214,"type":194,"marks":490},[491],{"type":210},{"text":493,"type":194},"):",{"type":495,"content":496},"table",[497,525,557,587],{"type":498,"content":499},"tableRow",[500,509,517],{"type":501,"attrs":502,"content":503},"tableHeader",{"colspan":54,"rowspan":54,"colwidth":179},[504],{"type":196,"attrs":505,"content":506},{"textAlign":179},[507],{"text":508,"type":194},"Variante",{"type":501,"attrs":510,"content":511},{"colspan":54,"rowspan":54,"colwidth":179},[512],{"type":196,"attrs":513,"content":514},{"textAlign":179},[515],{"text":516,"type":194},"Flags por defecto",{"type":501,"attrs":518,"content":519},{"colspan":54,"rowspan":54,"colwidth":179},[520],{"type":196,"attrs":521,"content":522},{"textAlign":179},[523],{"text":524,"type":194},"Sin Options API",{"type":498,"content":526},[527,541,549],{"type":528,"attrs":529,"content":530},"tableCell",{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[531],{"type":196,"attrs":532,"content":533},{"textAlign":179},[534,536,539],{"text":535,"type":194},"Virtual DOM (",{"text":361,"type":194,"marks":537},[538],{"type":210},{"text":540,"type":194},")",{"type":528,"attrs":542,"content":543},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[544],{"type":196,"attrs":545,"content":546},{"textAlign":179},[547],{"text":548,"type":194},"25,1 kB",{"type":528,"attrs":550,"content":551},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[552],{"type":196,"attrs":553,"content":554},{"textAlign":179},[555],{"text":556,"type":194},"21,9 kB",{"type":498,"content":558},[559,572,580],{"type":528,"attrs":560,"content":561},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[562],{"type":196,"attrs":563,"content":564},{"textAlign":179},[565,567,571],{"text":566,"type":194},"Solo Vapor (",{"text":568,"type":194,"marks":569},"createVaporApp",[570],{"type":210},{"text":540,"type":194},{"type":528,"attrs":573,"content":574},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[575],{"type":196,"attrs":576,"content":577},{"textAlign":179},[578],{"text":579,"type":194},"17,8 kB",{"type":528,"attrs":581,"content":582},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[583],{"type":196,"attrs":584,"content":585},{"textAlign":179},[586],{"text":579,"type":194},{"type":498,"content":588},[589,601,609],{"type":528,"attrs":590,"content":591},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[592],{"type":196,"attrs":593,"content":594},{"textAlign":179},[595,597,600],{"text":596,"type":194},"Vapor dentro de app Virtual DOM (",{"text":367,"type":194,"marks":598},[599],{"type":210},{"text":540,"type":194},{"type":528,"attrs":602,"content":603},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[604],{"type":196,"attrs":605,"content":606},{"textAlign":179},[607],{"text":608,"type":194},"45,7 kB",{"type":528,"attrs":610,"content":611},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[612],{"type":196,"attrs":613,"content":614},{"textAlign":179},[615],{"text":616,"type":194},"42,7 kB",{"type":196,"attrs":618,"content":619},{"textAlign":179},[620],{"text":621,"type":194},"Hay tres lecturas:",{"type":623,"attrs":624,"content":625},"ordered_list",{"order":54},[626,637,648],{"type":267,"content":627},[628],{"type":196,"attrs":629,"content":630},{"textAlign":179},[631,635],{"text":632,"type":194,"marks":633},"Una aplicación 100 % Vapor pesa menos.",[634],{"type":276},{"text":636,"type":194}," Un 29 % menos que Virtual DOM con las flags por defecto, y un 19 % menos si desactivas la Options API en Virtual DOM. Esa es la comparación justa, porque Vapor no soporta Options API.",{"type":267,"content":638},[639],{"type":196,"attrs":640,"content":641},{"textAlign":179},[642,646],{"text":643,"type":194,"marks":644},"Con interop, el bundle casi se duplica.",[645],{"type":276},{"text":647,"type":194}," Un 82 % más que Virtual DOM solo, y un 2,6 veces más que Vapor puro, porque se cargan los dos runtimes.",{"type":267,"content":649},[650],{"type":196,"attrs":651,"content":652},{"textAlign":179},[653,657],{"text":654,"type":194,"marks":655},"En una app existente, el peso sube antes de bajar.",[656],{"type":276},{"text":658,"type":194}," La ganancia de tamaño llega cuando eliminas el runtime de Virtual DOM, es decir, cuando toda la aplicación (o micro-frontend) es Vapor. Mientras convives con los dos, pagas los dos.",{"type":196,"attrs":660,"content":661},{"textAlign":179},[662],{"text":663,"type":194},"Por eso, la adopción gradual gana en rendimiento de las partes migradas, pero no en peso. Si el peso inicial es tu problema, la migración completa de un micro-frontend tiene más sentido que migrar componentes sueltos.",{"type":196,"attrs":665,"content":666},{"textAlign":179},[667,669,673,675,679],{"text":668,"type":194},"Estas cifras son de ",{"text":670,"type":194,"marks":671},"rc.14",[672],{"type":210},{"text":674,"type":194}," y son mías: el equipo no publica un tamaño base oficial. Las puedes repetir con el script ",{"text":676,"type":194,"marks":677},"measure:bundle",[678],{"type":210},{"text":680,"type":194}," del laboratorio.",{"type":189,"attrs":682,"content":683},{"level":82,"textAlign":179},[684],{"text":685,"type":194},"Lo que hay que vigilar",{"type":264,"content":687},[688,699,710,737],{"type":267,"content":689},[690],{"type":196,"attrs":691,"content":692},{"textAlign":179},[693,697],{"text":694,"type":194,"marks":695},"DevTools y Vue Test Utils.",[696],{"type":276},{"text":698,"type":194}," En el roadmap de Vapor siguen como pendientes. Revisa si tu flujo de pruebas depende de ellos antes de migrar.",{"type":267,"content":700},[701],{"type":196,"attrs":702,"content":703},{"textAlign":179},[704,708],{"text":705,"type":194,"marks":706},"Transition, KeepAlive y Teleport.",[707],{"type":276},{"text":709,"type":194}," Tienen versión Vapor, pero prueba los casos que usas: animaciones de salida, componentes cacheados y destinos de Teleport.",{"type":267,"content":711},[712],{"type":196,"attrs":713,"content":714},{"textAlign":179},[715,719,721,725,727,731,733,736],{"text":716,"type":194,"marks":717},"Correcciones entre RC.",[718],{"type":276},{"text":720,"type":194}," Solo en ",{"text":722,"type":194,"marks":723},"rc.15",[724],{"type":210},{"text":726,"type":194}," (12 de noviembre) hay decenas de correcciones de Vapor, incluidas varias sobre interop: por ejemplo, componentes interop que se mueven dentro de un ",{"text":728,"type":194,"marks":729},"KeepAlive",[730],{"type":210},{"text":732,"type":194}," o props de custom elements que se aplican juntas. Si pruebas la interop con un RC anterior, repite las pruebas con ",{"text":722,"type":194,"marks":734},[735],{"type":210},{"text":307,"type":194},{"type":267,"content":738},[739],{"type":196,"attrs":740,"content":741},{"textAlign":179},[742,746,748,752],{"text":743,"type":194,"marks":744},"Suspense.",[745],{"type":276},{"text":747,"type":194}," No tiene versión propia de Vapor. Un componente Vapor puede vivir dentro de un ",{"text":749,"type":194,"marks":750},"\u003CSuspense>",[751],{"type":210},{"text":753,"type":194}," de Virtual DOM.",{"type":189,"attrs":755,"content":756},{"level":82,"textAlign":179},[757],{"text":758,"type":194},"Comprueba el resultado",{"type":196,"attrs":760,"content":761},{"textAlign":179},[762],{"text":763,"type":194},"En tu aplicación:",{"type":623,"attrs":765,"content":766},{"order":54},[767,779,786,805],{"type":267,"content":768},[769],{"type":196,"attrs":770,"content":771},{"textAlign":179},[772,774,777],{"text":773,"type":194},"Activa ",{"text":367,"type":194,"marks":775},[776],{"type":210},{"text":778,"type":194}," y confirma que la aplicación arranca y navega sin errores en consola.",{"type":267,"content":780},[781],{"type":196,"attrs":782,"content":783},{"textAlign":179},[784],{"text":785,"type":194},"Migra un componente hoja y verifica sus props, eventos y slots con los casos reales de tu app.",{"type":267,"content":787},[788],{"type":196,"attrs":789,"content":790},{"textAlign":179},[791,793,797,799,803],{"text":792,"type":194},"Ejecuta ",{"text":794,"type":194,"marks":795},"npm run build",[796],{"type":210},{"text":798,"type":194}," y ",{"text":800,"type":194,"marks":801},"npm run preview",[802],{"type":210},{"text":804,"type":194},", y compara el tamaño del bundle con la versión anterior.",{"type":267,"content":806},[807],{"type":196,"attrs":808,"content":809},{"textAlign":179},[810],{"text":811,"type":194},"Si la migración afecta a una pantalla crítica, repite las mediciones de rendimiento de esa pantalla.",{"type":189,"attrs":813,"content":814},{"level":82,"textAlign":179},[815],{"text":816,"type":194},"Errores frecuentes",{"type":264,"content":818},[819,830,841,852],{"type":267,"content":820},[821],{"type":196,"attrs":822,"content":823},{"textAlign":179},[824,828],{"text":825,"type":194,"marks":826},"Migrar componentes sueltos en todas partes.",[827],{"type":276},{"text":829,"type":194}," Multiplicas las fronteras entre runtimes y los casos que verificar, sin ganar peso.",{"type":267,"content":831},[832],{"type":196,"attrs":833,"content":834},{"textAlign":179},[835,839],{"text":836,"type":194,"marks":837},"Asumir que la interop es gratis.",[838],{"type":276},{"text":840,"type":194}," Mezclar runtimes sube el bundle, y las fronteras son donde aparecen los errores.",{"type":267,"content":842},[843],{"type":196,"attrs":844,"content":845},{"textAlign":179},[846,850],{"text":847,"type":194,"marks":848},"Migrar sin medir.",[849],{"type":276},{"text":851,"type":194}," Si la pantalla no mejora, la complejidad extra no se justifica.",{"type":267,"content":853},[854],{"type":196,"attrs":855,"content":856},{"textAlign":179},[857,861,863,866],{"text":858,"type":194,"marks":859},"Usar un RC sin repetir las pruebas de interop.",[860],{"type":276},{"text":862,"type":194}," Las correcciones de ",{"text":722,"type":194,"marks":864},[865],{"type":210},{"text":867,"type":194}," tocan justo ese punto.",{"type":189,"attrs":869,"content":870},{"level":82,"textAlign":179},[871],{"text":872,"type":194},"Cuándo adoptarlo hoy",{"type":264,"content":874},[875,886,897],{"type":267,"content":876},[877],{"type":196,"attrs":878,"content":879},{"textAlign":179},[880,884],{"text":881,"type":194,"marks":882},"Para una pantalla con muchas actualizaciones.",[883],{"type":276},{"text":885,"type":194}," Tablas grandes, dashboards, editores: donde el trabajo del framework es el cuello de botella.",{"type":267,"content":887},[888],{"type":196,"attrs":889,"content":890},{"textAlign":179},[891,895],{"text":892,"type":194,"marks":893},"Para un micro-frontend nuevo o pequeño.",[894],{"type":276},{"text":896,"type":194}," Donde toda la aplicación puede ser Vapor y el peso también mejora.",{"type":267,"content":898},[899],{"type":196,"attrs":900,"content":901},{"textAlign":179},[902,906],{"text":903,"type":194,"marks":904},"No para migrar todo de una vez.",[905],{"type":276},{"text":907,"type":194}," Es una RC, y la adopción gradual pide medir cada paso.",{"type":196,"attrs":909,"content":910},{"textAlign":179},[911,913,919],{"text":912,"type":194},"Si quieres el detalle del compilador que hay detrás de estos componentes, el ",{"text":914,"type":194,"marks":915},"post sobre v-if, v-for, v-model y slots",[916],{"type":453,"attrs":917},{"href":918,"uuid":179,"anchor":179,"target":179,"linktype":456},"https://elrincondevue.com/article-list/vue-vapor-compilador-v-if-v-for-v-model-slots",{"text":920,"type":194}," muestra la salida real de cada patrón.","posts","posts/vue-vapor-adopcion-interop-bundle",-140,[10,9],false,20030325,"9d3b9f3d-df50-42e3-bf34-0805c97e82de","default",[],1794670871803]