Un serveur de développement Web qui vous permet d'importer n'importe quoi *
* Si par quelque chose, vous entendez: JavaScript ES2015 +, TypeScript, JSON, JSX, TSX, AssemblyScript, Rust, C, C ++, WebAssembly, et à l'avenir tout ce qui se compile vers JavaScript ou WebAssembly.
Zwitterion est conçu pour remplacer instantanément votre serveur de fichiers statique de développement Web actuel.
Les déploiements de production sont également possibles grâce à la construction statique.
Par exemple, vous pouvez écrire des choses comme ce qui suit et cela fonctionne:
./index.html :
<!DOCTYPE html >
< html >
< head >
< script type =" module " src =" app.ts " > </ script >
</ head >
< body >
This is the simplest developer experience I've ever had!
</ body >
</ html > ./app.ts :
import { getHelloWorld } from './hello-world.ts' ;
const helloWorld : string = getHelloWorld ( ) ;
console . log ( helloWorld ) ; ./hello-world.ts :
export function getHelloWorld ( ) : string {
return 'Why hello there world!' ;
}Vraiment, ça marche juste.
Zwitterion vous permet de revenir au bon vieux temps du développement Web.
Écrivez simplement votre code source dans n'importe quelle langue prise en charge et exécutez-la dans le navigateur.
Aussi ... Zwitterion n'est pas un bundler. Il évite les regroupements pour une expérience plus simple.
import * as stuff from 'library'; au lieu d' import * as stuff from '../node_modules/library/index.js'; )index.html sur les routes non gérées)Installez Zwitterion dans le répertoire dont vous souhaitez servir les fichiers à partir de:
npm install zwitterionExécutez Zwitterion en accédant à son exécutable directement à partir du terminal:
node_modules/.bin/zwitterion
ou à partir d'un script NPM:
{
...
"scripts": {
"start": "zwitterion"
}
...
}
Installez Zwitterion à l'échelle mondiale à utiliser entre les projets:
npm install -g zwitterionExécutez Zwitterion à partir du terminal:
zwitterionou à partir d'un script NPM:
{
...
"scripts": {
"start": "zwitterion"
}
...
}
Il est recommandé d'utiliser Zwitterion en production en créant une construction statique de votre projet. Une version statique exécute essentiellement tous les fichiers pertinents via Zwitterion et copie ces fichiers et tous les autres de votre projet vers un répertoire dist . Vous pouvez prendre ce répertoire et le télécharger sur un réseau de livraison de contenu (CDN) ou un autre service d'hébergement de fichiers statique.
Vous pouvez également utiliser un serveur Zwitterion en cours de production, mais pour les performances et les raisons de sécurité potentielles, elle n'est pas recommandée.
Pour créer une version statique, exécutez Zwitterion avec l'option --build-static . Vous devrez probablement ajouter le type MIME application/javascript à votre fournisseur d'hébergement pour vos fichiers TypeScript, AssemblyScript, Rust, WASM et WAT.
Du terminal:
zwitterion --build-staticÀ partir d'un script NPM:
{
...
" scripts " : {
" build-static " : " zwitterion --build-static "
}
...
} La construction statique sera située dans un répertoire appelé dist , dans le même répertoire que vous avez exécuté la commande --build-static .
JavaScript est la langue du Web. Vous pouvez en savoir plus ici.
L'importation JavaScript ES2015 + est simple et fonctionne comme prévu. Utilisez simplement des instructions d'importation et d'exportation sans aucune modification. Il est recommandé d'utiliser des extensions de fichiers explicites:
./app.js :
import { helloWorld } from './hello-world.js' ;
console . log ( helloWorld ( ) ) ; ./hello-world.js :
export function helloWorld ( ) {
return 'Hello world!' ;
} La transpilation JavaScript est effectuée par le compilateur TypeScript. Par défaut, les compilerOptions de TypeScript du compilateur sont définies sur ce qui suit:
{
"module" : " ES2015 " ,
"target" : " ES2015 "
} Vous pouvez remplacer ces options en créant un fichier .json avec vos propres compilerOptions et en indiquant à Zwitterion où le localiser avec l'option de ligne de commande --tsc-options-file . Les options disponibles peuvent être trouvées ici. Les options sont spécifiées comme un objet JSON. Par exemple:
tsc-options.json :
{
"target" : " ES5 "
}Dites à Zwitterion où le localiser:
zwitterion --tsc-options-file tsc-options.jsonTypeScript est un superset tapé de JavaScript. Vous pouvez en savoir plus ici.
L'importation de typeScript est simple et fonctionne comme prévu. Utilisez simplement des instructions d'importation et d'exportation sans aucune modification. Il est recommandé d'utiliser des extensions de fichiers explicites:
./app.ts :
import { helloWorld } from './hello-world.ts' ;
console . log ( helloWorld ( ) ) ; ./hello-world.ts :
export function helloWorld ( ) : string {
return 'Hello world!' ;
} Par défaut, les compilerOptions de TypeScript du compilateur sont définies sur ce qui suit:
{
"module" : " ES2015 " ,
"target" : " ES2015 "
} Vous pouvez remplacer ces options en créant un fichier .json avec vos propres compilerOptions et en indiquant à Zwitterion où le localiser avec l'option de ligne de commande --tsc-options-file . Les options disponibles peuvent être trouvées ici. Les options sont spécifiées comme un objet JSON. Par exemple:
tsc-options.json :
{
"target" : " ES5 "
}Dites à Zwitterion où le localiser:
zwitterion --tsc-options-file tsc-options.jsonJSON est fourni comme exportation par défaut. Il est recommandé d'utiliser des extensions de fichiers explicites:
./app.js :
import helloWorld from './hello-world.json' ;
console . log ( helloWorld ) ; ./hello-world.json :
{
"hello" : " world "
}L'importation de JSX est simple et fonctionne comme prévu. Utilisez simplement des instructions d'importation et d'exportation sans aucune modification. Il est recommandé d'utiliser des extensions de fichiers explicites:
./app.js :
import { helloWorldElement } from './hello-world.jsx' ;
ReactDOM . render (
helloWorldElement ,
document . getElementById ( 'root' )
) ; ./hello-world.jsx :
export const hellowWorldElement = < h1 > Hello, world! </ h1 > ; La transpilation JSX est effectuée par le compilateur TypeScript. Par défaut, les compilerOptions de TypeScript du compilateur sont définies sur ce qui suit:
{
"module" : " ES2015 " ,
"target" : " ES2015 "
} Vous pouvez remplacer ces options en créant un fichier .json avec vos propres compilerOptions et en indiquant à Zwitterion où le localiser avec l'option de ligne de commande --tsc-options-file . Les options disponibles peuvent être trouvées ici. Les options sont spécifiées comme un objet JSON. Par exemple:
tsc-options.json :
{
"target" : " ES5 "
}Dites à Zwitterion où le localiser:
zwitterion --tsc-options-file tsc-options.jsonL'importation de TSX est simple et fonctionne comme prévu. Utilisez simplement des instructions d'importation et d'exportation sans aucune modification. Il est recommandé d'utiliser des extensions de fichiers explicites:
./app.js :
import { helloWorldElement } from './hello-world.tsx' ;
ReactDOM . render (
helloWorldElement ,
document . getElementById ( 'root' )
) ; ./hello-world.tsx :
const helloWorld : string = 'Hello, world!' ;
export const hellowWorldElement = < h1 > { helloWorld } </ h1 > ; La transpilation TSX est effectuée par le compilateur TypeScript. Par défaut, les compilerOptions de TypeScript du compilateur sont définies sur ce qui suit:
{
"module" : " ES2015 " ,
"target" : " ES2015 "
} Vous pouvez remplacer ces options en créant un fichier .json avec vos propres compilerOptions et en indiquant à Zwitterion où le localiser avec l'option de ligne de commande --tsc-options-file . Les options disponibles peuvent être trouvées ici. Les options sont spécifiées comme un objet JSON. Par exemple:
tsc-options.json :
{
"target" : " ES5 "
}Dites à Zwitterion où le localiser:
zwitterion --tsc-options-file tsc-options.jsonAssemblyScript est une nouvelle langue qui compile un sous-ensemble strict de TypeScript à WebAssembly. Vous pouvez en savoir plus dans le livre de l'AssemblyScript.
Zwitterion suppose que les fichiers d'assemblycript ont l'extension de fichier .as . Il s'agit d'un choix d'extension spécifique à Zwitterion, car le projet AssemblScript n'a pas encore choisi sa propre extension de fichier officielle. Vous pouvez suivre cette discussion ici. Zwitterion suivra le choix d'extension officiel une fois qu'il sera fait.
L'importation d'assemblage est presque identique à l'importation javascript ou dactylographe. La principale différence est que l'exportation par défaut de votre module d'assemblycript de saisie est une fonction qui renvoie une promesse. Cette fonction prend comme paramètre un seul objet contenant des importations dans le module d'assemblycript.
Passer des valeurs vers et depuis les fonctions exportées à partir des modules d'assemblage doit être simple, mais il y a certaines limites. Zwitterion utilise la liaison sous le capot pour courtiser les valeurs vers et depuis les modules d'assemblycript. Regardez là-bas si vous avez besoin de plus d'informations.
Vous pouvez importer AssemblyScript à partir de fichiers JavaScript ou TypeScript comme ceci:
./app.js :
import addModuleInit from './add.as' ;
runAssemblyScript ( ) ;
async function runAssemblyScript ( ) {
const adddModule = await addModuleInit ( ) ;
console . log ( addModule . add ( 1 , 1 ) ) ;
} ./add.as :
export function add ( x : i32 , y : i32 ) : i32 {
return x + y ;
}Si vous souhaitez transmettre des importations en dehors de l'environnement de l'assemblycript, vous créez un fichier avec des déclarations d'exportation définissant les types d'importations. Vous transmettez ensuite vos importations en tant qu'objet à la fonction INIT du module d'assemblycript. Le nom de la propriété qui définit vos importations pour un module doit être le nom de fichier exact du fichier exportant les déclarations d'importation. Par exemple:
./app.js :
import addModuleInit from './add.as' ;
runAssemblyScript ( ) ;
async function runAssemblyScript ( ) {
const adddModule = await addModuleInit ( {
'env.as' : {
log : console . log
}
} ) ;
console . log ( addModule . add ( 1 , 1 ) ) ;
} ./env.as :
export declare function log ( x : number ) : void ; ./add.as :
import { log } from './env.as' ;
export function add ( x : i32 , y : i32 ) : i32 {
log ( x + y ) ;
return x + y ;
}Vous pouvez également importer l'assemblycript à partir des fichiers d'assemblycript, comme ainsi:
./add.as :
import { subtract } from './subtract.as' ;
export function add ( x : i32 , y : i32 ) : i32 {
return subtract ( x + y , 0 ) ;
} ./subtract.as :
export function subtract ( x : i32 , y : i32 ) : i32 {
return x - y ;
} Par défaut, aucune option de compilateur n'a été définie. Les options disponibles peuvent être trouvées ici. Vous pouvez ajouter des options en créant un fichier .json avec un tableau de noms et de valeurs d'options, et en indiquant à Zwitterion où le localiser avec l'option de ligne de commande --asc-options-file . Par exemple:
./asc-options.json :
[
" --optimizeLevel " , " 3 " ,
" --runtime " , " none " ,
" --shrinkLevel " , " 2 "
]Dites à Zwitterion où le localiser:
zwitterion --asc-options-file asc-options.jsonLa rouille est un langage de bas niveau axé sur les performances, la fiabilité et la productivité. Apprenez-en plus ici.
Le support de la rouille est actuellement très basique (c'est-à-dire non de support Wasm-Bindgen). Vous devez faire installer la rouille sur votre machine. Vous pouvez trouver des instructions pour installer la rouille ici. C'est un objectif de Zwitterion d'installer automatiquement une version locale de l'outillage de rouille nécessaire lorsque Zwitterion est installé, mais c'est actuellement un travail en cours.
L'importation de rouille est presque identique à l'importation javascript ou dactylographiée. La principale différence est que l'exportation par défaut de votre module de rouille d'entrée est une fonction qui renvoie une promesse. Cette fonction prend comme paramètre un objet contenant des importations dans le module de rouille. Vous pouvez importer de la rouille à partir de fichiers JavaScript ou TypeScript comme celui-ci:
./app.js
import addModuleInit from './add.rs' ;
runRust ( ) ;
async function runRust ( ) {
const addModule = await addModuleInit ( ) ;
console . log ( addModule . add ( 5 , 5 ) ) ;
} ./add.rs
#! [ no_main ]
# [ no_mangle ]
pub fn add ( x : i32 , y : i32 ) -> i32 {
return x + y ;
}Le support C est actuellement très basique. Vous devez faire installer Emscripten sur votre machine. Vous pouvez trouver des instructions pour installer Emscripten ici. C'est un objectif de Zwitterion d'installer automatiquement une version locale de l'outillage C nécessaire lorsque Zwitterion est installé, mais c'est actuellement un travail en cours.
L'importation c est presque identique à l'importation javascript ou dactylographiée. La principale différence est que l'exportation par défaut de votre module C Entrée est une fonction qui renvoie une promesse. Cette fonction prend comme paramètre un objet contenant des importations dans le module C. Vous pouvez importer C à partir de fichiers JavaScript ou TypeScript comme celui-ci:
./app.js
import addModuleInit from './add.c' ;
runC ( ) ;
async function runC ( ) {
const addModule = await addModuleInit ( ) ;
console . log ( addModule . add ( 5 , 5 ) ) ;
} ./add.c
int add ( int x , int y ) {
return x + y ;
}Le support C ++ est actuellement très basique. Vous devez faire installer Emscripten sur votre machine. Vous pouvez trouver des instructions pour installer Emscripten ici. C'est un objectif de Zwitterion d'installer automatiquement une version locale de l'outillage C ++ nécessaire lorsque Zwitterion est installé, mais c'est actuellement un travail en cours.
L'importation C ++ est presque identique à l'importation javascript ou dactylographiée. La principale différence est que l'exportation par défaut de votre module C ++ d'entrée est une fonction qui renvoie une promesse. Cette fonction prend comme paramètre un seul objet contenant des importations dans le module C ++. Vous pouvez importer C ++ à partir de fichiers JavaScript ou TypeScript comme ceci:
./app.js
import addModuleInit from './add.cpp' ;
runCPP ( ) ;
async function runCPP ( ) {
const addModule = await addModuleInit ( ) ;
console . log ( addModule . add ( 5 , 5 ) ) ;
} ./add.cpp
extern " C " {
int add ( int x, int y) {
return x + y;
}
}
Wat est une représentation textuelle du format binaire WASM. Il permet à Wasm d'être plus facilement écrit à la main. Apprenez-en plus ici.
L'importation de WAT est presque identique à l'importation javascript ou dactylographiée. La principale différence est que l'exportation par défaut de votre module WAT d'entrée est une fonction qui renvoie une promesse. Cette fonction prend comme paramètre un objet contenant des importations dans le module WAT. Vous pouvez importer WAT à partir de fichiers JavaScript ou TypeScript comme celui-ci:
./app.js
import addModuleInit from './add.wat' ;
runWat ( ) ;
async function runWat ( ) {
const addModule = await addModuleInit ( ) ;
console . log ( addModule . add ( 5 , 5 ) ) ;
} ./add.wat
(module
(func $add (param $x i32) (param $y i32) (result i32)
(i32.add (get_local $x) (get_local $y))
)
( export " add " (func $add))
)WASM est un format d'instruction binaire conçu pour être efficace, sûr, portable et ouvert. Apprenez-en plus ici.
L'importation WASM est presque identique à l'importation javascript ou dactylographiée. La principale différence est que l'exportation par défaut de votre module de l'entrée était une fonction qui renvoie une promesse. Cette fonction prend comme paramètre un seul objet contenant des importations dans le module WASM. Vous pouvez importer WasM à partir de fichiers JavaScript ou TypeScript comme ceci:
./app.js
import addModuleInit from './add.wasm' ;
runWasm ( ) ;
async function runWasm ( ) {
const addModule = await addModuleInit ( ) ;
console . log ( addModule . add ( 5 , 5 ) ) ;
} ./add.wasm
Imagine this is a compiled Wasm binary file with a function called `add`
Spécifiez le port du serveur:
--port [port]Créez une version statique du répertoire de travail actuel. La sortie sera dans un répertoire appelé DIST dans le répertoire de travail actuel:
--build-staticUne liste de chemins séparés par des virgules, par rapport au répertoire actuel, à exclure de la construction statique:
--exclude [exclude]Une liste de chemins séparés par des virgules, par rapport au répertoire actuel, à inclure dans la construction statique
--include [include]Un chemin vers un fichier, par rapport au répertoire actuel, pour servir de racine de spa. Il sera renvoyé pour le chemin racine et lorsqu'un fichier ne peut être trouvé:
--spa-root [spaRoot]Désactivez la redirection du spa vers index.html:
--disable-spaUn chemin d'accès à un fichier JSON, par rapport au répertoire actuel, pour les en-têtes HTTP personnalisés:
--headers-file [headersFile]Les en-têtes HTTP personnalisés sont spécifiés comme un objet JSON avec la forme suivante:
type CustomHTTPHeaders = {
[ regexp : string ] : HTTPHeaders ;
}
type HTTPHeaders = {
[ key : string ] : string ;
}Par exemple:
./headers.json
{
"^service-worker.ts$" : {
"Service-Worker-Allowed" : " / "
}
}Un chemin d'accès à un fichier JSON, par rapport au répertoire actuel, pour les options de compilateur TSC:
--tsc-options-file [tscOptionsFile]Les options disponibles peuvent être trouvées ici. Les options sont spécifiées comme un objet JSON. Par exemple:
tsc-options.json :
{
"target" : " ES5 "
}Un chemin d'accès à un fichier JSON, par rapport au répertoire actuel, pour les options de compilateur ASC:
--asc-options-file [ascOptionsFile]Par défaut, aucune option de compilateur n'a été définie. Les options disponibles peuvent être trouvées ici. Les options sont spécifiées comme un tableau de noms et de valeurs d'options. Par exemple:
./asc-options.json :
[
" --optimizeLevel " , " 3 " ,
" --runtime " , " none " ,
" --shrinkLevel " , " 2 "
]Les packages tiers doivent être rédigés comme s'ils utilisaient Zwitterion. Essentiellement, cela signifie qu'ils devraient être rédigés dans JavaScript ou dactylographie standard, et l'assemblycript, Rust, C et C ++ doivent être rédigés en fonction de leur documentation WebAssembly. Des exceptions notables seront expliquées dans cette documentation. CommonJS (la syntaxe nécessite), les importations de modules JSON, HTML ou CSS ES et d'autres fonctionnalités non standard que les regroupements prennent généralement en charge ne sont pas supportées dans le code source.
Il est important de noter que Zwitterion suppose que le fichier racine (le fichier trouvé à / ) de votre application Web est toujours un fichier index.html .
Zwitterion dépend de la prise en charge du navigateur natif pour les modules ES (syntaxe d'importation / exportation). Vous devez ajouter l'attribut type="module" aux éléments de script qui référence les modules, par exemple:
<script type="module" src="amazing-module.ts"></script>
Il est important de noter que Zwitterion ne regroupe pas les fichiers ni ne s'engage dans des tremblements d'arbre. Cela peut avoir un impact sur les performances de votre application. Les modules HTTP2 et ES peuvent aider à la performance, mais à ce stade, les signes ont tendance à pointer vers de pires performances. Zwitterion prévoit d'améliorer les performances en générant automatiquement les informations de push du serveur HTTP2 à partir de la construction statique et en examinant les tremblements d'arbre, mais il n'est pas clair ce que cela aura. Restez à l'écoute pour plus d'informations sur les performances à mesure que Zwitterion mûrit.
Tout ce qui précède étant dit, les implications de performance ne sont pas claires. Mesurez par vous-même.
Lisez ce qui suit pour plus d'informations sur le regroupement par rapport à ne pas regrouper avec HTTP2:
Zwitterion est simple. Il s'agit plus ou moins d'un serveur de fichiers statique, mais il réécrit les fichiers demandés en mémoire si nécessaire pour revenir au client. Par exemple, si un fichier TypeScript est demandé au client, Zwitterion récupérera le texte du fichier, le compile à JavaScript, puis renvoie le texte compilé au client. La même chose est effectuée pour les fichiers JavaScript. En fait, presque le même processus sera utilisé pour toute extension de fichier que nous voulons prendre en charge à l'avenir. Par exemple, à l'avenir, si un fichier C est demandé, il sera lu en mémoire, le texte sera compilé sur WebAssembly et le WebAssembly sera renvoyé au client. Toute cette compilation est effectuée côté serveur et caché à l'utilisateur. Pour l'utilisateur, c'est juste un serveur de fichiers statique.