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:
- Check
dist/server/routes.jsonto verify entry point naming and hash patterns match yourentryNamesspecification - Examine
dist/client/to confirm source map generation or absence thereof - 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:
src/js/esbuild/esbuild.config.js– The main build script whereprocess.env.BUILDis parsed (lines 71-84) and merged into the final esbuild options (lines 44-45)src/js/esbuild/entry-points-config.js– Defines how client and server entry points are discovered and named; customentryNamesin your BUILD config directly influence this logicsrc/js/esbuild/esbuild-jsx.plugin.js– Handles JSX transformation for server bundles; advanced configurations may reference this for plugin orderingsrc/js/esbuild/esbuild-metafile.plugin.js– Generates the asset manifest mapping routes to hashed filenames; affected byentryNamesand public path settings
Summary
- The
BUILDenvironment 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.jsafter defaults are established, ensuring your values take precedence - Use
BUILDto 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, whilesxo startserves pre-built assets and ignores runtime BUILD modifications - Verify changes through the
dist/server/routes.jsonmanifest 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →