Le bundler de Bun implémente une option --compile pour générer un binaire autonome à partir d'un fichier TypeScript ou JavaScript.
bun build ./cli.ts --compile --outfile mycliconsole.log("Bonjour le monde !");Cela bundle cli.ts dans un exécutable qui peut être exécuté directement :
./mycliBonjour le monde !Tous les fichiers et packages importés sont bundle dans l'exécutable, ainsi qu'une copie du runtime Bun. Toutes les API intégrées de Bun et Node.js sont prises en charge.
Cross-compilation vers d'autres plateformes
L'option --target vous permet de compiler votre exécutable autonome pour un système d'exploitation, une architecture ou une version de Bun différente de la machine sur laquelle vous exécutez bun build.
Pour construire pour Linux x64 (la plupart des serveurs) :
bun build --compile --target=bun-linux-x64 ./index.ts --outfile myapp
# Pour prendre en charge les CPU d'avant 2013, utilisez la version baseline (nehalem)
bun build --compile --target=bun-linux-x64-baseline ./index.ts --outfile myapp
# Pour prendre explicitement en charge uniquement les CPU de 2013 et plus récents, utilisez la version modern (haswell)
# modern est plus rapide, mais baseline est plus compatible.
bun build --compile --target=bun-linux-x64-modern ./index.ts --outfile myappPour construire pour Linux ARM64 (par exemple Graviton ou Raspberry Pi) :
# Note : l'architecture par défaut est x64 si aucune architecture n'est spécifiée.
bun build --compile --target=bun-linux-arm64 ./index.ts --outfile myappPour construire pour Windows x64 :
bun build --compile --target=bun-windows-x64 ./path/to/my/app.ts --outfile myapp
# Pour prendre en charge les CPU d'avant 2013, utilisez la version baseline (nehalem)
bun build --compile --target=bun-windows-x64-baseline ./path/to/my/app.ts --outfile myapp
# Pour prendre explicitement en charge uniquement les CPU de 2013 et plus récents, utilisez la version modern (haswell)
bun build --compile --target=bun-windows-x64-modern ./path/to/my/app.ts --outfile myapp
# note : si aucune extension .exe n'est fournie, Bun l'ajoutera automatiquement pour les exécutables WindowsPour construire pour macOS arm64 :
bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myappPour construire pour macOS x64 :
bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myappCibles prises en charge
L'ordre des options --target n'a pas d'importance, tant qu'elles sont délimitées par un -.
| --target | Système d'exploitation | Architecture | Modern | Baseline | Libc |
|---|---|---|---|---|---|
| bun-linux-x64 | Linux | x64 | ✅ | ✅ | glibc |
| bun-linux-arm64 | Linux | arm64 | ✅ | N/A | glibc |
| bun-windows-x64 | Windows | x64 | ✅ | ✅ | - |
| ❌ | ❌ | - | |||
| bun-darwin-x64 | macOS | x64 | ✅ | ✅ | - |
| bun-darwin-arm64 | macOS | arm64 | ✅ | N/A | - |
| bun-linux-x64-musl | Linux | x64 | ✅ | ✅ | musl |
| bun-linux-arm64-musl | Linux | arm64 | ✅ | N/A | musl |
Constantes au moment de la construction
Utilisez l'option --define pour injecter des constantes au moment de la construction dans votre exécutable, telles que des numéros de version, des horodatages de construction ou des valeurs de configuration :
bun build --compile --define BUILD_VERSION='"1.2.3"' --define BUILD_TIME='"2024-01-15T10:30:00Z"' src/cli.ts --outfile mycliCes constantes sont intégrées directement dans votre binaire compilé au moment de la construction, offrant un surcoût d'exécution nul et permettant des optimisations d'élimination de code mort.
NOTE
Pour des exemples complets et des modèles avancés, consultez le [guide des constantes au moment de la construction](/fr/guides/runtime/build-time-constants).Déploiement en production
Les exécutables compilés réduisent l'utilisation de la mémoire et améliorent le temps de démarrage de Bun.
Normalement, Bun lit et transpile les fichiers JavaScript et TypeScript lors de import et require. C'est ce qui fait qu'une grande partie de Bun "fonctionne simplement", mais ce n'est pas gratuit. Cela coûte du temps et de la mémoire de lire les fichiers depuis le disque, de résoudre les chemins de fichiers, d'analyser, de transpiler et d'imprimer le code source.
Avec les exécutables compilés, vous pouvez déplacer ce coût du temps d'exécution au temps de construction.
Lors du déploiement en production, nous recommandons ce qui suit :
bun build --compile --minify --sourcemap ./path/to/my/app.ts --outfile myappCompilation du bytecode
Pour améliorer le temps de démarrage, activez la compilation du bytecode :
bun build --compile --minify --sourcemap --bytecode ./path/to/my/app.ts --outfile myappEn utilisant la compilation du bytecode, tsc démarre 2x plus vite :
La compilation du bytecode déplace la surcharge d'analyse pour les grands fichiers d'entrée du temps d'exécution au temps de bundle. Votre application démarre plus vite, en échange de rendre la commande bun build un peu plus lente. Elle n'obscurcit pas le code source.
Que font ces options ?
L'argument --minify optimise la taille du code transpilé. Si vous avez une grande application, cela peut économiser des mégaoctets d'espace. Pour les applications plus petites, cela peut encore améliorer un peu le temps de démarrage.
L'argument --sourcemap intègre une sourcemap compressée avec zstd, afin que les erreurs et les stacktraces pointent vers leurs emplacements d'origine au lieu de l'emplacement transpilé. Bun décompressera et résoudra automatiquement la sourcemap lorsqu'une erreur se produit.
L'argument --bytecode active la compilation du bytecode. Chaque fois que vous exécutez du code JavaScript dans Bun, JavaScriptCore (le moteur) compile votre code source en bytecode. Nous pouvons déplacer ce travail d'analyse du temps d'exécution au temps de bundle, vous faisant gagner du temps de démarrage.
Intégration des arguments d'exécution
--compile-exec-argv="args" - Intègre des arguments d'exécution disponibles via process.execArgv :
bun build --compile --compile-exec-argv="--smol --user-agent=MyBot" ./app.ts --outfile myapp// Dans l'application compilée
console.log(process.execArgv); // ["--smol", "--user-agent=MyBot"]Désactivation du chargement automatique de la configuration
Par défaut, les exécutables autonomes recherchent des fichiers .env et bunfig.toml dans le répertoire où l'exécutable est exécuté. Vous pouvez désactiver ce comportement au moment de la construction pour une exécution déterministe quel que soit le répertoire de travail de l'utilisateur.
# Désactiver le chargement .env
bun build --compile --no-compile-autoload-dotenv ./app.ts --outfile myapp
# Désactiver le chargement bunfig.toml
bun build --compile --no-compile-autoload-bunfig ./app.ts --outfile myapp
# Désactiver les deux
bun build --compile --no-compile-autoload-dotenv --no-compile-autoload-bunfig ./app.ts --outfile myappVous pouvez également configurer cela via l'API JavaScript :
await Bun.build({
entrypoints: ["./app.ts"],
compile: {
autoloadDotenv: false, // Désactiver le chargement .env
autoloadBunfig: false, // Désactiver le chargement bunfig.toml
},
});Agir comme la CLI Bun
NOTE
Nouveau dans Bun v1.2.16Vous pouvez exécuter un exécutable autonome comme s'il s'agissait de la CLI bun elle-même en définissant la variable d'environnement BUN_BE_BUN=1. Lorsque cette variable est définie, l'exécutable ignorera son point d'entrée bundle et exposera toutes les fonctionnalités de la CLI de Bun.
Par exemple, considérez un exécutable compilé à partir d'un script simple :
echo "console.log(\"vous ne devriez pas voir ceci\");" > such-bun.js
bun build --compile ./such-bun.js[3ms] bundle 1 modules
[89ms] compile such-bunNormalement, exécuter ./such-bun avec des arguments exécuterait le script.
# L'exécutable exécute son propre point d'entrée par défaut
./such-bun installvous ne devriez pas voir ceciCependant, avec la variable d'environnement BUN_BE_BUN=1, il agit comme le binaire bun :
# Avec la variable d'environnement, l'exécutable agit comme la CLI `bun`
BUN_BE_BUN=1 ./such-bun installbun install v1.2.16-canary.1 (1d1db811)
Checked 63 installs across 64 packages (no changes) [5.00ms]Ceci est utile pour construire des outils CLI sur Bun qui peuvent avoir besoin d'installer des packages, de bundler des dépendances, d'exécuter différents fichiers ou des fichiers locaux et plus encore sans avoir besoin de télécharger un binaire séparé ou d'installer bun.
Exécutables full-stack
NOTE
Nouveau dans Bun v1.2.17L'option --compile de Bun peut créer des exécutables autonomes qui contiennent à la fois du code serveur et client, ce qui le rend idéal pour les applications full-stack. Lorsque vous importez un fichier HTML dans votre code serveur, Bun bundle automatiquement tous les assets frontend (JavaScript, CSS, etc.) et les intègre dans l'exécutable. Lorsque Bun voit l'importation HTML sur le serveur, il lance un processus de construction frontend pour bundler le JavaScript, le CSS et d'autres assets.
import { serve } from "bun";
import index from "./index.html";
const server = serve({
routes: {
"/": index,
"/api/hello": { GET: () => Response.json({ message: "Bonjour depuis l'API" }) },
},
});
console.log(`Serveur en cours d'exécution sur http://localhost:${server.port}`);<!DOCTYPE html>
<html>
<head>
<title>Mon Application</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<h1>Bonjour le monde</h1>
<script src="./app.ts"></script>
</body>
</html>console.log("Bonjour depuis le client !");body {
background-color: #f0f0f0;
}Pour construire cela en un seul exécutable :
bun build --compile ./server.ts --outfile myappCela crée un binaire autonome qui inclut :
- Votre code serveur
- Le runtime Bun
- Tous les assets frontend (HTML, CSS, JavaScript)
- Tous les packages npm utilisés par votre serveur
Le résultat est un seul fichier qui peut être déployé n'importe où sans avoir besoin de Node.js, Bun ou de dépendances installées. Il suffit d'exécuter :
./myappBun gère automatiquement le service des assets frontend avec les types MIME et les en-têtes de cache appropriés. L'importation HTML est remplacée par un objet manifeste que Bun.serve utilise pour servir efficacement des assets pré-bundle.
Pour plus de détails sur la construction d'applications full-stack avec Bun, consultez le guide full-stack.
Worker
Pour utiliser des workers dans un exécutable autonome, ajoutez le point d'entrée du worker aux arguments CLI :
bun build --compile ./index.ts ./my-worker.ts --outfile myappEnsuite, référencez le worker dans votre code :
console.log("Bonjour depuis Bun !");
// N'importe laquelle de ces options fonctionnera :
new Worker("./my-worker.ts");
new Worker(new URL("./my-worker.ts", import.meta.url));
new Worker(new URL("./my-worker.ts", import.meta.url).href);Lorsque vous ajoutez plusieurs points d'entrée à un exécutable autonome, ils seront bundle séparément dans l'exécutable.
À l'avenir, nous pourrions détecter automatiquement les utilisations de chemins statiquement connus dans new Worker(path) puis les bundler dans l'exécutable, mais pour l'instant, vous devrez les ajouter manuellement à la commande shell comme dans l'exemple ci-dessus.
Si vous utilisez un chemin relatif vers un fichier non inclus dans l'exécutable autonome, il tentera de charger ce chemin depuis le disque par rapport au répertoire de travail actuel du processus (puis affichera une erreur s'il n'existe pas).
SQLite
Vous pouvez utiliser les importations bun:sqlite avec bun build --compile.
Par défaut, la base de données est résolue par rapport au répertoire de travail actuel du processus.
import db from "./my.db" with { type: "sqlite" };
console.log(db.query("select * from users LIMIT 1").get());Cela signifie que si l'exécutable est situé à /usr/bin/hello, le terminal de l'utilisateur est situé à /home/me/Desktop, il recherchera /home/me/Desktop/my.db.
cd /home/me/Desktop
./helloIntégration de fichiers et d'assets
Les exécutables autonomes prennent en charge l'intégration de fichiers.
Pour intégrer des fichiers dans un exécutable avec bun build --compile, importez le fichier dans votre code.
// ceci devient un chemin de fichier interne
import icon from "./icon.png" with { type: "file" };
import { file } from "bun";
export default {
fetch(req) {
// Les fichiers intégrés peuvent être streamés depuis des objets Response
return new Response(file(icon));
},
};Les fichiers intégrés peuvent être lus en utilisant les fonctions de Bun.file ou la fonction fs.readFile de Node.js (dans "node:fs").
Par exemple, pour lire le contenu du fichier intégré :
import icon from "./icon.png" with { type: "file" };
import { file } from "bun";
const bytes = await file(icon).arrayBuffer();
// await fs.promises.readFile(icon)
// fs.readFileSync(icon)Intégrer des bases de données SQLite
Si votre application souhaite intégrer une base de données SQLite, définissez type: "sqlite" dans l'attribut d'importation et l'attribut embed à "true".
import myEmbeddedDb from "./my.db" with { type: "sqlite", embed: "true" };
console.log(myEmbeddedDb.query("select * from users LIMIT 1").get());Cette base de données est en lecture-écriture, mais toutes les modifications sont perdues lorsque l'exécutable se termine (puisqu'elle est stockée en mémoire).
Intégrer des addons N-API
Vous pouvez intégrer des fichiers .node dans des exécutables.
const addon = require("./addon.node");
console.log(addon.hello());Malheureusement, si vous utilisez @mapbox/node-pre-gyp ou d'autres outils similaires, vous devrez vous assurer que le fichier .node est directement requis sinon il ne sera pas bundle correctement.
Intégrer des répertoires
Pour intégrer un répertoire avec bun build --compile, utilisez un glob shell dans votre commande bun build :
bun build --compile ./index.ts ./public/**/*.pngEnsuite, vous pouvez référencer les fichiers dans votre code :
import icon from "./public/assets/icon.png" with { type: "file" };
import { file } from "bun";
export default {
fetch(req) {
// Les fichiers intégrés peuvent être streamés depuis des objets Response
return new Response(file(icon));
},
};C'est honnêtement une solution de contournement, et nous espérons améliorer cela à l'avenir avec une API plus directe.
Lister les fichiers intégrés
Pour obtenir une liste de tous les fichiers intégrés, utilisez Bun.embeddedFiles :
import "./icon.png" with { type: "file" };
import { embeddedFiles } from "bun";
console.log(embeddedFiles[0].name); // `icon-${hash}.png`Bun.embeddedFiles retourne un tableau d'objets Blob que vous pouvez utiliser pour obtenir la taille, le contenu et d'autres propriétés des fichiers.
embeddedFiles: Blob[]La liste des fichiers intégrés exclut le code source bundle comme les fichiers .ts et .js.
Hachage de contenu
Par défaut, les fichiers intégrés ont un hachage de contenu ajouté à leur nom. Ceci est utile pour les situations où vous voulez servir le fichier depuis une URL ou un CDN et avoir moins de problèmes d'invalidation de cache. Mais parfois, cela est inattendu et vous pourriez vouloir le nom d'origine à la place :
Pour désactiver le hachage de contenu, passez --asset-naming à bun build --compile comme ceci :
bun build --compile --asset-naming="[name].[ext]" ./index.tsMinification
Pour réduire un peu la taille de l'exécutable, passez --minify à bun build --compile. Cela utilise le minifieur de Bun pour réduire la taille du code. Dans l'ensemble, le binaire de Bun est toujours beaucoup trop grand et nous devons le rendre plus petit.
Options spécifiques à Windows
Lors de la compilation d'un exécutable autonome sur Windows, il y a deux options spécifiques à la plateforme qui peuvent être utilisées pour personnaliser les métadonnées sur le fichier .exe généré :
--windows-icon=path/to/icon.icopour personnaliser l'icône du fichier exécutable.--windows-hide-consolepour désactiver le terminal d'arrière-plan, qui peut être utilisé pour les applications qui n'ont pas besoin d'un TTY.
Signature de code sur macOS
Pour signer un exécutable autonome sur macOS (ce qui corrige les avertissements Gatekeeper), utilisez la commande codesign.
codesign --deep --force -vvvv --sign "XXXXXXXXXX" ./myappNous recommandons d'inclure un fichier entitlements.plist avec les permissions JIT.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>Pour signer avec le support JIT, passez l'option --entitlements à codesign.
codesign --deep --force -vvvv --sign "XXXXXXXXXX" --entitlements entitlements.plist ./myappAprès la signature de code, vérifiez l'exécutable :
codesign -vvv --verify ./myapp
./myapp: valid on disk
./myapp: satisfies its Designated RequirementCode splitting
Les exécutables autonomes prennent en charge le code splitting. Utilisez --compile avec --splitting pour créer un exécutable qui charge des chunks de code split au moment de l'exécution.
bun build --compile --splitting ./src/entry.ts --outdir ./buildconsole.log("Point d'entrée chargé");
const lazy = await import("./lazy.ts");
lazy.hello();export function hello() {
console.log("Module lazy chargé");
}./build/entryPoint d'entrée chargé
Module lazy chargéArguments CLI non pris en charge
Actuellement, l'option --compile ne peut accepter qu'un seul point d'entrée à la fois et ne prend pas en charge les options suivantes :
--outdir— utilisezoutfileà la place (sauf lors de l'utilisation avec--splitting).--public-path--target=nodeou--target=browser--no-bundle- nous bundle toujours tout dans l'exécutable.