152 lines
4.1 KiB
Plaintext
152 lines
4.1 KiB
Plaintext
---
|
|
title: Define and replace static globals & constants
|
|
sidebarTitle: Define constants
|
|
mode: center
|
|
---
|
|
|
|
The `--define` flag declares statically-analyzable constants and globals. It replaces all usages of an identifier or property in a JavaScript or TypeScript file with a constant value, and works both at runtime and in `bun build`. It's similar to `#define` in C/C++, but for JavaScript.
|
|
|
|
```sh terminal icon="terminal"
|
|
bun --define process.env.NODE_ENV="'production'" src/index.ts # Runtime
|
|
bun build --define process.env.NODE_ENV="'production'" src/index.ts # Build
|
|
```
|
|
|
|
---
|
|
|
|
Bun uses these statically-known values for dead code elimination and other optimizations.
|
|
|
|
```ts
|
|
if (process.env.NODE_ENV === "production") {
|
|
console.log("Production mode");
|
|
} else {
|
|
console.log("Development mode");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
Before the code reaches the JavaScript engine, Bun replaces `process.env.NODE_ENV` with `"production"`.
|
|
|
|
{/* prettier-ignore */}
|
|
```ts
|
|
if ("production" === "production") { // [!code ++]
|
|
console.log("Production mode");
|
|
} else {
|
|
console.log("Development mode");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
Bun's optimizing transpiler also does basic constant folding.
|
|
|
|
Since `"production" === "production"` is always `true`, Bun replaces the entire expression with the `true` value and drops the unreachable `else` branch.
|
|
|
|
{/* prettier-ignore */}
|
|
```ts
|
|
if (true) { // [!code ++]
|
|
console.log("Production mode");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
To also collapse the surrounding `if` scaffolding down to the following output, pass `--minify-syntax` (also enabled by `--minify`):
|
|
|
|
```sh terminal icon="terminal"
|
|
bun build --define process.env.NODE_ENV="'production'" --minify-syntax src/index.ts
|
|
```
|
|
|
|
```ts
|
|
console.log("Production mode");
|
|
```
|
|
|
|
---
|
|
|
|
## What types of values are supported?
|
|
|
|
Values can be strings, identifiers, properties, or JSON.
|
|
|
|
### Replace global identifiers
|
|
|
|
To replace all usages of `window` with `undefined`:
|
|
|
|
```sh
|
|
bun --define window="undefined" src/index.ts
|
|
```
|
|
|
|
This replacement is useful for server-side rendering (SSR), or to make sure code doesn't depend on the `window` object.
|
|
|
|
```js
|
|
if (typeof window !== "undefined") {
|
|
console.log("Client-side code");
|
|
} else {
|
|
console.log("Server-side code");
|
|
}
|
|
```
|
|
|
|
The value can also be another identifier. For example, to replace all usages of `global` with `globalThis`:
|
|
|
|
```sh
|
|
bun --define global="globalThis" src/index.ts
|
|
```
|
|
|
|
`global` is a global object in Node.js, but not in web browsers, so this replacement fixes code that assumes `global` is available.
|
|
|
|
### Replace values with JSON
|
|
|
|
`--define` can also replace values with JSON objects and arrays.
|
|
|
|
To replace all usages of `AWS` with the JSON object `{"ACCESS_KEY":"abc","SECRET_KEY":"def"}`:
|
|
|
|
```sh
|
|
# JSON
|
|
bun --define AWS='{"ACCESS_KEY":"abc","SECRET_KEY":"def"}' src/index.ts
|
|
```
|
|
|
|
Bun transforms these into the equivalent JavaScript code.
|
|
|
|
From:
|
|
|
|
```ts
|
|
console.log(AWS.ACCESS_KEY); // => "abc"
|
|
```
|
|
|
|
To:
|
|
|
|
```ts
|
|
console.log({ ACCESS_KEY: "abc", SECRET_KEY: "def" }.ACCESS_KEY);
|
|
```
|
|
|
|
### Replace values with other properties
|
|
|
|
You can also pass properties to the `--define` flag.
|
|
|
|
For example, to replace all usages of `console.write` with `console.log`:
|
|
|
|
```sh
|
|
bun --define console.write=console.log src/index.ts
|
|
```
|
|
|
|
That transforms the following input:
|
|
|
|
```ts
|
|
console.write("Hello, world!");
|
|
```
|
|
|
|
Into the following output:
|
|
|
|
```ts
|
|
console.log("Hello, world!");
|
|
```
|
|
|
|
## How is this different than setting a variable?
|
|
|
|
You can also set `process.env.NODE_ENV` to `"production"` in your code, but that doesn't help with dead code elimination. In JavaScript, property accesses can have side effects. Getters & setters can be functions, and even dynamically defined (due to prototype chains and Proxy). Even if you set `process.env.NODE_ENV` to `"production"`, static analysis tools can't assume it is still `"production"` on the next line.
|
|
|
|
## How is this different than find-and-replace or string replacement?
|
|
|
|
The `--define` flag operates on the AST (Abstract Syntax Tree), not on text. The replacement happens during transpilation, so it participates in optimizations like dead code elimination.
|
|
|
|
String replacement tools tend to have escaping issues and replace unintended parts of the code.
|