Il y a environ un an, l' article manifeste de Nikita Prokopov sur la déception des logiciels a été publié. À en juger par les commentaires positifs, les développeurs ne sont pas indifférents à la qualité de leurs produits. Peut-être qu'il est temps de commencer à jouer?
Dans cet article, je veux parler de mon développement, qui, à mon avis, peut résoudre les principaux problèmes de performances du Web moderne et rendre l'utilisateur un peu plus heureux. Les problèmes sont: un code JS lourd, un délai de démarrage de la page (TTI) élevé, une consommation de mémoire et de processeur élevée.
Avant de continuer à lire, suivez le lien . Essayez de jouer à quelques jeux. Jouez de préférence depuis le bureau.
Un peu d'histoire
Dès le début, le navigateur Web a été conçu comme un client léger pour les serveurs Web. Le navigateur affiche les pages hypertextes qu'il a reçues du serveur. Simple et élégant. Comme cela arrive souvent, une belle idée est confrontée à la réalité, et après quelques années, les fabricants de navigateurs ont ajouté la prise en charge du langage de script. Au début, il ne servait que de décoration, et jusqu'au milieu des années 2000, il était considéré comme une bonne forme pour faire fonctionner les pages Web sans le support de JS.
Une approche moderne du développement de sites Web est le résultat du développement des exigences d'interactivité de l'interface utilisateur. Les tâches visant à améliorer l'interactivité incombaient aux codeurs. Ceux-ci n'avaient souvent pas les compétences et l'autorité nécessaires pour développer une solution «de bout en bout». Les concepteurs de mise en page ont appris à écrire JS et sont devenus front-end. La logique a progressivement commencé à circuler du serveur vers le client. Il est pratique pour le front-runner d'écrire pour le navigateur, et le back-end est pratique de ne pas penser à l'utilisateur (donnez-moi mon JSON, puis au moins l'herbe ne pousse pas). Il y a tout juste deux ans, l'intérêt pour l'architecture sans serveur a fortement augmenté, et il a été suggéré que les applications JS fonctionneraient directement avec la base de données et les bus d'événements.
À l'heure actuelle, le "site Web sphérique dans le vide" est une application JS complexe et un simple serveur API avec lequel il communique. La logique principale s'exécute sur un client lourd, le côté serveur dégénère en une simple couche de la base de données.
La nécessité de garder la logique sur le client crée des problèmes. Si le service «décolle» et commence à gagner de l'argent, alors, en termes de productivité, il ne fera qu'empirer. Les exigences vont changer. L'équipe de développement va changer. Il y aura de plus en plus de nouveau code et l'ancien code ne sera pas nettoyé. La page va gonfler des dépendances, elle chargera du JSON sur le but dont personne ne se souvient, mais ça fait peur à supprimer, tout à coup quelque chose se casse. Des tâches d'arrière-plan SetInterval apparaîtront, chacune étant exécutée pendant plusieurs millisecondes par seconde, ce qui, après un certain temps, entraînera des freins et réchauffera l' iPad de l'infortuné au point qu'il pourra y faire frire des œufs frits. Cela se termine par le fait que le front-end brûlé viendra au gestionnaire avec une proposition de tout réécrire à partir de zéro sur un nouveau cadre. Le gestionnaire refusera et le frontal commencera à utiliser deux cadres ensemble.
Comment fonctionne Korolev
Et si nous revenons au point du rapport? Le moment où quelqu'un a eu l'idée de mettre à jour le contenu sans recharger la page, et l'inévitabilité historique a donné naissance à AJAX? Que faire si vous laissez tout sur le serveur et faites un client léger? Les meilleurs sites font le pré-rendu des pages du serveur (SSR) afin que l'utilisateur voit l'interface avant le chargement et le démarrage de JS. Vous pouvez aller plus loin et ne laisser au client que le code responsable du traitement des E / S, compte tenu des exigences actuelles d'interactivité. Des réflexions à ce sujet ont débordé sur le projet Korolev .
Comment ça marche côté client? L'utilisateur vient sur la page. Le serveur fournit le code HTML généré et un petit script (~ 6 Ko sans compression) qui se connecte au serveur via une socket web. Lorsqu'un utilisateur déclenche un événement (par exemple, un clic), le script l'envoie au serveur. Après traitement de l'événement, le serveur génère une liste de commandes de la forme "ajoutez un nouveau <div>
là", "ajoutez une classe à tel élément", "supprimez tel ou tel élément". Le client applique la liste de commandes au DOM. En tant que tel, le travail avec HTML ne se produit pas - le script fonctionne directement avec le DOM, alors ne vous inquiétez pas que le contenu du formulaire ou la position du défilement sera réinitialisé.
Que se passe-t-il sur le serveur? Lorsqu'une demande de page provient du navigateur, Korolev crée une nouvelle session. Pour la session, l'état initial est créé, qui est stocké dans le cache. Le HTML est généré à partir de cet état, qui est donné au client en réponse à la demande. De plus, le serveur enregistre le "DOM virtuel" dans la session. Après avoir demandé la page, le serveur accepte la demande d'ouverture du socket Web. Korolev associe une socket web ouverte à une session. Chaque événement provenant du client peut changer l'état associé à la session. Chaque changement d'état conduit à un appel à la fonction de render
, qui forme un nouveau "DOM virtuel", qui est comparé à l'ancienne version. La comparaison aboutit à une liste de commandes à envoyer au client.
Que se passe-t-il dans le code et la tête du développeur? Ce qui précède pourrait vous rappeler React, à la différence près que tout fonctionne sur le serveur. En termes d'approche de développement, nous avons également quelque chose de similaire. Par conséquent, si vous avez travaillé avec React ou un autre "DOM virtuel", l'approche de Queen vous sera familière. Si vous n'êtes pas familier avec React, alors imaginez que vous avez des données que vous insérez dans le modèle. Imaginez que selon le modèle, les gestionnaires d'événements sont dispersés et peuvent modifier les données (mais pas le DOM). Vous changez les données, la page se change. Korolev lui-même trouve comment changer le DOM.
Performances
Il y a deux questions fréquentes à propos de Korolev: «et si les retards sont importants» et «cela ne chargera-t-il pas mon serveur». Les deux questions sont très raisonnables. Le programmeur frontal a l'habitude de faire exécuter son programme sur la machine locale de l'utilisateur. Cela signifie que les modifications apportées seront appliquées dès que la machine JS aura terminé d'exécuter le code et que le navigateur commencera le rendu. J'ai montré spécifiquement un exemple d'utilisation "à vitesse maximale" au tout début. Vous ne pouviez observer le retard que si vous veniez de l'autre côté du globe (les serveurs sont situés à Moscou) ou si vous vous êtes assis sur Internet via GPRS. Eh bien, ou mon serveur virtuel pathétique avec un cœur et 1 Go de RAM ne pouvait pas supporter l'effet habr.
La question de la charge du serveur est généralement posée par les beckenders. Le moteur de sortie de changement fonctionne très rapidement: ~ 10 mille conclusions par seconde pour deux arbres arbitraires de 500 nœuds sur le macbook junior de 2013. Le rendu statique donne également un assez bon résultat: jusqu'à 1 million de pages par seconde. Chaque "DOM virtuel" est stocké et traité sous une forme sérialisée spéciale et prend 128 Ko pour une page Web moyenne. Le processus de sortie est spécialement optimisé et n'a pas de surcharge pour la mémoire et le GC.
Quant à la vitesse de développement, Korolev offre ici de grands avantages. Pas besoin d'écrire une couche supplémentaire entre la base de données et le serveur. Pas besoin de négocier un protocole entre le client et le serveur. Pas besoin de vous soucier de la modularité du front-end - le poids JS sur le client restera toujours le même. Pas besoin de faire de logique supplémentaire pour les événements du serveur: acceptez simplement le message de la file d'attente et changez l'état de la session, Korolev restituera et livrera.
Prix
Vous devez payer pour les avantages. Il faudra abandonner certaines habitudes et en acquérir de nouvelles. Par exemple, vous devez abandonner les animations JS et vous contenter des animations CSS. Vous devrez apprendre à rendre l'infrastructure initialement géo-distribuée si vous souhaitez servir des utilisateurs de différents pays avec une haute qualité. Je dois abandonner JS et aller à Scala.
J'ai un peu honte (en fait pas) d'avoir trompé le lecteur et de ne pas dire immédiatement que Korolev a été écrit en Scala. Pourriez-vous lire jusqu'à ce point si j'en parlais immédiatement? En parlant de la Reine, je dois surmonter deux stéréotypes. Le premier est dû au fait que le rendu du serveur est perçu comme quelque chose de lent, pas interactif. La seconde est liée au fait que Scala est quelque chose de compliqué. Et le premier et le deuxième stéréotype n'ont rien à voir avec la réalité. De plus, la programmation dans le style React sur Scala est plus pratique que sur JS. Le JS moderne se tourne vers la programmation fonctionnelle, Scala le sort de la boîte. Par exemple, tout objet dans Scala a une méthode copy()
qui vous permet de copier un objet en modifiant certains champs. Les collections immuables sont intégrées dans la bibliothèque standard de Scala.
Conclusion
Korolev a été développé pendant trois ans par plusieurs développeurs et de nombreux problèmes "enfants" y sont résolus. Le projet est bien documenté, toutes les fonctionnalités sont couvertes d'exemples. Je propose de commencer la mise en place de la Reine avec de petits services indépendants. J'espère que Korolev contribuera à rendre les programmes moins décevants.
Lien vers le projet sur github