cover image
< Accueil
Web

Intégrer une bibliothèque Go dans une page Web JavaScript avec WebAssembly

Avec WebAssembly, vous pouvez intégrer différents langages de programmation. Cela ouvre de nouvelles possibilités d'utiliser de grandes bibliothèques écrites dans un langage sur une plateforme différente. Dans cet article, je veux montrer comment intégrer une bibliothèque Go pour la tokenisation de phrases dans une page web JavaScript. Normalement, il n'est pas possible d'exécuter du code Go dans un navigateur web, mais avec la technologie WebAssembly, c'est possible.

WebAssembly

WebAssembly est une spécification du W3C qui définit un format binaire et textuel pour les programmes exécutables qui peuvent être exécutés dans le navigateur, mais aussi de manière autonome. Les programmes WebAssembly s'exécutent dans une machine virtuelle (VM) basée sur une pile. Tirant son nom du langage de programmation Assembly, qui est très proche du matériel réel, WebAssembly définit un langage plus indépendant de l'appareil que l'Assembly, mais qui reste de très bas niveau.

Au moment de la rédaction de cet article, WebAssembly est pris en charge par 97,11 % de tous les navigateurs mondiaux (caniuse.com). Il existe plusieurs extensions à la spécification WebAssembly du W3C qui ont différents niveaux de support parmi les navigateurs.

Bibliothèque Go

Sentences est une bibliothèque Go pour la tokenisation de phrases écrite par Eric Bower et publiée en tant que source ouverte sur GitHub. Comme il n'est pas possible d'exécuter du code Go dans le navigateur de manière native, mais seulement du JavaScript, il est possible d'utiliser WebAssembly pour intégrer la bibliothèque dans un site web.

Exposer la bibliothèque Sentences à JavaScript

Vous pouvez intégrer la bibliothèque Sentences en écrivant une application wrapper Go qui exploite le paquetage syscall/js de Go. Il fait partie de la bibliothèque standard de Go. Notez qu'au moment de l'écriture de cet article, ce paquet est étiqueté comme "expérimental".

Plus précisément, nous utiliserons la fonction js.FuncOf. Voici le code source complet de l'application Go :

package main

import (
	"fmt"
	"strings"
	"syscall/js"

	"github.com/neurosnap/sentences/english"
)

func sentenceWrapper() js.Func {
	sentenceFunc := js.FuncOf(func(this js.Value, args []js.Value) any {
		if len(args) != 1 {
			return "Invalid no of arguments passed"
		}
		inputSentence := args[0].String()
		fmt.Printf("input %s\n", inputSentence)
		tokenizer, err := english.NewSentenceTokenizer(nil)
		if err != nil {
			panic(err)
		}

		sentences := tokenizer.Tokenize(inputSentence)
		for _, s := range sentences {
			fmt.Println(s.Text)
		}

		var sentenceTexts []string
		for _, s := range sentences {
			trimmedText := strings.TrimSpace(s.Text)
			sentenceTexts = append(sentenceTexts, trimmedText)
		}

		allSentences := strings.Join(sentenceTexts, "\n") // Join all sentences separated by a space
		return allSentences

	})
	return sentenceFunc
}

func main() {
	fmt.Println("Go Web Assembly")
	js.Global().Set("tokenizeSentence", sentenceWrapper())
	<-make(chan struct{})
}

Vous voyez que maintenant la fonction sentenceWrapper est exposée comme la fonction tokenizeSentence en JavaScript. Elle attend comme argument une chaîne à tokeniser et renvoie la chaîne tokenisée. L'intégration réelle avec la bibliothèque sentences se fait à l'intérieur de la fonction passée à js.FuncOf.

Compiler le Wrapper

Vous compilez l'application en WebAssembly en utilisant la commande Go build suivante :

GOOS=js GOARCH=wasm go build -o main.wasm 

Si tout s'est bien passé, vous devriez trouver le fichier main.wasm en sortie dans votre dossier. C'est le binaire WebAssembly qui sera chargé dans l'application JavaScript.

Intégrer la bibliothèque WebAssembly Go dans le site web

Afin de charger le fichier main.wasm dans la page web, vous avez besoin du code suivant :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <script src="wasm_exec.js"></script>
    <script>
      const go = new Go();
      WebAssembly.instantiateStreaming(
        fetch("./main.wasm"),
        go.importObject
      ).then((result) => {
        go.run(result.instance);
      });
    </script>
  </head>
  <body>
    <textarea id="sentenceinput" name="jsoninput" cols="80" rows="20"></textarea>
    <input
      id="button"
      type="submit"
      name="button"
      value="tokenize"
      onclick="tokenize(sentenceinput.value)"
    />
    <textarea id="jsonoutput" name="jsonoutput" cols="80" rows="20"></textarea>
  </body>
  <script>
    var tokenize = function (input) {
      jsonoutput.value = tokenizeSentence(input);
    };
  </script>
</html>

Lorsque vous exécutez cette page web dans le navigateur, vous avez également besoin du fichier JavaScript utilitaire wasm_exec.js dans le répertoire courant. Vous pouvez obtenir ce fichier à partir de :

cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .

Comme vous pouvez le voir dans le code JavaScript, la fonction exposée tokenizeSentence() est appelée à partir de JavaScript lorsque l'on clique sur le bouton "tokenize". Le contenu du champ de saisie est utilisé comme argument de la fonction et la valeur de retour est alors écrite dans le champ de texte à droite. Notez que vous devez exécuter un serveur web afin d'exécuter la page web dans votre navigateur. Vous pouvez utiliser ce code pour construire un serveur web en Go :

server/server.go

package main

import (
	"fmt"
	"net/http"
)

func main() {
	err := http.ListenAndServe(":9090", http.FileServer(http.Dir("../")))
	if err != nil {
		fmt.Println("Failed to start server", err)
		return
	}
}

Après avoir démarré le serveur web, vous pouvez accéder à la page dans votre navigateur sous : http://localhost:9090.

Merci à Naveen Ramanathan de golangbot.com pour son inspiration pour cet article.

Conclusion

Comme toujours, j'espère que cet article vous a aidé d'une manière ou d'une autre à rester curieux. WebAssembly est une technologie qui a un grand potentiel pour intégrer les différents éco-systèmes de langage entre eux.

Références

Photo par Venti Views sur Unsplash

Publié le

6 juil. 2024


Creative Commons License

Cette œuvre est soumise à une licence Creative Commons Attribution 4.0 International License.
Thomas Derflinger

Écrit par Thomas Derflinger

Je suis un entrepreneur visionnaire et un développeur de logiciels. Dans ce blog, j'écris principalement sur la programmation web et des sujets connexes comme l'IdO.