How to Optimize Production Builds with Custom esbuild Configuration in SXO

SXO exposes its internal esbuild pipeline through the BUILD environment variable, allowing you to inject any valid esbuild option that overrides defaults at runtime before the client-side bundle is generated.

SXO ships with a built-in esbuild pipeline that automatically handles minification, hashing, and server-side rendering (SSR) wiring. While the default configuration in gc-victor/sxo handles most production scenarios, the architecture allows fine-grained control through environment-based configuration injection without modifying core source files.

Understanding the Built-in esbuild Pipeline

The build system centers around src/js/esbuild/esbuild.config.js. This script assembles a default configuration object that includes sensible production defaults: minify: true, conditional sourcemaps based on development mode, entry-name patterns, public path resolution, and internal plugins for JSX and metafile generation.

When you run sxo build or sxo dev, the pipeline executes an esbuild process that bundles client assets while preserving the SSR module structure required by the framework.

Using the BUILD Environment Variable to Override Defaults

SXO exposes an extension point through the BUILD environment variable. The system reads process.env.BUILD at lines 71-84 of src/js/esbuild/esbuild.config.js, parses the value as JSON, and stores it in a buildConfig variable. Immediately after the default configuration is assembled, the code spreads buildConfig into the final options object at lines 44-45:

// Simplified excerpt from esbuild.config.js
const buildConfig = process.env.BUILD ? JSON.parse(process.env.BUILD) : {};
// ... default config assembly ...
await esbuild.build({
  ...defaultConfig,
  ...buildConfig, // Your overrides take precedence here
});

Because the spread operation occurs after all defaults are defined, any property you provide will override the built-in settings.

Common Override Scenarios for Production Optimization

Goal BUILD JSON Value Effect
Disable minification for debugging {"minify":false} Removes code compression while preserving other optimizations
Adjust hashing strategy {"entryNames":"[dir]/[name]"} Eliminates content hashes for deterministic builds across deployments
Externalize large dependencies {"external":["react","react-dom"]} Prevents bundling of libraries served via CDN, reducing bundle size
Enable source maps {"sourcemap":true} Generates separate .map files for production debugging
Inject compile-time constants {"define":{"process.env.API_URL":"\"https://api.example.com\""}} Bakes environment variables into the bundle without client-side exposure

Practical Implementation Examples

Quick One-Liner for Debugging

For immediate feedback during debugging sessions, pass a raw JSON string directly to the build command:

BUILD='{"minify":false}' sxo build

This disables minification temporarily without creating persistent configuration files.

Full Custom Configuration File

Create a build-config.json for complex, reusable configurations:

{
  "minify": false,
  "sourcemap": true,
  "entryNames": "[dir]/[name]",
  "external": ["react", "react-dom"],
  "loader": {
    "\\.svg$": "text"
  },
  "define": {
    "process.env.API_URL": "\"https://api.example.com\""
  }
}

Execute the build by exporting the file contents into the environment variable:

BUILD=$(cat build-config.json) sxo build

Reproducible Build Script for CI/CD

For production pipelines requiring consistent, documented configurations:

#!/usr/bin/env bash

# build-prod.sh – Reproducible production build with custom esbuild options

CONFIG=$(cat <<'EOF'
{
  "minify": true,
  "sourcemap": false,
  "entryNames": "[dir]/[name].[hash]",
  "publicPath": "/static/",
  "loader": { "\\.png$": "file" }
}
EOF
)

BUILD="$CONFIG" sxo build

Verifying Your Configuration Changes

After executing a custom build, inspect the generated assets to confirm your overrides took effect:

  1. Check dist/server/routes.json to verify entry point naming and hash patterns match your entryNames specification
  2. Examine dist/client/ to confirm source map generation or absence thereof
  3. Review bundle sizes to validate externalization of specified dependencies

To debug the effective configuration during development, temporarily add console.log(buildConfig) after line 73 in src/js/esbuild/esbuild.config.js to visualize the merged object before it reaches esbuild.

Key Source Files for Reference

Understanding these core files helps when crafting custom configurations:

Summary

  • The BUILD environment variable accepts raw JSON that overrides any default esbuild option in SXO's pipeline
  • Configuration merging happens at runtime in src/js/esbuild/esbuild.config.js after defaults are established, ensuring your values take precedence
  • Use BUILD to disable minification for debugging, adjust hashing strategies, externalize dependencies, or inject compile-time constants
  • Production builds (sxo build) honor these settings during the asset generation phase, while sxo start serves pre-built assets and ignores runtime BUILD modifications
  • Verify changes through the dist/server/routes.json manifest and generated client assets

Frequently Asked Questions

What is the BUILD environment variable in SXO?

The BUILD environment variable is a runtime configuration hook exposed by SXO that accepts a JSON string representing valid esbuild options. When present, the build pipeline parses this value in src/js/esbuild/esbuild.config.js and deep-merges it into the default esbuild configuration, allowing override of minification, entry naming, source maps, and loader behavior without modifying source code.

How do I disable minification for debugging production builds?

Pass {"minify":false} through the BUILD variable: BUILD='{"minify":false}' sxo build. This preserves all other production optimizations while removing code obfuscation, making stack traces and bundle inspection meaningful during debugging sessions.

Can I use the BUILD environment variable in development mode?

Yes. The BUILD variable is read unconditionally in src/js/esbuild/esbuild.config.js, meaning it affects both sxo dev and sxo build commands. However, since development mode typically enables inline source maps and disables minification by default, you will most commonly use BUILD overrides for production-specific tuning or specialized local debugging scenarios.

Where does SXO merge custom esbuild options into the configuration?

The merge occurs in src/js/esbuild/esbuild.config.js at two critical points: first, the raw JSON is parsed from process.env.BUILD between lines 71-84 and stored as buildConfig; second, this object is spread into the final esbuild options at lines 44-45, immediately after the default configuration object is assembled. This ordering ensures custom properties override SXO's built-in defaults.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →