Skip to content

L'option --define vous permet de déclarer des constantes et des globales analysables statiquement. Elle remplace toutes les utilisations d'un identifiant ou d'une propriété dans un fichier JavaScript ou TypeScript par une valeur constante. Cette fonctionnalité est prise en charge au moment de l'exécution et également dans bun build. C'est en quelque sorte similaire à #define en C/C++, mais pour JavaScript.

sh
bun --define process.env.NODE_ENV="'production'" src/index.ts # Exécution
bun build --define process.env.NODE_ENV="'production'" src/index.ts # Compilation

Ces valeurs connues statiquement sont utilisées par Bun pour l'élimination du code mort et d'autres optimisations.

ts
if (process.env.NODE_ENV === "production") {
  console.log("Mode production");
} else {
  console.log("Mode développement");
}

Avant que le code n'atteigne le moteur JavaScript, Bun remplace process.env.NODE_ENV par "production".

ts
if ("production" === "production") { 
  console.log("Mode production");
} else {
  console.log("Mode développement");
}

Cela ne s'arrête pas là. Le transpileur d'optimisation de Bun est assez intelligent pour effectuer une pliage de constantes de base.

Puisque "production" === "production" est toujours true, Bun remplace l'expression entière par la valeur true.

ts
if (true) { 
  console.log("Mode production");
} else {
  console.log("Mode développement");
}

Et enfin, Bun détecte que la branche else n'est pas accessible et l'élimine.

ts
console.log("Mode production");

Quels types de valeurs sont pris en charge ?

Les valeurs peuvent être des chaînes, des identifiants, des propriétés ou du JSON.

Remplacer les identifiants globaux

Pour que toutes les utilisations de window soient undefined, vous pouvez utiliser la commande suivante.

sh
bun --define window="undefined" src/index.ts

Cela peut être utile lors du rendu côté serveur (SSR) ou lorsque vous voulez vous assurer que le code ne dépend pas de l'objet window.

js
if (typeof window !== "undefined") {
  console.log("Code côté client");
} else {
  console.log("Code côté serveur");
}

Vous pouvez également définir la valeur comme un autre identifiant. Par exemple, pour que toutes les utilisations de global soient globalThis, vous pouvez utiliser la commande suivante.

sh
bun --define global="globalThis" src/index.ts

global est un objet global dans Node.js, mais pas dans les navigateurs web. Vous pouvez donc utiliser ceci pour corriger certains cas où le code suppose que global est disponible.

Remplacer des valeurs par du JSON

--define peut également être utilisé pour remplacer des valeurs par des objets et des tableaux JSON.

Pour remplacer toutes les utilisations de AWS par l'objet JSON {"ACCESS_KEY":"abc","SECRET_KEY":"def"}, vous pouvez utiliser la commande suivante.

sh
# JSON
bun --define AWS='{"ACCESS_KEY":"abc","SECRET_KEY":"def"}' src/index.ts

Celles-ci seront transformées en code JavaScript équivalent.

De :

ts
console.log(AWS.ACCESS_KEY); // => "abc"

À :

ts
console.log("abc");

Remplacer des valeurs par d'autres propriétés

Vous pouvez également passer des propriétés à l'option --define.

Par exemple, pour remplacer toutes les utilisations de console.write par console.log, vous pouvez utiliser la commande suivante

sh
bun --define console.write=console.log src/index.ts

Cela transforme l'entrée suivante :

ts
console.write("Hello, world!");

En la sortie suivante :

ts
console.log("Hello, world!");

En quoi cela diffère-t-il de la définition d'une variable ?

Vous pouvez également définir process.env.NODE_ENV sur "production" dans votre code, mais cela n'aidera pas avec l'élimination du code mort. En JavaScript, les accès aux propriétés peuvent avoir des effets de bord. Les getters et setters peuvent être des fonctions, et même définis dynamiquement (en raison des chaînes de prototypes et de Proxy). Même si vous définissez process.env.NODE_ENV sur "production", à la ligne suivante, il n'est pas sûr pour les outils d'analyse statique de supposer que process.env.NODE_ENV est "production".

En quoi cela diffère-t-il de la recherche et remplacement ou du remplacement de chaîne ?

L'option --define fonctionne au niveau de l'AST (Abstract Syntax Tree), pas au niveau du texte. Cela se produit pendant le processus de transpilation, ce qui signifie qu'elle peut être utilisée dans des optimisations comme l'élimination du code mort.

Les outils de remplacement de chaînes ont tendance à avoir des problèmes d'échappement et à remplacer des parties non intentionnelles du code.

Bun édité par www.bunjs.com.cn