Skip to content

Define / Global Constants

define replaces identifiers with a JSON literal everywhere they appear, in both dev and build. Use it for compile-time flags and metadata that should be inlined — and dead branches tree-shaken — rather than read at runtime.

Basic usage

ts
import { defineConfig } from "vantris";

export default defineConfig({
  define: {
    __DEV__: true,
    __APP_VERSION__: "1.0.0",
  },
});

Every occurrence of the key is substituted verbatim, as a JSON literal:

ts
if (__DEV__) console.log("dev only"); // → if (true) …
console.log(__APP_VERSION__);          // → console.log("1.0.0")

Values are inlined and tree-shaken

Because the replacement is a literal, the bundler can fold constants and drop dead code. Set __DEV__: false for a production build and the guarded branch disappears entirely:

ts
// define: { __DEV__: false }
if (__DEV__) {
  expensiveDevOnlyCheck(); // removed from the production bundle
}

This makes define the idiomatic way to strip development-only code from production output.

Accepted value types

A define value is a string, number, or boolean. Each is serialised to a JSON literal and substituted:

ts
define: {
  __DEV__: false,            // boolean → false
  __MAX_ITEMS__: 100,        // number  → 100
  __APP_VERSION__: "1.0.0",  // string  → "1.0.0"
}

Strings become string literals

A string value is inserted as a JSON string, quotes included. __APP_VERSION__: "1.0.0" produces "1.0.0" in the code, not the bare token 1.0.0. To inline a raw expression (rare), you'd need to embed it as a string that already reads as code — but prefer keeping define values to plain constants.

Declaring the globals for TypeScript

TypeScript doesn't know about your injected globals, so declare them once in a .d.ts in your project:

ts
// globals.d.ts
declare const __DEV__: boolean;
declare const __APP_VERSION__: string;
declare const __MAX_ITEMS__: number;

Now __DEV__ type-checks as boolean and your editor autocompletes it.

define vs. import.meta.env

Both inline values at build time and both tree-shake dead branches. The difference is where the values come from and how they're namespaced:

defineimport.meta.env
Sourcevantris.config.ts.env files
Namingany identifier you chooseVANTRIS_-prefixed + built-ins
Mode-awaremanual✅ (files per mode)
Typical useconstants, feature flags, metadataper-environment URLs, secrets-safe flags

Use define for constants that live in your config; use import.meta.env for values that change per environment and live in .env files.

A common pattern

Inline your package version and a build timestamp:

ts
import { defineConfig } from "vantris";
import pkg from "./package.json" with { type: "json" };

export default defineConfig({
  define: {
    __APP_VERSION__: pkg.version,
    __BUILT_AT__: new Date().toISOString(),
  },
});
ts
console.log(`v${__APP_VERSION__} built ${__BUILT_AT__}`);

See the Shared Options → define reference for the exact type.

Released under the MIT License.