Vue3 - Vapor Mode

mercredi 12 juillet 2023
Image par Mathieu LALLEMAND.
Mathieu LALLEMAND Photo de l'auteur

Vue3 Vapor Mode

C'est dans un billet de début d'année que Evan You a précisé qu'il travaillais actuellement à l'intégration d'un Vapor Mode. Il en parle plus en détail dans cette vidéo de début 2023 où il présente l'actualité de l'éco-système VueJS.

Mais qu'est-ce que le vapor mode ?

Un peu d'histoire sur la gestion de la réactivité en Vue2 et Vue3

En javascript, ce qui coûte en temps c'est la phase de modification du DOM (Document Object Model) par le navigateur. En effet, durant cette phase de redraw, le navigateur va prendre les instructions données par le moteur Javascript (V8 pour Chrome) pour les transmettre au moteur de Rendu (WebKit sous Chrome). Cette transmission va prendre du temps. Plus vous aurez de composants et plus votre DOM sera long à mettre à jour.

En Vue 2 (tout comme en React d'ailleurs) la phase de modification du DOM est accélérée par un système qui va calculer toutes les modifications a réaliser sur le DOM en Javascript, puis extraire en une seule fois ce nouvel état pour l'envoyer d'un coup au DOM. Ce système est appelé le Virtual DOM ou V-DOM.

En pratique, il s'agit simplement de définir une function qui va prendre un nom de balise HTML (par exemple div), des propriétés à inclure dans cette balise (les props) et les enfants de ce noeud (Ex: une chaine de caractère qui sera le texte contenu dans div).

En VueJS c'est la fonction h() qui s'occupe de cela. Pour garder l'article d'une longueur raisonnable, je ne vais pas entrer dans les détails, si vous souhaitez creuser le sujet, je vous invite à lire la documentation sur le sujet. Sachez simplement que Vue 2 va réaliser un arbre de tous les noeuds créés, puis à chaque modification d'une valeur, va recalculer l'état "stable" de cet arbre en ne relançant le rendu que pour les composant devant être modifiés pour ensuite transformer cet arbre Javascript en code HTML à envoyer dans le DOM du navigateur.

En Vue 3, le grain est plus fin. Le compilateur va isoler les parties à redessiner au sein même de vos composant. Il va par exemple créer un sous-composant pour un v-if et un autre pour un v-for quelques lignes plus bas si celui-ci n'est pas imbriqué.

Le gain de performance entre Vue 2 et Vue 3 est dû à cette optimisation qui, au lieu de redessiner tout le composant si une partie vient à changer, ne va redessiner qui la sous-partie du composant qui doit changer. Je vous laisse imaginer l'impact sur de très gros composants, que du bonheur !

L'envoi du V-DOM au DOM suis cependant le même principe qu'en vue 2.

Le Vapor Mode de Vue 3

L'idée du Vapor Mode a été inspiré par la bibliothèque SolidJS. Evan You prévoir l'utilisation du Vapor Mode pour les applications dont la performance est critique.

L'idée est de réussir à se passer du V-DOM sur les composants tout en permettant un redraw hyper-rapide du DOM, en utilisant des fonctions JS pour effectuer les modifications en direct. Evidement des gains de performance importants sont attendus car le système devrait s'approcher de très prêt d'une performance javascript optimale (sans les mots de têtes lors de la maintenance du code).

Ainsi, le vapor-mode est un mode spécifique de compilation des fichiers .vue. D'ailleurs pour différencier les fichier qui devront être compilés via le vapor mode des autres, ils porteront l'extension .vapor.vue

Concrètement, en partant de ce code d'exemple :

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
<div>
<button @click="count++">{{ count }}</button>
</div>
</template>

Le compilateur vue/vapor va compiler ce composant de cette manière :

import { ref, effect } from 'vue'
import { template, on, setText } from 'vue/vapor'

const t0 = template(`<div><button>`)

export default () {
const count = ref(0)

let div = t0()
let button = div.firstChild
let _button_text
effect(() => {
setText(button, _button_text, count.value)
})
on(button, 'click', () => count.value++)
return div
}

Le setText va patcher le texte du bouton dès que count.value va changer, et qu'on va écouter l'évènement click sur ce bouton pour changer la valeur de count. Obtenant ainsi une réactivité performante sans passer par un virtual DOM.

Evidement l'équipe autour de VueJS va permettre de n'avoir que certains composants en vapor mode parmi d'autres qui seront eux compilés traditionnellement. Il existera aussi une possibilité de ne coder "que" en vapor mode, en créant son application non plus depuis vue mais de vue/vapor.

Un autre avantage reside dans l'empreinte mémoire, le vapor mode est moins coûteux en mémoire, ce qui laisse entrevoir la possibilité d'avoir des applications avec une plus grosse concentration de composants et donc de données. On parle pour le moment d'un facteur 2.

Si on ajoute à cela un bundle qui va diminuer drastiquement de taille, on aura donc un code de sortie plus rapide et moins gourmand en mémoire...

A quel prix me direz-vous ? Et bien pour le même prix. Enfin presque.

Comment se préparer au Vapor Mode.

Tout d'abord, seule les composant SFC (fichiers .vue) seront compatible avec le vapor mode. Il ne sera donc pas possible de l'utiliser directement dans le navigateur sans compilation préalable.

Ensuite le vapor mode ne comprendra qu'un sous-ensemble de fonction VueJS, par conséquent oubliez l'Option API. Vous devrez forcément utiliser l'API de composition. Et vous devrez le faire via la balise <script setup ... (ce que vous devriez faire depuis au moins 1 an maintenant !)

Restera ensuite à nommer vos composants avec l'extension .vapor.vue et la magie opérera.

Si vous avez suivi l'éco-système VueJS, vous conviendrez que ces quelques contraintes n'en sont pas vraiment car elles viennent s'inscrire dans la continuité du Framework.

Conclusion

Le vapor mode s'annonce comme une formidable avancée, et cela avec un coût quasiment négligeable, un peu comme le passage de Vue2 à Vue3 (si on met de côté le temps qu'ont mis certaines librairies tierces à se mettre à jour).

On pourra compter sur un Framework encore plus rapide, toujours plus proche de la performance optimale tout en garantissant une lecture facile et rapide du code, source d'efficacité dans la maintenance des applications.

Ce Framework m'épate encore 10 après... J'ai vraiment hâte de pouvoir tester cette nouvelle avancée.