Replace strings in files while bundling them with Rollup
npx @tessl/cli install tessl/npm-rollup-plugin-replace@1.2.0Rollup Plugin Replace is a Rollup plugin that performs string replacement during the bundling process. It allows developers to replace specific strings or patterns in their code at build time, making it ideal for environment variable injection, build-time configuration, and conditional compilation scenarios.
npm install --save-dev rollup-plugin-replaceimport replace from 'rollup-plugin-replace';For CommonJS:
const replace = require('rollup-plugin-replace');// rollup.config.js
import replace from 'rollup-plugin-replace';
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'iife'
},
plugins: [
replace({
ENVIRONMENT: JSON.stringify('production'),
VERSION: JSON.stringify('1.0.0')
})
]
};Important: The replace plugin should be placed before other plugins (like rollup-plugin-commonjs) in your plugins array to allow those plugins to apply optimizations such as dead code removal.
The plugin operates through a simple but effective architecture:
The plugin's core algorithm escapes special characters in both delimiters and replacement keys, ensuring reliable pattern matching even with complex replacement scenarios.
Creates a Rollup plugin instance configured for string replacement.
/**
* Creates a Rollup plugin for string replacement during bundling
* @param options - Configuration object for replacement settings
* @returns Rollup plugin object with name and transform methods
*/
function replace(options = {}): RollupPlugin;
interface RollupPlugin {
/** Plugin identifier */
name: string;
/** Transform function that processes file contents */
transform(code: string, id: string): TransformResult | null;
}
interface TransformResult {
/** Transformed code */
code: string;
/** Source map (if sourceMap option is not false) */
map?: object;
}The options object supports the following properties:
interface ReplaceOptions {
/** Minimatch pattern or array of patterns for files to include */
include?: string | string[];
/** Minimatch pattern or array of patterns for files to exclude */
exclude?: string | string[];
/** Custom delimiters for replacement patterns [prefix, suffix] */
delimiters?: [string, string];
/** Whether to generate source maps (default: true) */
sourceMap?: boolean;
/** Object containing replacement key-value pairs */
values?: { [key: string]: string | ReplacementFunction };
/** Direct replacement properties (when values is not specified) */
[key: string]: string | ReplacementFunction | any;
}
type ReplacementFunction = (id: string) => string;Usage Examples:
// Basic string replacements
replace({
ENVIRONMENT: JSON.stringify('production'),
API_URL: JSON.stringify('https://api.example.com')
})
// File filtering
replace({
include: 'src/**/*.js',
exclude: 'node_modules/**',
DEBUG: 'false'
})
// Custom delimiters
replace({
delimiters: ['<@', '@>'],
VERSION: '1.0.0'
// Replaces <@VERSION@> instead of VERSION
})
// Function-based replacements
replace({
__dirname: (id) => `'${path.dirname(id)}'`,
__filename: (id) => `'${id}'`
})
// Using values object
replace({
include: '**/*.js',
sourceMap: false,
values: {
ENVIRONMENT: JSON.stringify('development'),
DEBUG: 'true'
}
})
// Special characters in replacement keys
replace({
"require('config')": "require('./config-prod')",
"process.env.NODE_ENV": JSON.stringify('production')
})Control which files are processed using include/exclude patterns:
interface FileFilterOptions {
/** Include files matching these minimatch patterns */
include?: string | string[];
/** Exclude files matching these minimatch patterns */
exclude?: string | string[];
}include is omitted, all files are processed by defaultexclude patterns take precedence over include patternsCustomize the delimiters used for pattern matching:
interface DelimiterOptions {
/** Custom delimiters as [prefix, suffix] array */
delimiters?: [string, string];
}['', ''] (matches exact strings)delimiters: ['<@', '@>']Define what strings should be replaced and their replacement values:
type ReplacementValue = string | ReplacementFunction;
type ReplacementFunction = (id: string) => string;
interface ReplacementConfig {
/** Organized replacement values */
values?: { [key: string]: ReplacementValue };
/** Direct replacement properties (merged with options) */
[key: string]: ReplacementValue | any;
}Replacement Types:
Static strings: Direct string replacement
{ API_URL: JSON.stringify('https://api.prod.com') }Function replacements: Dynamic replacement based on file ID
{ __dirname: (id) => `'${path.dirname(id)}'` }Special characters: Keys can contain regex special characters
{ "require('dev-config')": "require('prod-config')" }Control source map generation for replaced content:
interface SourceMapOptions {
/** Whether to generate source maps (default: true) */
sourceMap?: boolean;
}sourceMap: false to disable source map generationreplace({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
'process.env.API_URL': JSON.stringify(
process.env.NODE_ENV === 'production'
? 'https://api.prod.com'
: 'https://api.dev.com'
)
})replace({
'__DEV__': process.env.NODE_ENV !== 'production',
'__PROD__': process.env.NODE_ENV === 'production'
})replace({
'__filename': (id) => `'${path.relative(process.cwd(), id)}'`,
'__dirname': (id) => `'${path.relative(process.cwd(), path.dirname(id))}'`
})replace({
BUILD_VERSION: JSON.stringify(require('./package.json').version),
BUILD_DATE: JSON.stringify(new Date().toISOString()),
COMMIT_HASH: JSON.stringify(process.env.GIT_COMMIT || 'unknown')
})interface RollupPlugin {
/** Plugin identifier, always 'replace' */
name: string;
/**
* Transform function that processes file contents
* @param code - Source code of the file
* @param id - File path/identifier
* @returns Transform result or null if no changes
*/
transform(code: string, id: string): TransformResult | null;
}
interface TransformResult {
/** Transformed source code */
code: string;
/** Source map object (if sourceMap is not false) */
map?: object;
}
interface ReplaceOptions {
/** File inclusion patterns */
include?: string | string[];
/** File exclusion patterns */
exclude?: string | string[];
/** Custom replacement delimiters */
delimiters?: [string, string];
/** Source map generation flag */
sourceMap?: boolean;
/** Replacement values object */
values?: { [key: string]: string | ReplacementFunction };
/** Direct replacement properties */
[key: string]: any;
}
type ReplacementFunction = (id: string) => string;