WebAssembly (avec WASI)
WebAssembly est un environnement d'exécution sécurisé, isolé et portable qui fonctionne dans les navigateurs web et en dehors de ceux-ci.
En pratique :
- Les langages (tels que JavaScript) sont compilés vers WebAssembly (fichiers
.wasm) - Les environnements d'exécution WebAssembly (tels que
wasmtimeoujco) permettent d'exécuter des binaires WebAssembly
Même si WebAssembly de base n'a pas accès au système de fichiers local ou aux sockets, WebAssembly System Interface permet de définir une plateforme sous les charges de travail WebAssembly.
Ainsi, avec WASI, WebAssembly peut manipuler des fichiers, des sockets et bien plus encore.
Information
Vous souhaitez examiner vous-même l'interface WASI ? Consultez wasi:http.
La prise en charge de WebAssembly avec WASI en JavaScript repose sur StarlingMonkey. Grâce au respect des standards web par StarlingMonkey et Hono, Hono fonctionne *sans configuration supplémentaire dans les écosystèmes WebAssembly compatibles WASI.
1. Configuration
L'écosystème JavaScript de WebAssembly fournit des outils pour commencer facilement à créer des composants WebAssembly compatibles WASI :
- StarlingMonkey est un fork de SpiderMonkey qui se compile en WebAssembly et permet de créer des composants
componentize-jstransforme les modules ES JavaScript en composants WebAssemblyjcoest un outil polyvalent qui compile des composants, génère des types et exécute les composants dans des environnements comme Node.js ou le navigateur
Information
WebAssembly possède un écosystème ouvert et open source, dont les principaux projets sont gérés principalement par la Bytecode Alliance et ses membres.
Les nouvelles fonctionnalités, signalements de problèmes, pull requests et autres contributions sont toujours les bienvenus.
Bien qu'aucun modèle de démarrage Hono pour WebAssembly ne soit encore disponible, vous pouvez créer un projet Hono WebAssembly comme tout autre projet :
mkdir my-app
cd my-app
npm init
npm i hono
npm i -D @bytecodealliance/jco @bytecodealliance/componentize-js @bytecodealliance/jco-std
npm i -D rolldownmkdir my-app
cd my-app
npm init
yarn add hono
yarn add -D @bytecodealliance/jco @bytecodealliance/componentize-js @bytecodealliance/jco-std
yarn add -D rolldownmkdir my-app
cd my-app
pnpm init --init-type module
pnpm add hono
pnpm add -D @bytecodealliance/jco @bytecodealliance/componentize-js @bytecodealliance/jco-std
pnpm add -D rolldownmkdir my-app
cd my-app
npm init
bun add hono
bun add -D @bytecodealliance/jco @bytecodealliance/componentize-js @bytecodealliance/jco-stdInformation
Pour que votre projet utilise les modules ES, assurez-vous que type vaut "module" dans package.json.
Après avoir ouvert le dossier my-app, installez les dépendances et initialisez TypeScript :
npm i
npx tsc --inityarn
yarn tsc --initpnpm i
pnpm exec tsc --initbun iUne fois le fichier de configuration TypeScript de base (tsconfig.json) créé, vérifiez le paramètre suivant :
compilerOptions.moduledéfini sur"nodenext"
Puisque componentize-js (et jco, qui le réutilise) ne prend en charge qu'un seul fichier JavaScript, il faut regrouper les fichiers ; rolldown peut créer ce fichier unique.
Vous pouvez utiliser une configuration Rolldown (rolldown.config.mjs) comme celle-ci :
import { defineConfig } from 'rolldown'
export default defineConfig({
input: 'src/component.ts',
external: /wasi:.*/,
output: {
file: 'dist/component.js',
format: 'esm',
},
})Information
Vous pouvez utiliser tout autre outil de regroupement avec lequel vous êtes plus à l'aise (rolldown, esbuild, rollup, etc.).
2. Configurer l'interface WIT et les dépendances
WebAssembly Interface Types (WIT) est un langage de définition d'interface (« IDL ») qui décrit les fonctionnalités utilisées (« imports ») et fournies (« exports ») par un composant WebAssembly.
Parmi les interfaces WIT standardisées, wasi:http gère les requêtes HTTP, entrantes comme sortantes. Puisque nous voulons créer un serveur web, notre composant doit déclarer l'utilisation de wasi:http/incoming-handler dans son monde WIT :
Configurons d'abord le monde WIT du composant dans un fichier nommé wit/component.wit :
package example:hono;
world component {
export wasi:http/incoming-handler@0.2.6;
}En termes simples, le fichier WIT ci-dessus indique que notre composant « fournit » la fonctionnalité de réception et de traitement des requêtes HTTP entrantes.
L'interface wasi:http/incoming-handler dépend d'interfaces WIT standardisées en amont (qui spécifient notamment la structure des requêtes).
Pour récupérer ces interfaces WIT tierces, maintenues par la Bytecode Alliance, nous pouvons utiliser wkg :
wkg wit fetchAprès l'exécution de wkg, vous devriez trouver dans votre dossier wit un nouveau dossier deps à côté de component.wit :
wit
├── component.wit
└── deps
├── wasi-cli-0.2.6
│ └── package.wit
├── wasi-clocks-0.2.6
│ └── package.wit
├── wasi-http-0.2.6
│ └── package.wit
├── wasi-io-0.2.6
│ └── package.wit
└── wasi-random-0.2.6
└── package.wit3. Bonjour Wasm
Pour créer un serveur HTTP dans WebAssembly, vous pouvez utiliser le projet [jco-std][jco-std], qui propose des helpers rendant l'expérience très proche de celle de Hono classique.
Implémentons notre monde component avec une application Hono de base sous forme de composant WebAssembly dans un fichier nommé src/component.ts :
import { Hono } from 'hono'
import { fire } from '@bytecodealliance/jco-std/wasi/0.2.6/http/adapters/hono/server'
const app = new Hono()
app.get('/hello', (c) => {
return c.json({ message: 'Hello from WebAssembly!' })
})
fire(app)
// Although we've called `fire()` with wasi HTTP configured for use above,
// we still need to actually export the `wasi:http/incoming-handler` interface object,
// as jco and componentize-js will be looking for the ES module export that matches the WASI interface.
export { incomingHandler } from '@bytecodealliance/jco-std/wasi/0.2.6/http/adapters/hono/server'4. Compilation
Puisque nous utilisons Rolldown, configuré pour compiler TypeScript, nous pouvons l'utiliser pour compiler et regrouper les fichiers :
npx rolldown -cyarn rolldown -cpnpm exec rolldown -cbun build --target=bun --outfile=dist/component.js ./src/component.tsInformation
L'étape de regroupement est nécessaire, car les outils de l'écosystème JavaScript de WebAssembly ne prennent actuellement en charge qu'un seul fichier JavaScript, et nous voulons inclure Hono ainsi que les bibliothèques associées.
Pour les composants aux besoins plus simples, les outils de regroupement ne sont pas nécessaires.
Pour compiler votre composant WebAssembly, utilisez jco (et indirectement componentize-js) :
npx jco componentize -w wit -o dist/component.wasm dist/component.jsyarn jco componentize -w wit -o dist/component.wasm dist/component.jspnpm exec jco componentize -w wit -o dist/component.wasm dist/component.jsbun run jco componentize -w wit -o dist/component.wasm dist/component.js5. Exécution
Pour exécuter votre serveur HTTP Hono WebAssembly, vous pouvez utiliser n'importe quel environnement d'exécution WebAssembly compatible WASI :
wasmtimejco(s'exécute dans Node.js)
Dans ce guide, nous utiliserons jco serve, puisqu'il est déjà installé.
Attention
jco serve est destiné au développement et n'est pas recommandé en production.
npx jco serve dist/component.wasmyarn jco serve dist/component.wasmpnpm exec jco serve dist/component.wasmbun run jco serve dist/component.wasmVous devriez obtenir un résultat similaire à celui-ci :
$ npx jco serve dist/component.wasm
Server listening @ localhost:8000...Une requête vers localhost:8000/hello renverra le JSON défini dans votre application Hono.
Vous devriez obtenir un résultat similaire à celui-ci :
{ "message": "Hello from WebAssembly!" }Information
jco serve convertit le composant WebAssembly en un module de base WebAssembly, afin de l'exécuter dans des environnements tels que Node.js et le navigateur.
Ce processus s'effectue normalement avec jco transpile. Il permet d'utiliser des moteurs JavaScript tels que Node.js et le navigateur (qui peuvent utiliser V8 ou d'autres moteurs JavaScript) comme environnements d'exécution de composants WebAssembly.
Le fonctionnement de jco transpile dépasse le cadre de ce guide ; vous pouvez en apprendre davantage dans le livre Jco.
Informations complémentaires
Pour en savoir plus sur WASI, les composants WebAssembly et les sujets associés, consultez :
- Livre Component Model de la Bytecode Alliance
- Code source de
jco- Exemples de composants
jco(notamment l'exemple Hono)
- Exemples de composants
- Livre Jco
- Code source de
componentize-js - Code source de StarlingMonkey
Pour contacter la communauté WebAssembly avec des questions, commentaires, contributions ou signalements de problèmes :
- Zulip de la Bytecode Alliance (vous pouvez publier dans le canal #jco)
- Dépôt Jco
- Dépôt componentize-js