Skip to content

naveen-ithappu/esbuild-plugin-conditional-replace

esbuild-plugin-conditional-replace

A robust esbuild plugin for conditional string/regexp replacement in source files, inspired by the need for environment-driven import rewriting.

npm version License: MIT Node.js CI

Problem Statement

When building packages with esbuild, there's often a need to conditionally rewrite imports or other strings based on environment variables. Common scenarios include:

  • Environment-specific imports: Switching between stable and preview versions of packages
  • Feature flags: Enabling/disabling features based on build environment
  • Path aliases: Dynamic path resolution based on target environment
  • API endpoints: Switching between development, staging, and production endpoints

Traditional approaches have limitations:

  • esbuild-plugin-alias: Only works for module resolution, not string replacement
  • Post-processing scripts: Add complexity and don't integrate with the build pipeline
  • Custom plugins: Often fragile and don't handle edge cases properly

Installation

npm install --save-dev esbuild-plugin-conditional-replace

Quick Start

import { conditionalReplacePlugin } from 'esbuild-plugin-conditional-replace';

esbuild.build({
  entryPoints: ['src/index.ts'],
  bundle: true,
  outfile: 'dist/bundle.js',
  plugins: [
    conditionalReplacePlugin({
      filter: /\.ts$/,
      condition: () => process.env.NODE_ENV === 'production',
      replacements: [
        {
          search: /DEBUG_MODE/g,
          replace: 'false'
        }
      ]
    })
  ]
});

Use Cases

1. Environment-Specific Package Imports

Scenario: A package needs to import different versions of a dependency based on the build environment.

// Source code
import button from '@my-org/ui-components';

// When NODE_ENV=development, should become:
import button from '@my-org/ui-components/preview';
conditionalReplacePlugin({
  filter: /\.ts$/,
  condition: () => process.env.NODE_ENV === 'development',
  replacements: [
    {
      search: /from\s+['"]@my-org\/ui-components['"]/g,
      replace: "from '@my-org/ui-components/preview'"
    }
  ]
})

2. Feature Flag Integration

Scenario: Enable/disable features based on build environment.

// Source code
const featureFlag = 'ENABLE_NEW_FEATURE';

// When NODE_ENV=production, should become:
const featureFlag = 'false';

3. Dynamic API Endpoints

Scenario: Switch API endpoints based on environment.

// Source code
const API_BASE_URL = 'https://api.example.com';

// When NODE_ENV=development, should become:
const API_BASE_URL = 'https://dev-api.example.com';

API Reference

conditionalReplacePlugin(options)

Creates an esbuild plugin for conditional string replacement.

Options

  • filter (RegExp): File pattern to match for processing (default: /\.ts$/)
  • replacements (Array): Array of replacement rules
  • condition (Function): Optional function that returns boolean to determine if replacements should be applied (default: () => true)

Replacement Rules

Each replacement rule should have:

  • search (string|RegExp): Pattern to search for
  • replace (string|Function): Replacement value or function

Examples

Basic Usage

import { conditionalReplacePlugin } from 'esbuild-plugin-conditional-replace';

esbuild.build({
  entryPoints: ['src/index.ts'],
  bundle: true,
  outfile: 'dist/bundle.js',
  plugins: [
    conditionalReplacePlugin({
      filter: /\.ts$/,
      condition: () => process.env.NODE_ENV === 'production',
      replacements: [
        {
          search: /DEBUG_MODE/g,
          replace: 'false'
        }
      ]
    })
  ]
});

Multiple Replacements

import { conditionalReplacePlugin } from 'esbuild-plugin-conditional-replace';

esbuild.build({
  entryPoints: ['src/**/*.ts'],
  bundle: true,
  outdir: 'build',
  plugins: [
    conditionalReplacePlugin({
      filter: /\.ts$/,
      condition: () => process.env.NODE_ENV === 'development',
      replacements: [
        {
          search: 'https://api.example.com',
          replace: 'https://dev-api.example.com'
        },
        {
          search: /ENABLE_DEBUG/g,
          replace: 'true'
        },
        {
          search: /console\.log\(/g,
          replace: 'console.debug('
        }
      ]
    })
  ]
});

Complex Conditions

import { conditionalReplacePlugin } from 'esbuild-plugin-conditional-replace';

esbuild.build({
  entryPoints: ['src/**/*.ts'],
  bundle: true,
  outdir: 'build',
  plugins: [
    conditionalReplacePlugin({
      filter: /\.ts$/,
      condition: () => {
        return process.env.NODE_ENV === 'production' && 
               process.env.FEATURE_FLAG === 'enabled';
      },
      replacements: [
        {
          search: /FEATURE_ENABLED/g,
          replace: 'true'
        }
      ]
    })
  ]
});

Features

βœ… What Works Well

  • Conditional execution: Only applies replacements when conditions are met
  • Flexible matching: Supports both string and RegExp patterns
  • Multiple replacements: Apply multiple rules in a single plugin instance
  • File filtering: Only process files matching specified patterns
  • Pre-build transformation: Replaces strings before esbuild processes files
  • Zero dependencies: Pure JavaScript implementation
  • TypeScript support: Works seamlessly with TypeScript files
  • Source map compatibility: Preserves source maps correctly

πŸ”§ Advanced Features

  • Function-based replacement: Support for dynamic replacement values
  • Multiple file types: Process different file types with different rules
  • Environment integration: Easy integration with build tools and CI/CD
  • Performance optimized: Only processes files that match the filter

Comparison with Alternatives

Feature esbuild-plugin-conditional-replace esbuild-plugin-alias Post-processing scripts Custom plugins
String replacement βœ… ❌ βœ… βœ…
Conditional execution βœ… ❌ ❌ βœ…
Pre-build transformation βœ… βœ… ❌ βœ…
Multiple replacements βœ… ❌ βœ… βœ…
Zero dependencies βœ… ❌ βœ… βœ…
Easy integration βœ… βœ… ❌ ❌

Development

Setup

git clone https://github.com/naveen-ithappu/esbuild-plugin-conditional-replace.git
cd esbuild-plugin-conditional-replace
npm install

Build

npm run build

Test

npm test

Lint

npm run lint

Contributing

This plugin is designed to be:

  • Simple: Easy to understand and use
  • Flexible: Supports various use cases
  • Reliable: Handles edge cases properly
  • Performant: Minimal overhead during build

We welcome contributions! Please see our Contributing Guide for details.

Roadmap

  • Support for async replacement functions
  • Better error handling and reporting
  • Integration with popular build tools (Vite, Rollup)
  • Performance optimizations for large codebases
  • TypeScript type definitions

License

MIT License - feel free to use in commercial and open-source projects.

Support

About

A robust esbuild plugin for conditional string/regexp replacement in source files

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published