A robust esbuild plugin for conditional string/regexp replacement in source files, inspired by the need for environment-driven import rewriting.
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
npm install --save-dev esbuild-plugin-conditional-replaceimport { 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'
}
]
})
]
});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'"
}
]
})Scenario: Enable/disable features based on build environment.
// Source code
const featureFlag = 'ENABLE_NEW_FEATURE';
// When NODE_ENV=production, should become:
const featureFlag = 'false';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';Creates an esbuild plugin for conditional string replacement.
filter(RegExp): File pattern to match for processing (default:/\.ts$/)replacements(Array): Array of replacement rulescondition(Function): Optional function that returns boolean to determine if replacements should be applied (default:() => true)
Each replacement rule should have:
search(string|RegExp): Pattern to search forreplace(string|Function): Replacement value or function
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'
}
]
})
]
});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('
}
]
})
]
});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'
}
]
})
]
});- 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
- 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
| 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 | β | β | β | β |
git clone https://github.com/naveen-ithappu/esbuild-plugin-conditional-replace.git
cd esbuild-plugin-conditional-replace
npm installnpm run buildnpm testnpm run lintThis 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.
- 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
MIT License - feel free to use in commercial and open-source projects.
- π Documentation
- π Report a Bug
- π‘ Request a Feature
- π€ Contributing