[{"data":1,"prerenderedAt":1527},["ShallowReactive",2],{"post-index":3,"post-vue-vapor-mode-sin-virtual-dom":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":43,"created_at":171,"published_at":46,"updated_at":172,"id":173,"uuid":174,"content":175,"slug":42,"full_slug":1519,"sort_by_date":179,"position":1520,"tag_list":1521,"is_startpage":1522,"parent_id":1523,"meta_data":179,"group_id":1524,"first_published_at":46,"release_id":179,"lang":1525,"path":179,"alternates":1526,"default_full_slug":179,"translated_slugs":179},"2026-11-14T13:53:32.077Z","2026-11-14T14:01:56.503Z",241560830292227,"fc23c6c1-06b4-4765-9629-3dac5350d615",{"_uid":176,"demo":177,"image":178,"level":10,"title":43,"video":182,"content":184,"excerpt":45,"category":9,"component":1518,"description":44,"youtube_url":13,"editorial_rank":13},"1def5527-4d0e-4194-9f34-639991417306",[],{"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,214,219,225,230,282,304,309,314,360,365,370,393,418,423,452,458,473,495,500,515,520,537,547,552,557,568,573,578,589,594,611,620,625,630,652,657,662,667,694,711,927,932,979,995,1000,1005,1115,1126,1131,1146,1157,1162,1205,1210,1370,1375,1410,1430,1435,1505],{"type":189,"attrs":190,"content":191},"paragraph",{"textAlign":179},[192,195,200,202,206,208,212],{"text":193,"type":194},"Agregas una palabra a tu componente, ","text",{"text":196,"type":194,"marks":197},"\u003Cscript setup vapor>",[198],{"type":199},"code",{"text":201,"type":194},", y Vue deja de usar el Virtual DOM para renderizarlo. No cambias la sintaxis del template, ni ",{"text":203,"type":194,"marks":204},"ref",[205],{"type":199},{"text":207,"type":194},", ni ",{"text":209,"type":194,"marks":210},"computed",[211],{"type":199},{"text":213,"type":194},". Cambia lo que el compilador genera: en vez de una función que crea un árbol de nodos virtuales en cada actualización, Vapor produce código que escribe directamente en el nodo del DOM que depende de cada dato.",{"type":189,"attrs":215,"content":216},{"textAlign":179},[217],{"text":218,"type":194},"En este artículo vemos qué problema resuelve Vapor Mode, cómo activarlo hoy, qué código genera el compilador y cuánto mejora realmente. Para eso medí la misma tabla de 1.000 filas con los dos motores, y también el peso del bundle. Spoiler: la mejora es enorme en algunas operaciones y modesta en otras, y entender por qué es lo más útil del experimento.",{"type":220,"attrs":221,"content":222},"heading",{"level":82,"textAlign":179},[223],{"text":224,"type":194},"Objetivo y requisitos",{"type":189,"attrs":226,"content":227},{"textAlign":179},[228],{"text":229,"type":194},"Vamos a crear un componente Vapor dentro de una aplicación Vue normal y a leer lo que genera el compilador. Necesitas:",{"type":231,"content":232},"bullet_list",[233,258,271],{"type":234,"content":235},"list_item",[236],{"type":189,"attrs":237,"content":238},{"textAlign":179},[239,244,246,250,252,256],{"text":240,"type":194,"marks":241},"Vue 3.6",[242],{"type":243},"bold",{"text":245,"type":194},", que hoy está en ",{"text":247,"type":194,"marks":248},"Release Candidate",[249],{"type":243},{"text":251,"type":194}," (",{"text":253,"type":194,"marks":254},"3.6.0-rc.15",[255],{"type":199},{"text":257,"type":194},", publicada el 12 de noviembre de 2026). La versión estable sigue siendo la 3.5. El equipo de Vue describe Vapor como completo en funcionalidades en este RC, pero aún no hay fecha para la versión estable.",{"type":234,"content":259},[260],{"type":189,"attrs":261,"content":262},{"textAlign":179},[263,265,269],{"text":264,"type":194},"Un proyecto con Vite creado con ",{"text":266,"type":194,"marks":267},"npm create vue@latest",[268],{"type":199},{"text":270,"type":194}," (TypeScript y Vue Router opcionales).",{"type":234,"content":272},[273],{"type":189,"attrs":274,"content":275},{"textAlign":179},[276,280],{"text":277,"type":194,"marks":278},"@vitejs/plugin-vue",[279],{"type":199},{"text":281,"type":194}," 6.0.10 o superior, la primera versión que acepta el RC de Vue 3.6.",{"type":283,"content":284},"blockquote",[285],{"type":189,"attrs":286,"content":287},{"textAlign":179},[288,290,298,302],{"text":289,"type":194},"Al ser una versión candidata, úsala para experimentar o en partes acotadas de tu aplicación. Revisa el ",{"text":291,"type":194,"marks":292},"CHANGELOG de la rama ",[293],{"type":294,"attrs":295},"link",{"href":296,"uuid":179,"anchor":179,"target":179,"linktype":297},"https://github.com/vuejs/core/blob/minor/CHANGELOG.md","url",{"text":299,"type":194,"marks":300},"minor",[301],{"type":199},{"text":303,"type":194}," antes de actualizar: cada semana sale un RC nuevo con correcciones.",{"type":220,"attrs":305,"content":306},{"level":82,"textAlign":179},[307],{"text":308,"type":194},"El costo que Vapor quiere eliminar",{"type":189,"attrs":310,"content":311},{"textAlign":179},[312],{"text":313,"type":194},"Con el Virtual DOM, cuando cambia un dato ocurre esto:",{"type":315,"attrs":316,"content":317},"ordered_list",{"order":54},[318,325,332,339,353],{"type":234,"content":319},[320],{"type":189,"attrs":321,"content":322},{"textAlign":179},[323],{"text":324,"type":194},"El estado cambia.",{"type":234,"content":326},[327],{"type":189,"attrs":328,"content":329},{"textAlign":179},[330],{"text":331,"type":194},"El componente vuelve a ejecutar su función de render.",{"type":234,"content":333},[334],{"type":189,"attrs":335,"content":336},{"textAlign":179},[337],{"text":338,"type":194},"Se crea un árbol nuevo de nodos virtuales (vnodes).",{"type":234,"content":340},[341],{"type":189,"attrs":342,"content":343},{"textAlign":179},[344,346,351],{"text":345,"type":194},"Vue compara ese árbol con el anterior (",{"text":347,"type":194,"marks":348},"diff",[349],{"type":350},"italic",{"text":352,"type":194},").",{"type":234,"content":354},[355],{"type":189,"attrs":356,"content":357},{"textAlign":179},[358],{"text":359,"type":194},"Aplica al DOM real solo las diferencias.",{"type":189,"attrs":361,"content":362},{"textAlign":179},[363],{"text":364,"type":194},"Vue ya optimiza mucho este proceso: marca qué partes del template son estáticas y cuáles son dinámicas para comparar menos. Aun así, cada actualización paga los pasos 2 a 4 aunque solo haya cambiado un texto.",{"type":189,"attrs":366,"content":367},{"textAlign":179},[368],{"text":369,"type":194},"Con Vapor el camino es más corto:",{"type":315,"attrs":371,"content":372},{"order":54},[373,379,386],{"type":234,"content":374},[375],{"type":189,"attrs":376,"content":377},{"textAlign":179},[378],{"text":324,"type":194},{"type":234,"content":380},[381],{"type":189,"attrs":382,"content":383},{"textAlign":179},[384],{"text":385,"type":194},"Solo se ejecuta el efecto que lee ese dato.",{"type":234,"content":387},[388],{"type":189,"attrs":389,"content":390},{"textAlign":179},[391],{"text":392,"type":194},"Ese efecto escribe directamente en su nodo del DOM.",{"type":189,"attrs":394,"content":395},{"textAlign":179},[396,398,402,404,408,410,416],{"text":397,"type":194},"No hay árbol virtual que recrear ni comparar. El HTML estático del componente se crea una vez clonando un ",{"text":399,"type":194,"marks":400},"\u003Ctemplate>",[401],{"type":199},{"text":403,"type":194},", y cada parte dinámica queda conectada a su propio efecto reactivo. Es el modelo de ",{"text":405,"type":194,"marks":406},"reactividad de grano fino",[407],{"type":243},{"text":409,"type":194}," que popularizaron Solid y Svelte 5; según las notas de lanzamiento de Vue 3.6, Vapor alcanza su mismo nivel de rendimiento en el ",{"text":411,"type":194,"marks":412},"js-framework-benchmark",[413],{"type":294,"attrs":414},{"href":415,"uuid":179,"anchor":179,"target":179,"linktype":297},"https://github.com/krausest/js-framework-benchmark",{"text":417,"type":194},".",{"type":220,"attrs":419,"content":420},{"level":82,"textAlign":179},[421],{"text":422,"type":194},"Activa Vapor en una aplicación existente",{"type":189,"attrs":424,"content":425},{"textAlign":179},[426,428,432,434,438,440,444,446,450],{"text":427,"type":194},"Instala la versión candidata. Como Vue Router declara compatibilidad con ",{"text":429,"type":194,"marks":430},"vue ^3.5",[431],{"type":199},{"text":433,"type":194}," y npm no acepta versiones ",{"text":435,"type":194,"marks":436},"prerelease",[437],{"type":350},{"text":439,"type":194}," en ese rango, fija la versión y añade ",{"text":441,"type":194,"marks":442},"overrides",[443],{"type":199},{"text":445,"type":194}," en ",{"text":447,"type":194,"marks":448},"package.json",[449],{"type":199},{"text":451,"type":194},":",{"type":453,"attrs":454,"content":455},"code_block",{"class":179},[456],{"text":457,"type":194},"{\n  \"dependencies\": {\n    \"vue\": \"3.6.0-rc.15\"\n  },\n  \"overrides\": {\n    \"vue\": \"$vue\",\n    \"@vue/compiler-sfc\": \"$vue\"\n  }\n}\n",{"type":189,"attrs":459,"content":460},{"textAlign":179},[461,463,467,469,472],{"text":462,"type":194},"Ejecuta ",{"text":464,"type":194,"marks":465},"npm install",[466],{"type":199},{"text":468,"type":194},". Cuando la 3.6 sea estable podrás quitar los ",{"text":441,"type":194,"marks":470},[471],{"type":199},{"text":417,"type":194},{"type":189,"attrs":474,"content":475},{"textAlign":179},[476,478,482,484,488,490,494],{"text":477,"type":194},"Crea ",{"text":479,"type":194,"marks":480},"src/components/VaporCounter.vue",[481],{"type":199},{"text":483,"type":194},". Es un componente normal con ",{"text":485,"type":194,"marks":486},"\u003Cscript setup>",[487],{"type":199},{"text":489,"type":194},"; la única diferencia es el atributo ",{"text":491,"type":194,"marks":492},"vapor",[493],{"type":199},{"text":451,"type":194},{"type":453,"attrs":496,"content":497},{"class":179},[498],{"text":499,"type":194},"\u003Cscript setup vapor lang=\"ts\">\nimport { ref } from 'vue'\n\nconst count = ref(0)\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cbutton type=\"button\" @click=\"count++\">Clicks: {{ count }}\u003C/button>\n\u003C/template>\n",{"type":189,"attrs":501,"content":502},{"textAlign":179},[503,505,509,510,514],{"text":504,"type":194},"Para usarlo dentro de una aplicación que sigue usando Virtual DOM, registra ",{"text":506,"type":194,"marks":507},"vaporInteropPlugin",[508],{"type":199},{"text":445,"type":194},{"text":511,"type":194,"marks":512},"src/main.ts",[513],{"type":199},{"text":451,"type":194},{"type":453,"attrs":516,"content":517},{"class":179},[518],{"text":519,"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":189,"attrs":521,"content":522},{"textAlign":179},[523,525,529,531,535],{"text":524,"type":194},"Ahora puedes importar ",{"text":526,"type":194,"marks":527},"VaporCounter",[528],{"type":199},{"text":530,"type":194}," desde cualquier componente, por ejemplo en ",{"text":532,"type":194,"marks":533},"App.vue",[534],{"type":199},{"text":536,"type":194},", como harías con cualquier otro. Props, eventos y slots funcionan entre los dos mundos.",{"type":189,"attrs":538,"content":539},{"textAlign":179},[540,542,546],{"text":541,"type":194},"Si toda tu aplicación es Vapor, puedes prescindir del runtime del Virtual DOM y montarla con ",{"text":543,"type":194,"marks":544},"createVaporApp",[545],{"type":199},{"text":451,"type":194},{"type":453,"attrs":548,"content":549},{"class":179},[550],{"text":551,"type":194},"import { createVaporApp } from 'vue'\nimport App from './App.vue' // también con \u003Cscript setup vapor>\n\ncreateVaporApp(App).mount('#app')\n",{"type":220,"attrs":553,"content":554},{"level":82,"textAlign":179},[555],{"text":556,"type":194},"Qué genera el compilador",{"type":189,"attrs":558,"content":559},{"textAlign":179},[560,562,566],{"text":561,"type":194},"La mejor forma de entender Vapor es leer su salida. Este es el mismo contador compilado con ",{"text":563,"type":194,"marks":564},"@vue/compiler-sfc",[565],{"type":199},{"text":567,"type":194}," en los dos modos (recorté imports, envoltorios y anotaciones de TypeScript).",{"type":189,"attrs":569,"content":570},{"textAlign":179},[571],{"text":572,"type":194},"Con Virtual DOM, el componente devuelve una función de render que crea vnodes en cada actualización:",{"type":453,"attrs":574,"content":575},{"class":179},[576],{"text":577,"type":194},"return (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(\"button\", {\n    type: \"button\",\n    onClick: _cache[0] || (_cache[0] = $event => (count.value++))\n  }, \"Clicks: \" + _toDisplayString(count.value), 1 /* TEXT */))\n}\n",{"type":189,"attrs":579,"content":580},{"textAlign":179},[581,583,587],{"text":582,"type":194},"Con Vapor, ",{"text":584,"type":194,"marks":585},"setup",[586],{"type":199},{"text":588,"type":194}," construye el DOM una sola vez y conecta los efectos:",{"type":453,"attrs":590,"content":591},{"class":179},[592],{"text":593,"type":194},"const t0 = _template(\"\u003Cbutton type=button> \", 1)\n\n// dentro de setup()\nconst n0 = t0()                 // clona el HTML estático\nconst x0 = _txt(n0)             // referencia al nodo de texto\n_on(n0, \"click\", () => (count.value++))\n_renderEffect(() => _setText(x0, \"Clicks: \" + _toDisplayString(count.value)))\nreturn n0\n",{"type":189,"attrs":595,"content":596},{"textAlign":179},[597,599,603,605,609],{"text":598,"type":194},"Ya no hay función de render. Cuando cambia ",{"text":600,"type":194,"marks":601},"count",[602],{"type":199},{"text":604,"type":194},", Vue solo vuelve a ejecutar ese ",{"text":606,"type":194,"marks":607},"_renderEffect",[608],{"type":199},{"text":610,"type":194},", que actualiza el texto de un nodo concreto. El resto del componente no se vuelve a evaluar.",{"type":220,"attrs":612,"content":613},{"level":70,"textAlign":179},[614,616],{"text":615,"type":194},"Un detalle brillante: ",{"text":617,"type":194,"marks":618},"createSelector",[619],{"type":199},{"type":189,"attrs":621,"content":622},{"textAlign":179},[623],{"text":624,"type":194},"El caso más interesante aparece en las listas. Imagina una lista donde una fila puede estar seleccionada:",{"type":453,"attrs":626,"content":627},{"class":179},[628],{"text":629,"type":194},"\u003Cli\n  v-for=\"row in rows\"\n  :key=\"row.id\"\n  :class=\"{ active: row.id === selectedId }\"\n  @click=\"selectedId = row.id\"\n>\n  {{ row.label }}\n\u003C/li>\n",{"type":189,"attrs":631,"content":632},{"textAlign":179},[633,635,639,641,645,647,651],{"text":634,"type":194},"Con Virtual DOM, cambiar ",{"text":636,"type":194,"marks":637},"selectedId",[638],{"type":199},{"text":640,"type":194}," vuelve a renderizar el componente y compara las 1.000 filas. El compilador Vapor detecta el patrón ",{"text":642,"type":194,"marks":643},"row.id === selectedId",[644],{"type":199},{"text":646,"type":194}," y genera un ",{"text":648,"type":194,"marks":649},"selector",[650],{"type":350},{"text":451,"type":194},{"type":453,"attrs":653,"content":654},{"class":179},[655],{"text":656,"type":194},"const _selector0 = _createSelector(() => selectedId.value)\n\n// por cada fila:\n_selector0(_for_item0.value.id, () => {\n  _setClassName(n2, _for_item0.value.id === selectedId.value ? 1 : 0, \"active\")\n})\n",{"type":189,"attrs":658,"content":659},{"textAlign":179},[660],{"text":661,"type":194},"Cuando cambia la selección, solo se ejecutan los efectos de dos filas: la que deja de estar activa y la nueva. El costo deja de depender del tamaño de la lista.",{"type":220,"attrs":663,"content":664},{"level":82,"textAlign":179},[665],{"text":666,"type":194},"¿Cuánto mejora realmente?",{"type":189,"attrs":668,"content":669},{"textAlign":179},[670,672,675,677,681,683,686,688,692],{"text":671,"type":194},"Monté la misma tabla dos veces. Los archivos son idénticos salvo por la palabra ",{"text":491,"type":194,"marks":673},[674],{"type":199},{"text":676,"type":194},", y cada tabla vive en una aplicación aislada (",{"text":678,"type":194,"marks":679},"createApp",[680],{"type":199},{"text":682,"type":194}," frente a ",{"text":543,"type":194,"marks":684},[685],{"type":199},{"text":687,"type":194},"). Medí con Vue ",{"text":689,"type":194,"marks":690},"3.6.0-rc.14",[691],{"type":199},{"text":693,"type":194},", en un build de producción, Chrome 156 y Windows 11, usando la mediana de 10 ejecuciones.",{"type":189,"attrs":695,"content":696},{"textAlign":179},[697,699,703,705,709],{"text":698,"type":194},"Medí dos cosas. ",{"text":700,"type":194,"marks":701},"Solo JS",[702],{"type":243},{"text":704,"type":194}," es el tiempo desde que cambia el estado hasta que Vue termina de escribir en el DOM. ",{"text":706,"type":194,"marks":707},"JS + layout",[708],{"type":243},{"text":710,"type":194}," suma además el cálculo de layout que hace el navegador.",{"type":712,"content":713},"table",[714,758,801,843,885],{"type":715,"content":716},"tableRow",[717,726,734,742,750],{"type":718,"attrs":719,"content":720},"tableHeader",{"colspan":54,"rowspan":54,"colwidth":179},[721],{"type":189,"attrs":722,"content":723},{"textAlign":179},[724],{"text":725,"type":194},"Operación",{"type":718,"attrs":727,"content":728},{"colspan":54,"rowspan":54,"colwidth":179},[729],{"type":189,"attrs":730,"content":731},{"textAlign":179},[732],{"text":733,"type":194},"VDOM, solo JS",{"type":718,"attrs":735,"content":736},{"colspan":54,"rowspan":54,"colwidth":179},[737],{"type":189,"attrs":738,"content":739},{"textAlign":179},[740],{"text":741,"type":194},"Vapor, solo JS",{"type":718,"attrs":743,"content":744},{"colspan":54,"rowspan":54,"colwidth":179},[745],{"type":189,"attrs":746,"content":747},{"textAlign":179},[748],{"text":749,"type":194},"VDOM, JS + layout",{"type":718,"attrs":751,"content":752},{"colspan":54,"rowspan":54,"colwidth":179},[753],{"type":189,"attrs":754,"content":755},{"textAlign":179},[756],{"text":757,"type":194},"Vapor, JS + layout",{"type":715,"content":759},[760,769,777,785,793],{"type":761,"attrs":762,"content":763},"tableCell",{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[764],{"type":189,"attrs":765,"content":766},{"textAlign":179},[767],{"text":768,"type":194},"Crear 1.000 filas",{"type":761,"attrs":770,"content":771},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[772],{"type":189,"attrs":773,"content":774},{"textAlign":179},[775],{"text":776,"type":194},"9,4 ms",{"type":761,"attrs":778,"content":779},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[780],{"type":189,"attrs":781,"content":782},{"textAlign":179},[783],{"text":784,"type":194},"5,6 ms",{"type":761,"attrs":786,"content":787},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[788],{"type":189,"attrs":789,"content":790},{"textAlign":179},[791],{"text":792,"type":194},"43,1 ms",{"type":761,"attrs":794,"content":795},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[796],{"type":189,"attrs":797,"content":798},{"textAlign":179},[799],{"text":800,"type":194},"37,3 ms",{"type":715,"content":802},[803,811,819,827,835],{"type":761,"attrs":804,"content":805},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[806],{"type":189,"attrs":807,"content":808},{"textAlign":179},[809],{"text":810,"type":194},"Actualizar 1 de cada 10 filas",{"type":761,"attrs":812,"content":813},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[814],{"type":189,"attrs":815,"content":816},{"textAlign":179},[817],{"text":818,"type":194},"2,0 ms",{"type":761,"attrs":820,"content":821},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[822],{"type":189,"attrs":823,"content":824},{"textAlign":179},[825],{"text":826,"type":194},"0,3 ms",{"type":761,"attrs":828,"content":829},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[830],{"type":189,"attrs":831,"content":832},{"textAlign":179},[833],{"text":834,"type":194},"6,1 ms",{"type":761,"attrs":836,"content":837},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[838],{"type":189,"attrs":839,"content":840},{"textAlign":179},[841],{"text":842,"type":194},"3,6 ms",{"type":715,"content":844},[845,853,861,869,877],{"type":761,"attrs":846,"content":847},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[848],{"type":189,"attrs":849,"content":850},{"textAlign":179},[851],{"text":852,"type":194},"Seleccionar una fila",{"type":761,"attrs":854,"content":855},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[856],{"type":189,"attrs":857,"content":858},{"textAlign":179},[859],{"text":860,"type":194},"1,6 ms",{"type":761,"attrs":862,"content":863},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[864],{"type":189,"attrs":865,"content":866},{"textAlign":179},[867],{"text":868,"type":194},"0,1 ms",{"type":761,"attrs":870,"content":871},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[872],{"type":189,"attrs":873,"content":874},{"textAlign":179},[875],{"text":876,"type":194},"5,1 ms",{"type":761,"attrs":878,"content":879},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[880],{"type":189,"attrs":881,"content":882},{"textAlign":179},[883],{"text":884,"type":194},"3,9 ms",{"type":715,"content":886},[887,895,903,911,919],{"type":761,"attrs":888,"content":889},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[890],{"type":189,"attrs":891,"content":892},{"textAlign":179},[893],{"text":894,"type":194},"Crear 10.000 filas",{"type":761,"attrs":896,"content":897},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[898],{"type":189,"attrs":899,"content":900},{"textAlign":179},[901],{"text":902,"type":194},"75,8 ms",{"type":761,"attrs":904,"content":905},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[906],{"type":189,"attrs":907,"content":908},{"textAlign":179},[909],{"text":910,"type":194},"67,4 ms",{"type":761,"attrs":912,"content":913},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[914],{"type":189,"attrs":915,"content":916},{"textAlign":179},[917],{"text":918,"type":194},"445,5 ms",{"type":761,"attrs":920,"content":921},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[922],{"type":189,"attrs":923,"content":924},{"textAlign":179},[925],{"text":926,"type":194},"392,1 ms",{"type":189,"attrs":928,"content":929},{"textAlign":179},[930],{"text":931,"type":194},"Tres conclusiones:",{"type":315,"attrs":933,"content":934},{"order":54},[935,957,968],{"type":234,"content":936},[937],{"type":189,"attrs":938,"content":939},{"textAlign":179},[940,944,946,949,951,955],{"text":941,"type":194,"marks":942},"En las actualizaciones, el trabajo de Vue casi desaparece.",[943],{"type":243},{"text":945,"type":194}," Entre 3,5 y 15 veces menos JavaScript, porque no hay render ni diff. La selección de fila es el caso extremo gracias a ",{"text":617,"type":194,"marks":947},[948],{"type":199},{"text":950,"type":194}," (valores tan pequeños rozan la precisión de ",{"text":952,"type":194,"marks":953},"performance.now()",[954],{"type":199},{"text":956,"type":194},", así que tómalo como orden de magnitud).",{"type":234,"content":958},[959],{"type":189,"attrs":960,"content":961},{"textAlign":179},[962,966],{"text":963,"type":194,"marks":964},"Al crear nodos, la ventaja es moderada",[965],{"type":243},{"text":967,"type":194}," (entre 1,1 y 1,7 veces). Ambos motores tienen que crear los mismos elementos en el DOM.",{"type":234,"content":969},[970],{"type":189,"attrs":971,"content":972},{"textAlign":179},[973,977],{"text":974,"type":194,"marks":975},"Medido de punta a punta, el navegador pasa a ser el cuello de botella.",[976],{"type":243},{"text":978,"type":194}," El layout cuesta lo mismo con los dos motores, por eso el total mejora entre 1,1 y 1,7 veces. Vapor no acelera el DOM: elimina el trabajo que Vue hacía alrededor de él.",{"type":189,"attrs":980,"content":981},{"textAlign":179},[982,984,988,990,994],{"text":983,"type":194},"Midiendo en modo desarrollo las cifras cambian bastante, porque Vue añade comprobaciones. Compara siempre con ",{"text":985,"type":194,"marks":986},"npm run build",[987],{"type":199},{"text":989,"type":194}," y ",{"text":991,"type":194,"marks":992},"npm run preview",[993],{"type":199},{"text":417,"type":194},{"type":220,"attrs":996,"content":997},{"level":70,"textAlign":179},[998],{"text":999,"type":194},"El peso del bundle",{"type":189,"attrs":1001,"content":1002},{"textAlign":179},[1003],{"text":1004,"type":194},"También compilé un contador mínimo en tres variantes con Vite y medí el JavaScript resultante comprimido con gzip:",{"type":712,"content":1006},[1007,1025,1048,1071,1093],{"type":715,"content":1008},[1009,1017],{"type":718,"attrs":1010,"content":1011},{"colspan":54,"rowspan":54,"colwidth":179},[1012],{"type":189,"attrs":1013,"content":1014},{"textAlign":179},[1015],{"text":1016,"type":194},"Variante",{"type":718,"attrs":1018,"content":1019},{"colspan":54,"rowspan":54,"colwidth":179},[1020],{"type":189,"attrs":1021,"content":1022},{"textAlign":179},[1023],{"text":1024,"type":194},"gzip",{"type":715,"content":1026},[1027,1040],{"type":761,"attrs":1028,"content":1029},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[1030],{"type":189,"attrs":1031,"content":1032},{"textAlign":179},[1033,1035,1038],{"text":1034,"type":194},"Virtual DOM (",{"text":678,"type":194,"marks":1036},[1037],{"type":199},{"text":1039,"type":194},")",{"type":761,"attrs":1041,"content":1042},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[1043],{"type":189,"attrs":1044,"content":1045},{"textAlign":179},[1046],{"text":1047,"type":194},"25,1 kB",{"type":715,"content":1049},[1050,1063],{"type":761,"attrs":1051,"content":1052},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[1053],{"type":189,"attrs":1054,"content":1055},{"textAlign":179},[1056,1058,1062],{"text":1057,"type":194},"Virtual DOM sin Options API (",{"text":1059,"type":194,"marks":1060},"__VUE_OPTIONS_API__: false",[1061],{"type":199},{"text":1039,"type":194},{"type":761,"attrs":1064,"content":1065},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[1066],{"type":189,"attrs":1067,"content":1068},{"textAlign":179},[1069],{"text":1070,"type":194},"21,9 kB",{"type":715,"content":1072},[1073,1085],{"type":761,"attrs":1074,"content":1075},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[1076],{"type":189,"attrs":1077,"content":1078},{"textAlign":179},[1079,1081,1084],{"text":1080,"type":194},"Solo Vapor (",{"text":543,"type":194,"marks":1082},[1083],{"type":199},{"text":1039,"type":194},{"type":761,"attrs":1086,"content":1087},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[1088],{"type":189,"attrs":1089,"content":1090},{"textAlign":179},[1091],{"text":1092,"type":194},"17,8 kB",{"type":715,"content":1094},[1095,1107],{"type":761,"attrs":1096,"content":1097},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[1098],{"type":189,"attrs":1099,"content":1100},{"textAlign":179},[1101,1103,1106],{"text":1102,"type":194},"Vapor dentro de una app VDOM (",{"text":506,"type":194,"marks":1104},[1105],{"type":199},{"text":1039,"type":194},{"type":761,"attrs":1108,"content":1109},{"colspan":54,"rowspan":54,"colwidth":179,"backgroundColor":179},[1110],{"type":189,"attrs":1111,"content":1112},{"textAlign":179},[1113],{"text":1114,"type":194},"45,7 kB",{"type":189,"attrs":1116,"content":1117},{"textAlign":179},[1118,1120,1124],{"text":1119,"type":194},"Una aplicación solo Vapor pesa un 19 % menos que la versión VDOM sin Options API, que es la comparación justa porque Vapor no la soporta. Pero fíjate en la última fila: ",{"text":1121,"type":194,"marks":1122},"con el plugin de interoperabilidad se cargan los dos runtimes",[1123],{"type":243},{"text":1125,"type":194}," y el bundle casi se duplica. En una aplicación existente, la ganancia de Vapor está en el rendimiento de los componentes migrados, no en el peso.",{"type":220,"attrs":1127,"content":1128},{"level":82,"textAlign":179},[1129],{"text":1130,"type":194},"Comprueba el resultado",{"type":189,"attrs":1132,"content":1133},{"textAlign":179},[1134,1135,1139,1141,1144],{"text":462,"type":194},{"text":1136,"type":194,"marks":1137},"npm run dev",[1138],{"type":199},{"text":1140,"type":194}," y pulsa el botón: el contador debe aumentar igual que un componente normal. Después ejecuta ",{"text":985,"type":194,"marks":1142},[1143],{"type":199},{"text":1145,"type":194}," para confirmar que el type-check y la compilación pasan.",{"type":189,"attrs":1147,"content":1148},{"textAlign":179},[1149,1151,1155],{"text":1150,"type":194},"Para ver lo que genera el compilador sin configurar nada, crea un archivo ",{"text":1152,"type":194,"marks":1153},"inspect-vapor.mjs",[1154],{"type":199},{"text":1156,"type":194}," en la raíz del proyecto:",{"type":453,"attrs":1158,"content":1159},{"class":179},[1160],{"text":1161,"type":194},"import { readFileSync } from 'node:fs'\nimport { parse, compileScript } from 'vue/compiler-sfc'\n\nconst file = 'src/components/VaporCounter.vue'\n// El atributo vapor del archivo tiene prioridad: lo quitamos para controlar el modo con la opción.\nconst source = readFileSync(file, 'utf8').replace('\u003Cscript setup vapor', '\u003Cscript setup')\nconst { descriptor } = parse(source, { filename: file })\n\nfor (const vapor of [false, true]) {\n  const { content } = compileScript(descriptor, { id: 'demo', inlineTemplate: true, vapor })\n  console.log(`\\n--- vapor: ${vapor} ---\\n${content}`)\n}\n",{"type":189,"attrs":1163,"content":1164},{"textAlign":179},[1165,1167,1171,1173,1177,1179,1183,1185,1189,1191,1195,1196,1199,1200,1204],{"text":1166,"type":194},"Ejecútalo con ",{"text":1168,"type":194,"marks":1169},"node inspect-vapor.mjs",[1170],{"type":199},{"text":1172,"type":194},". Con ",{"text":1174,"type":194,"marks":1175},"vapor: false",[1176],{"type":199},{"text":1178,"type":194}," verás ",{"text":1180,"type":194,"marks":1181},"_createElementBlock",[1182],{"type":199},{"text":1184,"type":194}," dentro de una función de render; con ",{"text":1186,"type":194,"marks":1187},"vapor: true",[1188],{"type":199},{"text":1190,"type":194},", ",{"text":1192,"type":194,"marks":1193},"_template",[1194],{"type":199},{"text":1190,"type":194},{"text":606,"type":194,"marks":1197},[1198],{"type":199},{"text":989,"type":194},{"text":1201,"type":194,"marks":1202},"_setText",[1203],{"type":199},{"text":417,"type":194},{"type":220,"attrs":1206,"content":1207},{"level":82,"textAlign":179},[1208],{"text":1209,"type":194},"Errores frecuentes y límites",{"type":231,"content":1211},[1212,1235,1264,1289,1300,1341,1352],{"type":234,"content":1213},[1214],{"type":189,"attrs":1215,"content":1216},{"textAlign":179},[1217,1221,1224,1227,1229,1233],{"text":1218,"type":194,"marks":1219},"Solo ",[1220],{"type":243},{"text":485,"type":194,"marks":1222},[1223],{"type":199},{"text":417,"type":194,"marks":1225},[1226],{"type":243},{"text":1228,"type":194}," Vapor no soporta Options API. Un componente con ",{"text":1230,"type":194,"marks":1231},"\u003Cscript>",[1232],{"type":199},{"text":1234,"type":194}," normal no se puede compilar en modo Vapor.",{"type":234,"content":1236},[1237],{"type":189,"attrs":1238,"content":1239},{"textAlign":179},[1240,1244,1246,1250,1252,1256,1258,1262],{"text":1241,"type":194,"marks":1242},"Sin instancia pública.",[1243],{"type":243},{"text":1245,"type":194}," ",{"text":1247,"type":194,"marks":1248},"getCurrentInstance()",[1249],{"type":199},{"text":1251,"type":194}," devuelve ",{"text":1253,"type":194,"marks":1254},"null",[1255],{"type":199},{"text":1257,"type":194}," y no existe ",{"text":1259,"type":194,"marks":1260},"app.config.globalProperties",[1261],{"type":199},{"text":1263,"type":194},". Si una librería depende de ellos, ese componente debe seguir en Virtual DOM.",{"type":234,"content":1265},[1266],{"type":189,"attrs":1267,"content":1268},{"textAlign":179},[1269,1273,1276,1279,1281,1287],{"text":1270,"type":194,"marks":1271},"Sin ",[1272],{"type":243},{"text":140,"type":194,"marks":1274},[1275],{"type":199},{"text":417,"type":194,"marks":1277},[1278],{"type":243},{"text":1280,"type":194}," Con Vapor no hace falta: la directiva existía para ",{"text":1282,"type":194,"marks":1283},"evitar renders innecesarios del Virtual DOM",[1284],{"type":294,"attrs":1285},{"href":1286,"uuid":179,"anchor":179,"target":179,"linktype":297},"https://elrincondevue.com/article-list/how-to-use-v-memo",{"text":1288,"type":194},", y en Vapor no hay render que evitar.",{"type":234,"content":1290},[1291],{"type":189,"attrs":1292,"content":1293},{"textAlign":179},[1294,1298],{"text":1295,"type":194,"marks":1296},"Render functions y JSX siguen siendo Virtual DOM.",[1297],{"type":243},{"text":1299,"type":194}," Necesitan el plugin de interoperabilidad.",{"type":234,"content":1301},[1302],{"type":189,"attrs":1303,"content":1304},{"textAlign":179},[1305,1309,1313,1317,1319,1323,1325,1329,1330,1334,1335,1339],{"text":1306,"type":194,"marks":1307},"No hay ",[1308],{"type":243},{"text":1310,"type":194,"marks":1311},"Suspense",[1312],{"type":199},{"text":1314,"type":194,"marks":1315}," propio de Vapor.",[1316],{"type":243},{"text":1318,"type":194}," Un componente Vapor sí puede vivir dentro de un ",{"text":1320,"type":194,"marks":1321},"\u003CSuspense>",[1322],{"type":199},{"text":1324,"type":194}," del Virtual DOM. ",{"text":1326,"type":194,"marks":1327},"Transition",[1328],{"type":199},{"text":1190,"type":194},{"text":1331,"type":194,"marks":1332},"KeepAlive",[1333],{"type":199},{"text":989,"type":194},{"text":1336,"type":194,"marks":1337},"Teleport",[1338],{"type":199},{"text":1340,"type":194}," sí tienen versión Vapor.",{"type":234,"content":1342},[1343],{"type":189,"attrs":1344,"content":1345},{"textAlign":179},[1346,1350],{"text":1347,"type":194,"marks":1348},"Interoperabilidad con librerías de UI.",[1349],{"type":243},{"text":1351,"type":194}," Funciona, pero el equipo recomienda separar regiones Vapor y Virtual DOM en vez de anidarlas mezcladas.",{"type":234,"content":1353},[1354],{"type":189,"attrs":1355,"content":1356},{"textAlign":179},[1357,1361,1363,1369],{"text":1358,"type":194,"marks":1359},"Herramientas.",[1360],{"type":243},{"text":1362,"type":194}," El soporte en Vue DevTools y Vue Test Utils todavía figura como pendiente en el ",{"text":1364,"type":194,"marks":1365},"roadmap de Vapor",[1366],{"type":294,"attrs":1367},{"href":1368,"uuid":179,"anchor":179,"target":179,"linktype":297},"https://github.com/vuejs/core/issues/13687",{"text":417,"type":194},{"type":220,"attrs":1371,"content":1372},{"level":82,"textAlign":179},[1373],{"text":1374,"type":194},"Cuándo usarlo hoy",{"type":231,"content":1376},[1377,1388,1399],{"type":234,"content":1378},[1379],{"type":189,"attrs":1380,"content":1381},{"textAlign":179},[1382,1386],{"text":1383,"type":194,"marks":1384},"Partes críticas de una aplicación existente:",[1385],{"type":243},{"text":1387,"type":194}," tablas grandes, dashboards con muchas actualizaciones, editores. Migra esos componentes y mide antes y después.",{"type":234,"content":1389},[1390],{"type":189,"attrs":1391,"content":1392},{"textAlign":179},[1393,1397],{"text":1394,"type":194,"marks":1395},"Aplicaciones pequeñas o micro-frontends nuevos completamente en Vapor",[1396],{"type":243},{"text":1398,"type":194},", donde además ganas en peso.",{"type":234,"content":1400},[1401],{"type":189,"attrs":1402,"content":1403},{"textAlign":179},[1404,1408],{"text":1405,"type":194,"marks":1406},"No migres todo de golpe.",[1407],{"type":243},{"text":1409,"type":194}," Es un RC, y mezclar los dos motores aumenta el bundle. La API que escribes es la misma, así que activarlo componente a componente es barato y reversible.",{"type":189,"attrs":1411,"content":1412},{"textAlign":179},[1413,1415,1419,1420,1424,1425,1428],{"text":1414,"type":194},"En las próximas entregas veremos cómo medí estos números sin engañarnos, qué más genera el compilador Vapor (",{"text":1416,"type":194,"marks":1417},"v-for",[1418],{"type":199},{"text":1190,"type":194},{"text":1421,"type":194,"marks":1422},"v-if",[1423],{"type":199},{"text":1190,"type":194},{"text":86,"type":194,"marks":1426},[1427],{"type":199},{"text":1429,"type":194},") y cómo adoptarlo en una aplicación real con librerías de terceros.",{"type":220,"attrs":1431,"content":1432},{"level":82,"textAlign":179},[1433],{"text":1434,"type":194},"Lecturas recomendadas",{"type":231,"content":1436},[1437,1450,1462,1474,1492],{"type":234,"content":1438},[1439],{"type":189,"attrs":1440,"content":1441},{"textAlign":179},[1442,1448],{"text":1443,"type":194,"marks":1444},"Notas de lanzamiento de Vue 3.6.0-rc.1",[1445],{"type":294,"attrs":1446},{"href":1447,"uuid":179,"anchor":179,"target":179,"linktype":297},"https://github.com/vuejs/core/releases/tag/v3.6.0-rc.1",{"text":1449,"type":194},": sintaxis, APIs y funcionalidades no soportadas.",{"type":234,"content":1451},[1452],{"type":189,"attrs":1453,"content":1454},{"textAlign":179},[1455,1460],{"text":1456,"type":194,"marks":1457},"CHANGELOG de Vue 3.6",[1458],{"type":294,"attrs":1459},{"href":296,"uuid":179,"anchor":179,"target":179,"linktype":297},{"text":1461,"type":194},": cambios de cada RC.",{"type":234,"content":1463},[1464],{"type":189,"attrs":1465,"content":1466},{"textAlign":179},[1467,1472],{"text":1468,"type":194,"marks":1469},"Roadmap de Vapor Mode",[1470],{"type":294,"attrs":1471},{"href":1368,"uuid":179,"anchor":179,"target":179,"linktype":297},{"text":1473,"type":194},": qué falta para la versión estable.",{"type":234,"content":1475},[1476],{"type":189,"attrs":1477,"content":1478},{"textAlign":179},[1479,1485,1487,1490],{"text":1480,"type":194,"marks":1481},"La nueva reactividad basada en alien-signals",[1482],{"type":294,"attrs":1483},{"href":1484,"uuid":179,"anchor":179,"target":179,"linktype":297},"https://github.com/vuejs/core/pull/12349",{"text":1486,"type":194},": menos memoria y ",{"text":209,"type":194,"marks":1488},[1489],{"type":199},{"text":1491,"type":194}," más rápidos en Vue 3.6.",{"type":234,"content":1493},[1494],{"type":189,"attrs":1495,"content":1496},{"textAlign":179},[1497,1503],{"text":1498,"type":194,"marks":1499},"Rendering Mechanism",[1500],{"type":294,"attrs":1501},{"href":1502,"uuid":179,"anchor":179,"target":179,"linktype":297},"https://vuejs.org/guide/extras/rendering-mechanism.html",{"text":1504,"type":194}," en la documentación oficial: cómo funciona el Virtual DOM que Vapor reemplaza.",{"type":189,"attrs":1506,"content":1507},{"textAlign":179},[1508,1510,1516],{"text":1509,"type":194},"Si te interesa cómo Vue convierte componentes en otras piezas de la plataforma web, lee también ",{"text":1511,"type":194,"marks":1512},"Web Components con Vue 3",[1513],{"type":294,"attrs":1514},{"href":1515,"uuid":179,"anchor":179,"target":179,"linktype":297},"https://elrincondevue.com/article-list/web-components-with-modern-vue",{"text":1517,"type":194}," en El Rincón de Vue.","posts","posts/vue-vapor-mode-sin-virtual-dom",-110,[10,9],false,20030325,"1ba66dd6-3339-4642-8f59-777fa12f42d9","default",[],1794670871649]