ADVERTENCIA — Software en fase alpha, para conocimiento, no para producción. Todo lo que describe este capítulo corresponde a OWL 3, una versión publicada actualmente como
3.0.0-alpha.45en el repositorio odoo/owl. El documento oficial de diseño lo dice sin rodeos: "the design is still a work in progress" (el diseño todavía está en desarrollo). No hay fecha anunciada para una versión estable. Nada de lo que verás aquí debería usarse hoy en un proyecto real — las APIs que aprendiste en el resto de este libro (OWL 2.0) son las que corren en las versiones actuales de Odoo, incluyendo Odoo 19. Este capítulo existe para que, cuando OWL 3 llegue, nada de esto te tome por sorpresa.¿Por qué este capítulo? Porque el OWL que acabas de dominar durante diecisiete capítulos no es el estado final — ya hay una reescritura mayor en marcha, y conocer su forma ahora significa que no tendrás que reaprender todo desde cero más adelante. ¿Qué trata de resolver Odoo con esto? La reactividad de OWL 2.0 está atada a las instancias de componente de una forma que limita cómo se puede compartir, derivar u observar el estado fuera de un ciclo de render — OWL 3 es una reconstrucción desde cero pensada para eliminar esa limitación. Aplicación en la vida real: Todavía ninguna, y ese es justamente el punto — esto es preparación, no una técnica para llevar a un proyecto de cliente. La aplicación realista hoy es reconocer el vocabulario (signals, Plugins,
useProps()) cuando empiece a aparecer en notas de lanzamiento, para que una futura migración no te tome por sorpresa.
Todo framework, tarde o temprano, reescribe las partes de sí mismo que resultaron limitantes. React lo hizo al pasar de componentes de clase a hooks. Vue lo hizo al pasar de la Options API a la Composition API. OWL está haciendo algo similar ahora con su sistema de reactividad — y el efecto dominó llega hasta las props, los servicios, los hooks de ciclo de vida e incluso el compilador de templates.
Este capítulo es un recorrido guiado por los cambios más grandes, basado directamente en el documento de diseño propio de OWL y en la guía de migración en borrador del repositorio odoo/owl. Piénsalo como un adelanto, no como un tutorial — aquí no construirás nada, solo aprenderás a reconocer lo que viene.
¿Por Qué una Nueva Versión Mayor?
En OWL 2.0, la reactividad se construye sobre useState, que envuelve un objeto en un Proxy (Capítulo 7). Ese proxy está atado al componente que lo creó: OWL rastrea "este componente leyó esta propiedad, así que hay que volver a renderizarlo cuando cambie". Funciona bien, pero tiene un límite estructural — los valores reactivos son difíciles de compartir, calcular u observar fuera del ciclo de renderizado de un componente.
OWL 3 reconstruye la reactividad alrededor de signals (señales): pequeños contenedores reactivos que no están atados a ningún componente en particular. Cualquier cosa que lea una signal — el render de un componente, un valor calculado, un efecto — se suscribe automáticamente a ella, sin importar dónde viva ese código. Ese único cambio es la raíz de casi todo lo demás en este capítulo.
El Modelo de Reactividad: De Proxies a Signals
Donde OWL 2.0 te da useState() y reactive(), OWL 3 te da cuatro bloques de construcción:
signal(valor)— un único valor reactivo, de lectura/escritura.proxy(objeto)— el equivalente más cercano aluseState()/reactive()de hoy: un objeto cuyas propiedades están respaldadas cada una por una signal.computed(() => ...)— un valor derivado que se recalcula automáticamente cuando cambian las signals que lee, y queda cacheado hasta entonces.effect(() => ...)— ejecuta un callback cada vez que cambian las signals que lee (similar en espíritu auseEffect, pero no atado a un componente).
// OWL 2.0 (este libro)
setup() {
this.state = useState({ count: 0, step: 1 });
}
// OWL 3 (alpha)
setup() {
this.state = proxy({ count: 0, step: 1 });
this.doubled = computed(() => this.state.count * 2);
}
Qué reemplaza esto: el patrón del Capítulo 7 donde calculabas un valor derivado directamente en el template, o lo recalculabas en cada render dentro de un getter. computed() cachea el resultado y solo recalcula cuando cambian sus dependencias reales — cercano a cómo funciona la memoization (Capítulo 8), pero automático.
Props y Entorno: Un Nuevo Modelo de Inyección
Este es el cambio con mayor radio de impacto. En OWL 2.0, todo componente recibe automáticamente this.props y this.env (Capítulos 8 y 11). En OWL 3, ambos dejan de ser miembros implícitos del componente.
Las props se declaran explícitamente con useProps() y un validador construido con el helper t:
// OWL 2.0 (este libro)
static props = { name: String, age: { type: Number, optional: true } };
// OWL 3 (alpha)
setup() {
this.props = useProps({
name: t.string(),
age: t.number().optional(0),
});
}
this.env y toda la capa de servicios (useService, Capítulo 13) se reemplazan por un sistema de Plugins: en vez de un objeto de entorno global del que cualquier componente puede sacar servicios, defines una clase Plugin y declaras explícitamente qué componentes dependen de ella.
// OWL 3 (alpha) — boceto, la API todavía está en movimiento
class OrmPlugin extends Plugin { /* ... */ }
setup() {
this.orm = usePlugin(OrmPlugin);
}
Por qué te importa esto: todo lo que el Capítulo 13 enseñó sobre useService("orm"), useService("notification"), etc. se traduce conceptualmente en "inyectar un Plugin" en OWL 3 — el patrón (declarar una dependencia, no acceder a un global) sobrevive, pero la API es completamente distinta.
Cambios en el Ciclo de Vida
Tres cambios aquí afectan directamente hooks que ya conoces del Capítulo 10:
onWillUpdatePropsse elimina, sin reemplazo directo. Según lo que estuvieras haciendo con él, la guía de migración te dirige haciacomputed()(si derivabas estado a partir de props),useEffect()(si ejecutabas un efecto puntual), o un nuevo hookasyncComputed()(si cargabas datos según una prop — la prop tiene que ser una signal para que esto funcione).onPatched/onWillPatchse vuelven más estrictos. En OWL 2.0 se disparan cuando cualquier descendiente se vuelve a renderizar, incluso a través de un slot. En OWL 3 solo se disparan cuando el propio componente se re-renderiza — el re-render de un descendiente ya no burbujea hacia arriba.this.render(),onWillRenderyonRenderedse eliminan directamente, sin reemplazo directo listado todavía.
Cambios en el Compilador de Templates
Algunos cambios afectan cómo escribes templates QWeb:
- Ya no hay variables libres implícitas. En OWL 2.0 puedes escribir
t-on-click="onClick"y OWL resuelveonClickcomothis.onClick. OWL 3 exige elthis.explícito:t-on-click="this.onClick". t-escse elimina. Usat-outpara todo — en OWL 3,t-outse extendió para manejar de forma segura tanto valores simples como markup, así que cubre lo que antes hacíat-esc(Capítulo 6).t-refyt-modelahora toman una signal, no un string. En OWL 2.0 escribest-ref="miRef"y leesthis.miRef.el; en OWL 3 la ref misma es una signal que creas y pasas.t-slotse renombra at-call-slot. El renombre busca dejar más claro que esta directiva inserta el contenido de un slot, a diferencia det-set-slot, que sigue definiendo qué recibe un slot (Capítulo 14).
Eventos
useExternalListener (el hook que usarías para escuchar en window o document con limpieza automática) se renombra a useListener. Funcionalmente es la misma idea: adjuntar un listener que se elimina automáticamente cuando el componente se desmonta.
Las directivas t-on-* también ganan un nuevo modificador .passive para listeners sensibles al rendimiento como scroll o touchmove — le indica al navegador que el handler nunca llamará a preventDefault(), lo que le permite optimizar el scroll. Es mutuamente excluyente con .prevent por la misma razón.
Qué se Elimina sin Reemplazo Directo
Una lista corta de cosas que este libro cubre (o que existen en OWL 2.0) que la guía de migración actualmente marca como eliminadas, sin un reemplazo 1:1 documentado todavía:
t-portal(renderizar fuera del árbol del componente)useComponent()(el hook de bajo nivel para acceder a la instancia del componente actual)loadFile
Si construyes algo con esto hoy, ten en cuenta que una futura migración a OWL 3 requerirá repensar esa parte del código, no solo reemplazar el nombre de una API.
Estado Actual y Cronograma
Al momento de escribir esto, odoo/owl está publicando pre-releases alpha (la más reciente al momento de la investigación era 3.0.0-alpha.45) desde una rama master que ya fue reestructurada en paquetes separados (owl-core, owl-compiler, owl-runtime, owl). El propio documento owl3_design.md afirma que el diseño todavía está evolucionando, y no hay fecha anunciada para una versión estable 3.0.0. El código de Odoo (la rama saas-19.4) ya tiene commits que vendorizan builds alpha de OWL 3 — una señal de que las pruebas internas están en marcha — pero eso no es lo mismo que OWL 3 estando listo para autores de addons.
¿Deberías Aprender OWL 3 Ahora?
Para trabajo de producción, no — todavía no. Todo lo que construiste en los ejemplos de este libro y en los addons de ejemplo es OWL 2.0, y eso es lo que corre en toda versión de Odoo actualmente soportada, incluyendo Odoo 19. Trata este capítulo como un mapa de hacia dónde van los conceptos, para que términos como "signals", "Plugins" y useProps() no te resulten desconocidos cuando aparezcan en notas de lanzamiento o artículos.
Si quieres profundizar una vez que domines todo lo de los Capítulos 1 a 17, las fuentes primarias son:
- doc/v3/owl/owl3_design.md en el repositorio odoo/owl (la justificación del diseño)
- doc/v3/owl/migration_owl2_to_owl3.md en el mismo repositorio (la guía de migración práctica, cambio disruptivo por cambio disruptivo)
Ambos son documentos vivos — espera que cambien antes de que OWL 3 se estabilice.
Resumen
OWL 3 es una reconstrucción desde cero del sistema de reactividad de OWL, pasando de proxies atados a un componente (useState) a signals independientes (signal, proxy, computed, effect). Ese único cambio se propaga hacia cómo se declaran las props (useProps() en vez de static props), cómo se inyectan los servicios (un sistema de Plugins en vez de env/useService), qué hooks de ciclo de vida existen (onWillUpdateProps desaparece, onPatched/onWillPatch se vuelven más estrictos), e incluso pequeñas reglas de sintaxis de templates (this. explícito, t-esc desaparece, t-slot se renombra a t-call-slot). Todo esto sigue en fase alpha y explícitamente en desarrollo — lee este capítulo para reconocer la forma de lo que viene, no para empezar a construir con ello.
TL;DR: OWL 3 sigue en alpha (3.0.0-alpha.45, sin fecha estable) y reconstruye la reactividad alrededor de signals, reemplazando useState/props/servicios/varios hooks en el camino — lee este capítulo para estar al tanto, no para empezar a construir con ello.
¿Qué Sigue?
No hay siguiente capítulo — este es el final del libro. El mejor próximo paso es volver atrás y poner a trabajar los Capítulos 1 al 17: construir algo real con los addons de ejemplo, romperlo, arreglarlo, y que así sea como OWL 2.0 realmente se te quede. Cuando vuelva la curiosidad por OWL 3, doc/v3/owl/ en el repositorio odoo/owl es donde el diseño sigue evolucionando.
Fin del Capítulo 18 Fin de "OWL 2.0: Donde Termina Odoo y Empiezas Tú"