Comparaison des frameworks
Si vous consultez cette page, vous avez probablement déjà utilisé d'autres frameworks pour construire des applications, et vous voulez savoir si Mithril.js peut vous aider à résoudre vos problèmes plus efficacement.
Pourquoi ne pas utiliser [insérer votre framework préféré ici] ?
La réalité est que la plupart des frameworks modernes sont rapides et bien adaptés à la construction d'applications complexes et maintenables, à condition de savoir les utiliser efficacement. On trouve des exemples d'applications très complexes utilisant presque tous les frameworks populaires : Udemy utilise Angular, AirBnB utilise React, Gitlab utilise Vue, Guild Wars 2 utilise Mithril.js (oui, à l'intérieur du jeu !). Il est clair qu'il s'agit dans tous les cas de frameworks adaptés à une utilisation professionnelle.
En général, si votre équipe est déjà fortement investie dans un autre framework/bibliothèque/"stack", il est plus logique de s'y tenir, sauf si votre équipe s'accorde à dire qu'il existe une raison très forte justifiant une réécriture coûteuse.
Cependant, si vous commencez un nouveau projet, envisagez d'essayer Mithril.js, ne serait-ce que pour comprendre la valeur que les utilisateurs de Mithril.js tirent de moins de 10kb (compressé gzip) de code. Mithril.js est utilisé par de nombreuses entreprises bien connues (par exemple, Vimeo, Nike, Fitbit), et il alimente également de grandes plateformes open-source (par exemple, Lichess, Flarum).
Pourquoi utiliser Mithril.js ?
En une phrase : parce que Mithril.js est pragmatique. Ce guide de 10 minutes en est un bon exemple : c'est le temps qu'il faut pour apprendre les composants, XHR et le routage - et c'est à peu près la quantité de connaissances nécessaires pour construire des applications utiles.
Mithril.js a pour objectif de réaliser un travail significatif de manière efficace. Faire des téléchargements de fichiers ? La documentation vous montre comment faire. Authentification ? Documenté aussi. Animations de sortie ? Vous l'avez. Aucune bibliothèque supplémentaire nécessaire, pas de fonctionnalités obscures.
Comparaisons
React
React est une bibliothèque de vues maintenue par Facebook.
React et Mithril.js partagent beaucoup de similitudes. Si vous avez déjà appris React, vous savez déjà presque tout ce dont vous avez besoin pour construire des applications avec Mithril.
- Ils utilisent tous les deux le DOM virtuel, les méthodes de cycle de vie et la réconciliation basée sur les clés.
- Ils organisent tous les deux les vues via des composants.
- Ils utilisent tous les deux JavaScript comme mécanisme de contrôle de flux dans les vues.
La différence la plus évidente entre React et Mithril.js réside dans leur portée. React est une bibliothèque de vues, donc une application typique basée sur React s'appuie sur des bibliothèques tierces pour le routage, XHR et la gestion d'état. L'utilisation d'une approche orientée bibliothèque permet aux développeurs de personnaliser leur "stack" pour qu'elle corresponde précisément à leurs besoins. En d'autres termes, les architectures basées sur React peuvent varier considérablement d'un projet à l'autre. Par conséquent, ces projets sont d'autant plus susceptibles de dépasser la barre des 1 Mo.
Mithril.js intègre des modules pour les besoins courants tels que le routage et XHR, et le guide en montre une utilisation idiomatique. Cette approche est préférable pour les équipes qui apprécient la cohérence et la facilité d'intégration.
Performance
React et Mithril.js accordent tous deux une grande importance aux performances de rendu, mais ils s'y prennent de différentes manières. Dans le passé, React avait deux implémentations de rendu DOM (une utilisant l'API DOM et une utilisant innerHTML
). Son architecture de fibre à venir introduit la planification et la priorisation des unités de travail. React dispose également d'un système de construction sophistiqué qui désactive divers contrôles et messages d'erreur pour les déploiements en production, ainsi que diverses optimisations spécifiques au navigateur. De plus, il existe également plusieurs bibliothèques axées sur la performance qui exploitent les "hooks" shouldComponentUpdate
de React et les propriétés de vérification rapide de l'égalité des objets des bibliothèques de structures de données immuables pour réduire les temps de réconciliation du DOM virtuel. D'une manière générale, l'approche de React en matière de performance consiste à concevoir des solutions relativement complexes.
Mithril.js adopte la philosophie du "moins c'est plus". Il possède une base de code considérablement plus petite et optimisée de manière agressive. En effet, une petite base de code est plus facile à auditer et à optimiser, ce qui réduit la quantité de code exécuté.
Voici une comparaison des temps de chargement des bibliothèques, c'est-à-dire le temps nécessaire pour analyser et exécuter le code JavaScript de chaque framework, en ajoutant un appel console.time()
au début et un appel console.timeEnd()
à la fin d'un script composé uniquement de code de framework. Pour votre confort de lecture, voici les 20 meilleurs résultats avec le code de journalisation ajouté manuellement aux scripts groupés, exécutés à partir du système de fichiers, dans Chrome sur un modeste PC de bureau de 2010 :
React | Mithril.js |
---|---|
55.8 ms | 4.5 ms |
Les temps de chargement des bibliothèques sont cruciaux pour les applications qui ne restent pas ouvertes longtemps (par exemple, sur mobile) et qui ne peuvent pas être optimisées par la mise en cache ou d'autres techniques.
Étant donné qu'il s'agit d'un micro-benchmark, nous vous encourageons à reproduire ces tests vous-même, car le matériel peut avoir un impact significatif sur les résultats. Notez que les "bundlers" comme Webpack peuvent déplacer les dépendances avant les appels de "timer" pour émuler la résolution statique des modules. Vous devez donc soit copier le code à partir des fichiers CDN compilés, soit ouvrir le fichier de sortie de la bibliothèque de "bundler", et ajouter manuellement les appels de "timer" haute résolution console.time
et console.timeEnd
au script groupé. Évitez d'utiliser new Date
et performance.now
, car ces mécanismes ne sont pas aussi précis statistiquement.
Pour votre confort de lecture, voici une version de ce "benchmark" adaptée à l'utilisation de CDN sur le web : le "benchmark" pour React est ici, et le "benchmark" pour Mithril.js est ici. Notez que nous évaluons les performances de l'ensemble de Mithril.js plutôt que du seul module de rendu (qui aurait une portée équivalente à React). Notez également que cette configuration basée sur CDN entraîne des frais généraux dus à la récupération des ressources à partir du cache disque (~2ms par ressource). Pour ces raisons, les chiffres ici ne sont pas entièrement exacts, mais ils devraient être suffisants pour observer que la vitesse d'initialisation de Mithril.js est sensiblement meilleure que celle de React.
Voici un "benchmark" légèrement plus significatif : mesurer le temps de script nécessaire pour créer 10 000 divs (et 10 000 nœuds de texte). Encore une fois, voici le code de "benchmark" pour React et Mithril.js. Leurs meilleurs résultats sont présentés ci-dessous :
React | Mithril.js |
---|---|
99.7 ms | 42.8 ms |
Ces chiffres montrent que Mithril.js s'initialise non seulement beaucoup plus rapidement, mais qu'il peut également traiter plus de 20 000 nœuds DOM virtuels avant que React ne soit prêt à être utilisé.
Performance de mise à jour
La performance de mise à jour peut être encore plus cruciale que celle du premier rendu, car les mises à jour peuvent se produire plusieurs fois pendant l'exécution d'une application monopage.
Un outil utile pour évaluer la performance de mise à jour est un outil développé par l'équipe Ember, appelé DbMonster. Il met à jour une table aussi rapidement que possible et mesure les images par seconde (FPS) ainsi que les temps JavaScript (min, max et moyen). Le nombre de FPS peut être difficile à évaluer, car il inclut également les temps de repeinture du navigateur et le délai de "clamping" setTimeout
. Ainsi, le chiffre le plus significatif à considérer est le temps de rendu moyen. Vous pouvez comparer une implémentation de React et une implémentation de Mithril.js. Les résultats d'exemple sont présentés ci-dessous :
React | Mithril.js |
---|---|
12.1 ms | 6.4 ms |
Performance de développement
Une autre chose à garder à l'esprit est que, comme React ajoute des contrôles supplémentaires et des messages d'erreur utiles en mode développement, il est plus lent en développement que la version de production utilisée pour les "benchmarks" ci-dessus. Pour illustrer, voici le "benchmark" de 10 000 nœuds ci-dessus en utilisant la version de développement de React.
Remplacements directs
Il existe plusieurs projets qui revendiquent la parité de l'API avec React (certains via des bibliothèques de couches de compatibilité), mais ils ne sont pas entièrement compatibles (par exemple, la prise en charge de PropType est généralement tronquée, les événements synthétiques ne sont parfois pas pris en charge et certaines API ont des sémantiques différentes). Notez que ces bibliothèques incluent généralement aussi des fonctionnalités qui ne font pas partie de l'API officielle de React, ce qui peut devenir problématique si l'on décide de revenir à React Fiber.
Les affirmations concernant la petite taille de téléchargement (par rapport à React) sont exactes, mais la plupart de ces bibliothèques sont légèrement plus grandes que le module de rendu de Mithril.js. Preact est la seule exception.
Méfiez-vous des affirmations agressives en matière de performance, car les "benchmarks" utilisés par certains de ces projets sont connus pour être obsolètes et imparfaits (dans le sens où ils peuvent être - et sont - exploités). Boris Kaul (auteur de certains des "benchmarks") a écrit en détail sur la façon dont les "benchmarks" sont truqués. Une autre chose à garder à l'esprit est que certains "benchmarks" utilisent de manière agressive des fonctionnalités d'optimisation avancées et démontrent ainsi une performance potentielle, c'est-à-dire une performance qui est possible compte tenu de certaines mises en garde, mais qui est réalistement improbable à moins que vous ne passiez activement du temps à examiner l'ensemble de votre base de code en identifiant les candidats à l'optimisation et en évaluant les risques de régression entraînés par les mises en garde de l'optimisation.
Afin de démontrer les caractéristiques de performance typiques, les benchmarks présentés dans cette page de comparaison sont implémentés de manière naïve, idiomatique et comparable (c'est-à-dire la façon dont vous écririez normalement 99 % de votre code). Ils n'emploient pas d'astuces ou d'optimisations avancées pour améliorer artificiellement les performances d'un framework par rapport à un autre. Vous êtes encouragé à contribuer une "PR" si vous pensez qu'une implémentation DbMonster ici pourrait être écrite de manière plus idiomatique.
Complexité
React et Mithril.js ont tous les deux des surfaces d'API relativement petites par rapport aux autres frameworks, ce qui contribue à faciliter la courbe d'apprentissage. Cependant, alors que Mithril.js idiomatique peut être écrit sans perte de lisibilité en utilisant du ES5 simple et aucune autre dépendance, React idiomatique s'appuie fortement sur des outils complexes (par exemple, Babel, plugin JSX, etc.), et ce niveau de complexité s'étend fréquemment aux parties populaires de son écosystème, que ce soit sous la forme d'extensions de syntaxe (par exemple, la syntaxe de "spread" d'objet non standard dans Redux), d'architectures (par exemple, celles qui utilisent des bibliothèques de données immuables) ou de fioritures (par exemple, le "hot module reloading").
Bien que des chaînes d'outils complexes soient également possibles avec Mithril.js et d'autres frameworks, il est fortement recommandé de suivre les principes KISS (Keep It Simple, Stupid) et YAGNI (You Ain't Gonna Need It) lors de l'utilisation de Mithril.
Courbe d'apprentissage
React et Mithril.js ont tous les deux des courbes d'apprentissage relativement courtes. La courbe d'apprentissage de React consiste principalement à comprendre les composants et leur cycle de vie. La courbe d'apprentissage des composants Mithril.js est presque identique. Il y a évidemment plus d'API à apprendre dans Mithril.js, puisque Mithril.js inclut également le routage et XHR, mais la courbe d'apprentissage serait assez similaire à l'apprentissage de React, React Router et une bibliothèque XHR comme superagent ou axios.
React idiomatique nécessite une connaissance pratique de JSX et de ses mises en garde, et il y a donc aussi une petite courbe d'apprentissage liée à Babel.
Documentation
La documentation de React est claire et bien écrite, et comprend une bonne référence d'API, des tutoriels pour démarrer, ainsi que des pages couvrant divers concepts avancés. Malheureusement, comme React se limite à n'être qu'une bibliothèque de vues, sa documentation n'explore pas comment utiliser React de manière idiomatique dans le contexte d'une application réelle. En conséquence, il existe de nombreuses bibliothèques de gestion d'état populaires et donc les architectures utilisant React peuvent différer considérablement d'une entreprise à l'autre (ou même entre les projets).
La documentation de Mithril.js comprend également des tutoriels d'introduction, des pages sur les concepts avancés et une section de référence d'API étendue, qui comprend des informations sur les types d'entrée/sortie, des exemples pour divers cas d'utilisation courants et des conseils contre l'utilisation abusive et les "anti-patterns". Elle comprend également un "aide-mémoire" pour une référence rapide.
La documentation de Mithril.js démontre également des solutions simples et proches du métal pour les cas d'utilisation courants dans les applications réelles, informant ainsi les développeurs que les normes web peuvent désormais rivaliser avec les grandes bibliothèques établies.
Angular
Angular est un framework d'application web développé par Google.
Angular et Mithril.js sont assez différents, mais ils présentent quelques similitudes :
- Les deux prennent en charge la composantisation.
- Les deux ont un éventail d'outils pour divers aspects des applications web (par exemple, le routage, XHR).
La différence la plus évidente entre Angular et Mithril.js réside dans leur complexité. Cela se remarque plus facilement dans la manière dont les vues sont implémentées. Les vues Mithril.js sont écrites en JavaScript simple, et le contrôle de flux s'effectue à l'aide de mécanismes intégrés à JavaScript, tels que les opérateurs ternaires ou Array.prototype.map
. Angular, en revanche, met en œuvre un système de directives pour étendre les vues HTML, permettant d'évaluer des expressions de type JavaScript dans les attributs HTML et les interpolations. Angular est en fait livré avec un analyseur et un compilateur écrits en JavaScript pour y parvenir. Si cela ne semble pas assez complexe, il existe en fait deux modes de compilation (un mode par défaut qui génère dynamiquement des fonctions JavaScript pour la performance, et un mode plus lent pour traiter les restrictions de la politique de sécurité du contenu).
Performance
Angular a fait beaucoup de progrès en termes de performance au fil des années. Angular 1 utilisait un mécanisme connu sous le nom de "dirty checking" qui avait tendance à devenir lent en raison de la nécessité de constamment différencier les grandes structures $scope
. Angular 2 utilise un mécanisme de détection des changements de modèle qui est beaucoup plus performant. Cependant, même malgré les améliorations d'Angular, Mithril.js est souvent plus rapide qu'Angular, en raison de la facilité d'audit que permet la petite taille de la base de code de Mithril.js.
Il est difficile de comparer les temps de chargement entre Angular et Mithril.js pour plusieurs raisons. La première raison est qu'Angular 1 et 2 sont en réalité des bases de code complètement différentes, et les deux versions sont officiellement prises en charge et maintenues (la grande majorité des bases de code Angular en production utilise encore la version 1). La deuxième raison est qu'Angular et Mithril.js sont modulaires. Dans les deux cas, il est possible de supprimer une partie importante du framework qui n'est pas utilisée dans une application donnée.
Cela dit, le plus petit "bundle" connu d'Angular 2 est un [hello world de 29kb] compressé avec l'algorithme Brotli (il fait 35kb avec gzip standard), et la plupart des fonctionnalités utiles d'Angular ont été supprimées. En comparaison, un hello world Mithril.js - incluant l'ensemble du cœur de Mithril.js avec toutes ses fonctionnalités - ferait environ 10kb compressé gzip.
De plus, gardez à l'esprit que les frameworks comme Angular et Mithril.js sont conçus pour des applications non triviales, donc une application qui utiliserait toute la surface de l'API d'Angular devrait télécharger plusieurs centaines de ko de code de framework, plutôt que seulement 29 ko.
Performance de mise à jour
Un outil utile pour évaluer la performance de mise à jour est un outil développé par l'équipe Ember, appelé DbMonster. Il met à jour une table aussi rapidement que possible et mesure les images par seconde (FPS) ainsi que les temps JavaScript (min, max et moyen). Le nombre de FPS peut être difficile à évaluer, car il inclut également les temps de repeinture du navigateur et le délai de "clamping" setTimeout
. Ainsi, le chiffre le plus significatif à considérer est le temps de rendu moyen. Vous pouvez comparer une implémentation d'Angular et une implémentation de Mithril.js. Les résultats d'exemple sont présentés ci-dessous :
Angular | Mithril.js |
---|---|
11.5 ms | 6.4 ms |
Complexité
Angular offre plus d'outils que Mithril.js (sous la forme de diverses directives et services), mais il est aussi beaucoup plus complexe. Comparez la surface de l'API d'Angular avec celle de Mithril.js. Vous pouvez juger par vous-même quelle API est la plus auto-descriptive et la plus pertinente pour vos besoins.
Angular 2 a beaucoup plus de concepts à comprendre : au niveau du langage, Typescript est le langage recommandé, et en plus de cela, il y a aussi la syntaxe de modèle spécifique à Angular telle que les liaisons, les "pipes", "l'opérateur de navigation sécurisée". Vous devez également vous renseigner sur les concepts architecturaux tels que les modules, les composants, les services, les directives, etc., et sur l'endroit où il est approprié d'utiliser quoi.
Courbe d'apprentissage
Si nous comparons des pommes avec des pommes, Angular 2 et Mithril.js ont des courbes d'apprentissage similaires : dans les deux, les composants sont un aspect central de l'architecture, et les deux ont des outils de routage et XHR raisonnables.
Cela étant dit, Angular a beaucoup plus de concepts à apprendre que Mithril. Il offre des API spécifiques à Angular pour beaucoup de choses qui peuvent souvent être trivialement implémentées (par exemple, la pluralisation est essentiellement une instruction "switch", la validation "required" est simplement une vérification d'égalité, etc.). Les templates Angular comportent également plusieurs couches d'abstraction pour émuler ce que JavaScript fait nativement dans Mithril.js. Par exemple, ng-if
/ngIf
d'Angular est une directive qui utilise un analyseur et un compilateur personnalisés pour évaluer une chaîne d'expression et émuler la portée lexicale, et ainsi de suite. Mithril.js a tendance à être beaucoup plus transparent, et donc plus facile à comprendre.
Documentation
La documentation d'Angular 2 fournit un tutoriel d'introduction étendu, et un autre tutoriel qui implémente une application. Il a également divers guides pour les concepts avancés, un "aide-mémoire" et un guide de style. Malheureusement, pour le moment, la référence de l'API laisse beaucoup à désirer. Plusieurs API ne sont pas documentées ou ne fournissent aucun contexte sur ce à quoi l'API pourrait servir.
La documentation de Mithril.js comprend des tutoriels d'introduction, des pages sur les concepts avancés et une section de référence d'API étendue, qui comprend des informations sur les types d'entrée/sortie, des exemples pour divers cas d'utilisation courants et des conseils contre l'utilisation abusive et les "anti-patterns". Elle comprend également un "aide-mémoire" pour une référence rapide.
La documentation de Mithril.js démontre également des solutions simples et proches du métal pour les cas d'utilisation courants dans les applications réelles, informant ainsi les développeurs que les normes web peuvent désormais rivaliser avec les grandes bibliothèques établies.
Vue
Vue est une bibliothèque de vues similaire à Angular.
Vue et Mithril.js ont beaucoup de différences mais ils partagent aussi quelques similitudes :
- Ils utilisent tous les deux le DOM virtuel et les méthodes de cycle de vie.
- Les deux organisent les vues via des composants.
Vue 2 utilise un "fork" de Snabbdom comme système de DOM virtuel. De plus, Vue fournit également des outils pour le routage et la gestion d'état sous forme de modules séparés. Vue ressemble beaucoup à Angular et fournit un système de directives similaire, des modèles basés sur HTML et des directives de flux logique. Il diffère d'Angular en ce qu'il implémente un système réactif de "monkeypatching" qui écrase les méthodes natives dans l'arborescence de données d'un composant (alors qu'Angular 1 utilise le "dirty checking" et les cycles "digest/apply" pour obtenir des résultats similaires). Semblable à Angular 2, Vue compile les modèles HTML en fonctions, mais les fonctions compilées ressemblent plus aux vues Mithril.js ou React, qu'aux fonctions de rendu compilées d'Angular.
Vue est significativement plus petit qu'Angular lorsque l'on compare des pommes avec des pommes, mais pas aussi petit que Mithril.js (le cœur de Vue fait environ 23kb compressé gzip, alors que le module de rendu équivalent dans Mithril.js fait environ 4kb compressé gzip). Les deux ont des caractéristiques de performance similaires, mais les "benchmarks" suggèrent généralement que Mithril.js est légèrement plus rapide.
Performance
Voici une comparaison des temps de chargement des bibliothèques, c'est-à-dire le temps nécessaire pour analyser et exécuter le code JavaScript de chaque framework, en ajoutant un appel console.time()
au début et un appel console.timeEnd()
à la fin d'un script composé uniquement de code de framework. Pour votre confort de lecture, voici les 20 meilleurs résultats avec le code de journalisation ajouté manuellement aux scripts groupés, exécutés à partir du système de fichiers, dans Chrome sur un modeste PC de bureau de 2010 :
Vue | Mithril.js |
---|---|
21.8 ms | 4.5 ms |
Les temps de chargement des bibliothèques sont cruciaux pour les applications qui ne restent pas ouvertes longtemps (par exemple, sur mobile) et qui ne peuvent pas être optimisées par la mise en cache ou d'autres techniques.
Performance de mise à jour
Un outil utile pour évaluer la performance de mise à jour est un outil développé par l'équipe Ember, appelé DbMonster. Il met à jour une table aussi rapidement que possible et mesure les images par seconde (FPS) ainsi que les temps JavaScript (min, max et moyen). Le nombre de FPS peut être difficile à évaluer, car il inclut également les temps de repeinture du navigateur et le délai de "clamping" setTimeout
. Ainsi, le chiffre le plus significatif à considérer est le temps de rendu moyen. Vous pouvez comparer une implémentation Vue et une implémentation Mithril.js. Les deux implémentations sont naïves (c'est-à-dire sans optimisations). Les résultats d'exemple sont présentés ci-dessous :
Vue | Mithril.js |
---|---|
9.8 ms | 6.4 ms |
Complexité
Vue est fortement inspiré par Angular et a beaucoup de choses que Angular fait (par exemple, les directives, les filtres, les liaisons bidirectionnelles, v-cloak
), mais a aussi des choses inspirées par React (par exemple, les composants). À partir de Vue 2.0, il est également possible d'écrire des modèles en utilisant la syntaxe "hyperscript/JSX" (en plus des composants à fichier unique et des divers "plugins" de transpilation de langage basés sur webpack). Vue fournit à la fois la liaison de données bidirectionnelle et une bibliothèque de gestion d'état optionnelle de type Redux, mais contrairement à Angular, il ne fournit pas de guide de style. Les nombreuses façons de faire une chose peuvent provoquer une fragmentation architecturale dans les projets de longue durée.
Mithril.js a beaucoup moins de concepts et organise généralement les applications en termes de composants et d'une couche de données. Tous les styles de création de composants dans Mithril.js produisent la même structure "vnode" en utilisant uniquement des fonctionnalités JavaScript natives. La conséquence directe de s'appuyer sur le langage est moins d'outillage et une configuration de projet plus simple.
Documentation
Vue et Mithril.js disposent tous deux d'une bonne documentation. Les deux incluent une bonne référence d'API avec des exemples, des tutoriels pour démarrer, ainsi que des pages couvrant divers concepts avancés.
Cependant, en raison de l'approche de Vue qui consiste à faire une chose de plusieurs façons, certaines choses peuvent ne pas être correctement documentées. Par exemple, leur "hyperscript" est fortement survolé.
La documentation de Mithril.js a généralement tendance à être trop approfondie si un sujet implique des choses en dehors de la portée de Mithril. Par exemple, lorsqu'un sujet implique une bibliothèque tierce, la documentation de Mithril.js explique le processus d'installation de la bibliothèque tierce. La documentation de Mithril.js démontre également souvent des solutions simples et proches du métal pour les cas d'utilisation courants dans les applications réelles, informant ainsi les développeurs que les normes web peuvent désormais rivaliser avec les grandes bibliothèques établies.
Les tutoriels de Mithril.js couvrent également beaucoup plus de terrain que ceux de Vue : le tutoriel de Vue se termine par une simple liste de tâches locale, après avoir parcouru plusieurs pages pour couvrir sa grande API de base. Le guide de 10 minutes de Mithril.js couvre la majorité de son API et aborde même les aspects clés des applications réelles, tels que la récupération de données à partir d'un serveur et le routage. Si cela ne suffit pas, il existe également un tutoriel plus long et plus approfondi.