Conception d'un framework Web Pure Python

DDD
Libérer: 2024-09-19 06:21:33
original
641 Les gens l'ont consulté

Le développement Web est l'un des cas d'utilisation les plus populaires en matière de programmation. Python est l'un des langages de programmation les plus populaires au monde. Alors pourquoi ne pouvons-nous pas créer des applications Web en Python ?

Créer une interface utilisateur devrait être simple, mais même si vous avez d'excellents ingénieurs dans votre équipe, les frais généraux liés à l'apprentissage d'un nouveau langage et d'outils constituaient un énorme obstacle. Souvent, créer une interface utilisateur peut être plus difficile que le travail réel que l'on effectue !

TLDR

Sous le capot, les applications Reflex se compilent en une application frontend React et une application backend FastAPI. Seule l'interface utilisateur est compilée en Javascript ; toute la logique de l'application et la gestion de l'état restent en Python et sont exécutées sur le serveur. Reflex utilise WebSockets pour envoyer des événements du frontend au backend et pour envoyer des mises à jour d'état du backend au frontend.

Solutions Python existantes

Il existait déjà plusieurs façons de créer des applications en Python, mais aucune ne répondait à nos besoins.

D'une part, il existe des frameworks comme Django et Flask qui sont parfaits pour créer des applications Web de qualité production. Mais ils ne gèrent que le backend - vous devez toujours utiliser JavaScript et un framework frontend, ainsi qu'écrire beaucoup de code passe-partout pour connecter le frontend et le backend.

D'un autre côté, les bibliothèques Python pures comme Dash et Streamlit peuvent être idéales pour les petits projets, mais elles sont limitées à un cas d'utilisation spécifique et n'ont pas les fonctionnalités et les performances nécessaires pour créer une application Web complète. À mesure que votre application grandit en fonctionnalités et en complexité, vous risquez de vous retrouver aux limites du framework, auquel cas vous devrez soit limiter votre idée pour l'adapter au framework, soit abandonner votre projet et le reconstruire à l'aide d'un "vrai framework web".

Nous souhaitons combler cette lacune en créant un cadre simple et intuitif pour démarrer, tout en restant flexible et puissant pour prendre en charge n'importe quelle application.

Objectifs du réflexe

  • Pure Python : utilisez un seul langage pour tout.
  • Facile à démarrer : Construisez vos idées facilement sans avoir besoin d'expérience en développement Web.
  • Flexibilité totale : les applications Web doivent correspondre à la personnalisation et aux performances des frameworks Web traditionnels.
  • Batteries incluses : Gérez le full-stack du frontend au backend jusqu'au déploiement.

Voyons maintenant comment nous avons construit Reflex pour atteindre ces objectifs.

L'architecture réflexe

Les applications Web full-stack sont composées d'un frontend et d'un backend. Le frontend est l'interface utilisateur et constitue une page Web qui s'exécute sur le navigateur de l'utilisateur. Le backend gère la logique et la gestion de l'état (comme les bases de données et les API) et est exécuté sur un serveur.

Dans le développement Web traditionnel, il s'agit généralement de deux applications distinctes et sont souvent écrites dans des frameworks ou des langages différents. Par exemple, vous pouvez combiner un backend Flask avec un frontend React. Avec cette approche, vous devez gérer deux applications distinctes et finir par écrire beaucoup de code passe-partout pour connecter le frontend et le backend.

Nous souhaitons simplifier ce processus dans Reflex en définissant à la fois le frontend et le backend dans une seule base de code, tout en utilisant Python pour tout. Les développeurs ne devraient se soucier que de la logique de leur application et non des détails de mise en œuvre de bas niveau.

Designing a Pure Python Web Framework

L'extrémité avant

Nous voulons que les applications Reflex ressemblent à une application Web traditionnelle pour l'utilisateur final, tout en restant faciles à créer et à maintenir pour le développeur. Pour ce faire, nous nous sommes appuyés sur des technologies Web matures et populaires.

Lorsque vous exécutez votre application par Reflex, Reflex compile le frontend en une application Next.js d'une seule page et la sert sur un port (3000 par défaut) auquel vous pouvez accéder dans votre navigateur.

Le travail du frontend consiste à refléter l'état de l'application et à envoyer des événements au backend lorsque l'utilisateur interagit avec l'interface utilisateur. Aucune logique réelle n'est exécutée sur le frontend.

Composants

Les interfaces Reflex sont construites à l'aide de composants qui peuvent être composés ensemble pour créer des interfaces utilisateur complexes. Au lieu d'utiliser un langage de template mélangeant HTML et Python, nous utilisons simplement les fonctions Python pour définir l'interface utilisateur.

Sous le capot, les composants se compilent en composants React.

Beaucoup de nos composants principaux sont basés sur Radix, une bibliothèque de composants React populaire. Nous avons également de nombreux autres composants pour les graphiques, les tables de données et bien plus encore.

Nous avons choisi React car c'est une bibliothèque populaire avec un énorme écosystème. Notre objectif n'est pas de recréer l'écosystème web, mais de le rendre accessible aux développeurs Python.

Cela permet également à nos utilisateurs d'apporter leurs propres composants si nous n'avons pas de composant dont ils ont besoin. Les utilisateurs peuvent envelopper leurs propres composants React, puis les publier pour que d'autres puissent les utiliser. Au fil du temps, nous développerons notre écosystème de composants tiers afin que les utilisateurs puissent facilement trouver et utiliser les composants que d'autres ont créés.

Stylisme

Nous voulions nous assurer que les applications Reflex soient belles dès leur sortie de la boîte, tout en donnant aux développeurs un contrôle total sur l'apparence de leur application.

Nous disposons d'un système de thèmes de base qui vous permet de définir des options de style de haut niveau telles que le mode sombre et la couleur d'accentuation dans votre application pour lui donner une apparence et une convivialité unifiées.

Au-delà de cela, les composants Reflex peuvent être stylisés en utilisant toute la puissance du CSS. Nous exploitons la bibliothèque Emotion pour autoriser le style "CSS-in-Python", afin que vous puissiez transmettre n'importe quel accessoire CSS comme argument de mot-clé à un composant. Cela inclut des accessoires réactifs en transmettant une liste de valeurs.

Back-end

Dans Reflex, seul le frontend est compilé en Javascript et s'exécute sur le navigateur de l'utilisateur, tandis que tout l'état et la logique restent en Python et sont exécutés sur le serveur. Lorsque vous exécutez Reflex, nous démarrons un serveur FastAPI (par défaut sur le port 8000) auquel le frontend se connecte via un websocket.

Tous les états et la logique sont définis dans une classe State.

L'état est composé de vars et de gestionnaires d'événements.

Les variables sont toutes les valeurs de votre application qui peuvent changer au fil du temps. Ils sont définis en tant qu'attributs de classe sur votre classe State et peuvent être n'importe quel type Python pouvant être sérialisé en JSON.

Les gestionnaires d'événements sont des méthodes de votre classe State qui sont appelées lorsque l'utilisateur interagit avec l'interface utilisateur. C'est le seul moyen de modifier les variables dans Reflex et peuvent être appelés en réponse aux actions de l'utilisateur, comme cliquer sur un bouton ou taper dans une zone de texte.

Étant donné que les gestionnaires d'événements sont exécutés sur le backend, vous pouvez utiliser n'importe quelle bibliothèque Python en leur sein.

Designing a Pure Python Web Framework

Traitement des événements

Normalement, lors de l'écriture d'applications Web, vous devez écrire beaucoup de code passe-partout pour connecter le frontend et le backend. Avec Reflex, vous n'avez pas à vous soucier de cela : nous gérons pour vous la communication entre le frontend et le backend. Les développeurs n'ont qu'à écrire la logique de leur gestionnaire d'événements, et lorsque les variables sont mises à jour, l'interface utilisateur est automatiquement mise à jour.

Déclencheurs d'événements

L'utilisateur peut interagir avec l'interface utilisateur de plusieurs manières, par exemple en cliquant sur un bouton, en tapant dans une zone de texte ou en survolant un élément. Dans Reflex, nous appelons cela des déclencheurs d'événements.

File d'attente des événements

Sur le frontend, nous maintenons une file d'attente de tous les événements en attente. Un événement est constitué de trois données majeures :

  • jeton client : Chaque client (onglet du navigateur) possède un jeton unique pour l'identifier. Cela permet au backend de savoir quel état mettre à jour.
  • gestionnaire d'événements : le gestionnaire d'événements à exécuter sur l'état.
  • arguments : Les arguments à transmettre au gestionnaire d'événements.

Lorsqu'un événement est déclenché, il est ajouté à la file d'attente.
Nous avons un indicateur de traitement pour garantir qu'un seul événement est traité à la fois. Cela garantit que l'état est toujours cohérent et qu'il n'y a pas de conditions de concurrence avec deux gestionnaires d'événements modifiant l'état en même temps. Il existe des exceptions à cela, comme les événements en arrière-plan qui vous permettent d'exécuter des événements en arrière-plan sans bloquer l'interface utilisateur.

Une fois que l'événement est prêt à être traité, il est envoyé au backend via une connexion WebSocket.

Gestionnaire d'État

Une fois l'événement reçu, il est traité sur le backend.

Reflex utilise un gestionnaire d'état qui maintient un mappage entre les jetons client et leur état. Par défaut, le gestionnaire d'état n'est qu'un dictionnaire en mémoire, mais il peut être étendu pour utiliser une base de données ou un cache. En production, nous utilisons Redis comme gestionnaire d'état.

Gestion des événements

Une fois que nous avons l'état de l'utilisateur, l'étape suivante consiste à exécuter le gestionnaire d'événements avec les arguments.

Mises à jour de l'état

Chaque fois qu'un gestionnaire d'événements revient (ou cède), nous enregistrons l'état dans le gestionnaire d'état et envoyons les mises à jour d'état au frontend pour mettre à jour l'interface utilisateur.

Pour maintenir les performances à mesure que votre état grandit, Reflex assure en interne le suivi des variables qui ont été mises à jour pendant le gestionnaire d'événements (vars sales).
Lorsque le gestionnaire d'événements a terminé le traitement, nous trouvons toutes les variables sales et créons une mise à jour d'état à envoyer au frontend.

Nous stockons le nouvel état dans notre gestionnaire d'état, puis envoyons la mise à jour de l'état au frontend.
Le frontend met ensuite à jour l'interface utilisateur pour refléter le nouvel état.

Conclusion

J'espère que cela donne un bon aperçu du fonctionnement de Reflex sous le capot. Nous publierons d'autres articles pour expliquer comment nous avons rendu Reflex évolutif et performant grâce à des fonctionnalités telles que le partage d'état et les optimisations du compilateur.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!