# How to Configure Custom esbuild Loaders for Server Builds in sxo

> Learn to configure custom esbuild loaders for server builds in sxo efficiently. Master CLI flags, env vars, and config files for seamless integration and highest precedence.

- Repository: [Víctor García/sxo](https://github.com/gc-victor/sxo)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Configure custom esbuild loaders for server builds in sxo using CLI flags, environment variables, or a configuration file, with CLI flags taking highest precedence over all other sources.**

When bundling server-side code, sxo uses esbuild to process non-JavaScript assets like SVGs, CSS files, and images. Understanding how to configure custom esbuild loaders for server builds ensures these assets are handled correctly during the server compilation phase, whether you need to inline them as text, copy them as files, or apply other transformations.

## Configuration Sources for Server Loaders

sxo collects the loader configuration from three distinct sources before merging them into the final build. The framework processes these through `resolveRuntimeConfig()` → `readEnvConfig()` → `normalizeConfig()` in [`src/js/config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/config.js).

### Command-Line Flags

Pass the `--loaders` flag to `sxo dev` or `sxo build` to specify extension-to-loader mappings directly. Each flag instance defines one mapping, and the CLI parser stores these in `flags.loaders` before processing them through `parseLoadersString()` (see [`src/js/config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/config.js), lines 44-54).

### Environment Variables

Set the `LOADERS` environment variable to a JSON string containing your extension mappings. The framework reads this in [`src/js/config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/config.js) (lines 31-84) and re-exports it through [`src/js/constants.js`](https://github.com/gc-victor/sxo/blob/main/src/js/constants.js) (lines 16-28). This method is useful for containerized deployments or CI/CD pipelines.

### Configuration File

Define persistent loader settings in [`sxo.config.js`](https://github.com/gc-victor/sxo/blob/main/sxo.config.js) or [`sxo.config.json`](https://github.com/gc-victor/sxo/blob/main/sxo.config.json) using the `loaders` object. The framework loads this via `resolveRuntimeConfig()` (lines 5-13 of [`src/js/config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/config.js)) and normalizes it alongside other sources.

## Configuration Precedence Order

According to `normalizeConfig()` in [`src/js/config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/config.js) (lines 69-97), sxo merges loader definitions using a strict hierarchy (highest to lowest):

1. **CLI flags** (`--loaders`)
2. **Configuration file** ([`sxo.config.js`](https://github.com/gc-victor/sxo/blob/main/sxo.config.js) or [`sxo.config.json`](https://github.com/gc-victor/sxo/blob/main/sxo.config.json))
3. **Environment variables** (`LOADERS`)
4. **Default values**

## How Loaders Are Applied to Server Builds

After resolution, the final loader map is exported as `LOADERS` from [`src/js/constants.js`](https://github.com/gc-victor/sxo/blob/main/src/js/constants.js) (lines 16-28). During the server build process, [`src/js/esbuild/esbuild.config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/esbuild.config.js) injects this map directly into esbuild's configuration (lines 61-62):

```javascript
// src/js/esbuild/esbuild.config.js
loader: serverLoaders,   // ← custom loaders for the server build

```

This ensures that any asset imported in your server code is processed according to your custom rules.

## Practical Configuration Examples

### Using a .env File

Create a `.env` file at your project root to configure loaders via environment variables. The value must be valid JSON with escaped backslashes for regex patterns:

```text

# .env

LOADERS='{"\\.svg":"file","\\.css":"text"}'

```

When you run `sxo dev` or `sxo build`, the environment is read, parsed (see [`src/js/constants.js`](https://github.com/gc-victor/sxo/blob/main/src/js/constants.js), lines 21-25), and applied to the server build.

### Specifying Loaders via CLI

Use multiple `--loaders` flags to define mappings on the command line. This overrides settings from other sources:

```bash

# Treat SVG files as file assets and CSS as text

sxo dev --loaders ".svg=file" --loaders ".css=text"

```

### Defining Loaders in sxo.config.js

For project-wide settings, create a [`sxo.config.js`](https://github.com/gc-victor/sxo/blob/main/sxo.config.js) file:

```javascript
// sxo.config.js
export default {
  loaders: {
    ".svg": "file",
    ".css": "text",
  },
};

```

The config is loaded by `resolveRuntimeConfig()` and normalized alongside environment and flag values.

### Combining Multiple Sources

When mixing sources, sxo merges them according to precedence rules. Consider this scenario:

```bash

# .env contains: LOADERS='{"\\.png":"file"}'

# Run with an additional loader via flag

sxo build --loaders ".svg=file"

```

The resulting loader map becomes `{ ".png": "file", ".svg": "file" }`, with the CLI flag ensuring `.svg` uses the file loader while preserving the environment variable's `.png` configuration.

## Summary

- sxo supports three methods to configure custom esbuild loaders for server builds: **CLI flags** (`--loaders`), the **`LOADERS` environment variable**, and the **`loaders` field** in [`sxo.config.js`](https://github.com/gc-victor/sxo/blob/main/sxo.config.js).
- Configuration precedence follows: **flags > config file > environment > defaults**, as implemented in [`src/js/config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/config.js).
- The resolved map is exported from [`src/js/constants.js`](https://github.com/gc-victor/sxo/blob/main/src/js/constants.js) and injected into the server build via [`src/js/esbuild/esbuild.config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/esbuild.config.js).
- Use CLI flags for temporary overrides during development and configuration files for persistent project-wide settings.

## Frequently Asked Questions

### What file formats can I configure with custom loaders?

You can configure any file extension that esbuild supports, including `.svg`, `.css`, `.png`, `.jpg`, `.json`, and `.txt`. The loader value must be a valid esbuild loader type such as `file`, `text`, `json`, `base64`, or `dataurl`.

### Which configuration method overrides the others?

Command-line flags take the highest precedence, followed by configuration file settings, then environment variables, and finally built-in defaults. This hierarchy is enforced by the `normalizeConfig()` function in [`src/js/config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/config.js) (lines 69-97).

### How do I escape special characters in the LOADERS environment variable?

When using the `LOADERS` environment variable, escape backslashes in the JSON string by doubling them. For example, use `\\.` to represent a literal dot in file extension patterns, as shown in `LOADERS='{"\\.svg":"file"}'`.

### Where is the final loader configuration used in the build process?

The final loader map is exported as `LOADERS` from [`src/js/constants.js`](https://github.com/gc-victor/sxo/blob/main/src/js/constants.js) (lines 16-28) and passed to esbuild via the `loader` property in [`src/js/esbuild/esbuild.config.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/esbuild.config.js) (lines 61-62), specifically targeting the server-side bundle generation.