Maison développement back-end Golang Go-DOM - étape majeure

Go-DOM - étape majeure

Nov 22, 2024 am 02:44 AM

Go-DOM -  major milestone

Après un peu moins de 2 semaines de travail ; J'ai enfin atteint la première étape majeure pour Go-DOM.

Maintenant, le navigateur va télécharger et exécuter du JavaScript à distance lors de la construction de l'arborescence DOM.

Une brève histoire

Le projet est parti d'une idée folle ; sachant que Go et HTMX sont une pile qui gagne en popularité ;

Go dispose déjà de tous les outils dont vous avez besoin pour tester le rendu pur côté serveur. Mais lors de l'ajout d'une bibliothèque comme HTMX, le comportement de l'application est le résultat d'une chorégraphie entre le DOM initial ; les attributs sur les éléments interactifs ; les points de terminaison HTTP atteints et le contenu fourni par ces points de terminaison ; les en-têtes et le corps de la réponse. Pour vérifier le comportement du point de vue de l'utilisateur, vous avez besoin d'un navigateur ; ou du moins un harnais de test qui se comporte... un peu comme un navigateur.1

La recherche de "navigateur sans tête en go" n'a conduit qu'à des résultats suggérant d'utiliser un vrai navigateur en mode sans tête. Cette combinaison qui entraîne d’énormes frais généraux ; décourageant la boucle TDD rapide et efficace. S'appuyer sur un vrai navigateur vous ralentira au lieu de vous accélérera.2

L'idée est donc née ; écrire un navigateur sans tête en Go pur comme outil de test pour les applications Web ;

La première incertitude à résoudre était l'analyse du HTML ; ainsi que l'exécution du script. J'y suis parvenu assez rapidement ; dans les 2 jours pour résoudre ces deux problèmes. J'avais un analyseur HTML très rudimentaire ; ainsi que j'avais intégré la v8 dans la base de code3 et rendu les objets Go accessibles au code JavaScript.

L'analyseur HTML a ensuite été supprimé, car go x/net/html implémente déjà un analyseur HTML ; traitant de toutes les bizarreries de l'analyse HTML. Analyser un document bien formé n'est pas un problème très difficile à résoudre. Il s'agit de gérer gracieusement le HTML mal formé là où cela devient délicat.

Après un certain temps, j'ai également réussi à faire en sorte que l'exécution du script inline s'exécute au bon moment ; c'est-à-dire que le script s'exécute lorsque l'élément est réellement connecté au DOM, et non après que le HTML complet a été analysé.

Travailler avec des requêtes HTTP

Après avoir pu traiter un document HTML avec un script en ligne ; l'étape suivante consistait à télécharger les scripts à partir des sources. Cela nécessitait d'intégrer une couche HTTP ; de telle sorte que le navigateur récupère lui-même le contenu ; plutôt que d'être nourri de contenu.

Le http.Client vous permet également de contrôler la couche de transport réelle à l'aide de l'interface http.RoundTripper. Normalement, vous démarrez un serveur ; qui écoutera les requêtes sur un port TCP. Dans ce contexte, TCP sert de couche de transport ; mais n'est en soi pas pertinent pour le traitement des requêtes HTTP. En raison de la simplicité de la pile HTTP standard dans Go ; un serveur HTTP entier est représenté par une seule fonction, func Handle(http.ResponseWriter, *http.Request).

Le navigateur sans tête peut contourner complètement la surcharge de la pile TCP et appeler cette fonction directement à l'aide d'un RoundTripper personnalisé.

Le navigateur peut désormais effectuer des requêtes HTTP, mais le code du navigateur lui-même ignore le fait que la couche HTTP est contournée. Et avec cela est venue la possibilité de télécharger le script pendant l'analyse DOM.

Exemple de code

Explorons un test simple, tel qu'il apparaît maintenant dans la base de code (le code utilise Ginkgo et Gomega, une combinaison quelque peu négligée à mon humble avis)

Tout d'abord, le test crée un gestionnaire HTTP simple qui dessert deux points de terminaison, /index.html et /js/script.js.

It("Should download and execute script from script tags", func() {
  // Setup a server with test content
  server := http.NewServeMux()
  server.HandleFunc(
    "GET /index.html",
    func(res http.ResponseWriter, req *http.Request) {
      res.Write(
        []byte(
          `<html><head><script src="/js/script.js"></script></head><body>Hello, World!</body>`,
        ),
      )
    },
  )
  server.HandleFunc(
    "GET /js/script.js",
    func(res http.ResponseWriter, req *http.Request) {
      res.Header().Add("Content-Type", "text/javascript")
      res.Write([]byte(`var scriptLoaded = true`))
    },
  )

  // ...
Copier après la connexion

L'intention ici est simplement de vérifier que le script est exécuté. Pour ce faire, le script produit un effet secondaire observable : il définit une valeur dans une portée globale.

Pour vérifier que le script a été exécuté, il suffit d'examiner la portée globale, ce qui se fait en exécutant du JavaScript ad hoc à partir du test lui-même ; vérifier le résultat de l'expression.

Le code pour créer le navigateur, charger le fichier d'index et vérifier l'effet secondaire observé

browser := ctx.NewBrowserFromHandler(server)
Expect(browser.OpenWindow("/index.html")).Error().ToNot(HaveOccurred())
Expect(ctx.RunTestScript("window.scriptLoaded")).To(BeTrue())
Copier après la connexion

L'exécution des tests est également assez rapide. La partie de la suite de tests impliquant l'exécution de JavaScript comprend actuellement 32 tests exécutés en 23 millisecondes.

Prochaine étape, intégrer HTMX.

Comme le projet a été initialement conçu en essayant de vérifier une application HTMX, un prochain objectif raisonnable est de prendre en charge uniquement ce cas. Une application HTMX simple avec un bouton et un compteur, qui augmente lorsque le bouton est enfoncé.

  • L'implémentation d'AnXMLHttpRequest doit être en place. Des travaux sont en cours pour cela.
  • Un XPathEvaluator. Je crois que cela peut être poly-rempli pour commencer.
  • Propagation des événements. Seuls les événements DOMContentLoaded et load sont émis pour le moment. Les éléments doivent prendre en charge davantage d'événements ; comme cliquer ; ainsi que les méthodes pour les déclencher.
    • Cela peut également nécessiter une capture et un bouillonnement appropriés des événements.

Et puis ...

Ensuite, une interaction utilisateur plus avancée ; gestion appropriée du formulaire, par exemple, ligne de saisie (par exemple, appuyer sur enter dans un champ pour soumettre le formulaire. Cela implique généralement également une sorte de redirection d'URL ; ce qui entraîne le besoin d'un objet d'historique, etc. .

Intégration de sites externes

Avec la possibilité de contrôler la couche de transport ; nous pouvons proposer des tests dotés de capacités uniques ; nous pouvons simuler des sites externes dont dépendrait le système au moment de l'exécution. Par exemple, pour un nom d'hôte donné, le test pourrait fournir un autre gestionnaire HTTP Go simulant le comportement.

L'exemple le plus évident est l'utilisation de fournisseurs d'identité externes. Le test pourrait simuler le comportement d'un flux de connexion ; ne pas avoir à vous forcer à créer des comptes factices dans un système externe, à avoir des échecs de tests en raison de pannes dans un système externe, ou simplement à être incapable d'automatiser le processus du tout à cause de 2FA ou d'un Captcha introduit par le fournisseur d'identité.

Un autre cas d'utilisation est l'utilisation de bibliothèques riches en API, comme les bibliothèques de cartes, qui entraînent un coût d'utilisation. Maquette du site externe pour ne pas recevoir de facture supplémentaire pour l'exécution de votre suite de tests.

Convivialité plutôt que compatibilité

Créer une implémentation 100 % conforme aux normes Whatwg est tout un effort ; Je n'ai pas entièrement compris la portée jusqu'à ce que je commence à lire certaines parties des spécifications Whatwg. Le but est de créer un outil d'aide à l'écriture de tests pour les applications web. La compatibilité totale est un objectif à long terme ; mais jusqu'à ce que le projet ait atteint un certain niveau d'utilisabilité, vais-je commencer à combler les trous.

Pour cette raison ; les fonctionnalités qui sont plus susceptibles d’être utilisées dans des applications réelles sont plus susceptibles d’être prioritaires. Une demande de fonctionnalité pointant vers un test réel donnant un résultat erroné sera probablement priorisée. Une demande de fonctionnalité pour la mise en œuvre d'une norme spécifique est susceptible d'être rejetée.

Faites passer le mot

Je pense que cela peut être un outil très utile pour de nombreux développeurs, donc si vous lisez ceci, faites savoir à vos collègues qu'il existe. Il s'agit jusqu'à présent d'un projet de temps libre, dont j'ai beaucoup à faire en ce moment ; mais ce ne sera pas le cas pour toujours.

Si vous voulez voir ça en live, faites passer le message...

Peut-être pourriez-vous même parrainer ceci ? Avez-vous une grande entreprise qui crée des applications Web dans Go ? N'hésitez pas à me contacter.

Retrouvez le projet ici : https://github.com/stroiman/go-dom


  1. Félicitations si vous avez réussi à capter l'hommage à une pièce radiophonique populaire de la BBC. ↩

  2. Ceci est basé sur une expérience personnelle. Faire correctement le TDD vous accélérera en raison du cycle de rétroaction rapide. La surcharge d'un vrai navigateur a tendance à vous obliger à écrire des tests après le code de production ; perdant le bénéfice de la boucle de rétroaction qu'une suite de tests rapides vous offre. ↩

  3. Les bases avaient déjà été posées par le projet v8go. Cependant; Toutes les fonctionnalités de la v8 ne sont pas exposées au code Go ; y compris les fonctionnalités nécessaires à l’intégration d’objets natifs. J'ai pu les ajouter dans un fork séparé ; qui est toujours en cours. ↩

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!

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

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

<🎜>: Bubble Gum Simulator Infinity - Comment obtenir et utiliser les clés royales
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
<🎜>: Grow A Garden - Guide de mutation complet
3 Il y a quelques semaines By DDD
Nordhold: Système de fusion, expliqué
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Comment déverrouiller le grappin
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel Java
1673
14
Tutoriel PHP
1278
29
Tutoriel C#
1257
24
Golang vs Python: performance et évolutivité Golang vs Python: performance et évolutivité Apr 19, 2025 am 12:18 AM

Golang est meilleur que Python en termes de performances et d'évolutivité. 1) Les caractéristiques de type compilation de Golang et le modèle de concurrence efficace le font bien fonctionner dans des scénarios de concurrence élevés. 2) Python, en tant que langue interprétée, s'exécute lentement, mais peut optimiser les performances via des outils tels que Cython.

Golang et C: concurrence vs vitesse brute Golang et C: concurrence vs vitesse brute Apr 21, 2025 am 12:16 AM

Golang est meilleur que C en concurrence, tandis que C est meilleur que Golang en vitesse brute. 1) Golang obtient une concurrence efficace par le goroutine et le canal, ce qui convient à la gestion d'un grand nombre de tâches simultanées. 2) C Grâce à l'optimisation du compilateur et à la bibliothèque standard, il offre des performances élevées près du matériel, adaptées aux applications qui nécessitent une optimisation extrême.

Partage avec Go: un guide du débutant Partage avec Go: un guide du débutant Apr 26, 2025 am 12:21 AM

GOISIDEALFORBEGINNERNERS et combinant pour pourcloudandNetWorkServicesDuetOtssimplicity, Efficiency, andCurrencyFeatures.1) InstallgofromTheofficialwebsiteandverifywith'goversion'..2)

Golang vs C: Performance et comparaison de la vitesse Golang vs C: Performance et comparaison de la vitesse Apr 21, 2025 am 12:13 AM

Golang convient au développement rapide et aux scénarios simultanés, et C convient aux scénarios où des performances extrêmes et un contrôle de bas niveau sont nécessaires. 1) Golang améliore les performances grâce à des mécanismes de collecte et de concurrence des ordures, et convient au développement de services Web à haute concurrence. 2) C réalise les performances ultimes grâce à la gestion manuelle de la mémoire et à l'optimisation du compilateur, et convient au développement du système intégré.

Golang vs Python: différences et similitudes clés Golang vs Python: différences et similitudes clés Apr 17, 2025 am 12:15 AM

Golang et Python ont chacun leurs propres avantages: Golang convient aux performances élevées et à la programmation simultanée, tandis que Python convient à la science des données et au développement Web. Golang est connu pour son modèle de concurrence et ses performances efficaces, tandis que Python est connu pour sa syntaxe concise et son écosystème de bibliothèque riche.

Golang et C: les compromis en performance Golang et C: les compromis en performance Apr 17, 2025 am 12:18 AM

Les différences de performance entre Golang et C se reflètent principalement dans la gestion de la mémoire, l'optimisation de la compilation et l'efficacité du temps d'exécution. 1) Le mécanisme de collecte des ordures de Golang est pratique mais peut affecter les performances, 2) la gestion manuelle de C et l'optimisation du compilateur sont plus efficaces dans l'informatique récursive.

La course de performance: Golang vs C La course de performance: Golang vs C Apr 16, 2025 am 12:07 AM

Golang et C ont chacun leurs propres avantages dans les compétitions de performance: 1) Golang convient à une concurrence élevée et à un développement rapide, et 2) C fournit des performances plus élevées et un contrôle fin. La sélection doit être basée sur les exigences du projet et la pile de technologie d'équipe.

Golang contre Python: les avantages et les inconvénients Golang contre Python: les avantages et les inconvénients Apr 21, 2025 am 12:17 AM

GolangisidealforBuildingsCalableSystemsDuetoitSefficiency and Concurrency, tandis que les Implicites de l'Indrecosystem et le Golang'sDesignenCourageSlecElNCORES

See all articles