SWC Feature Flags
A two-phase feature flag system for SWC that provides build-time marking and runtime dead code elimination.
Overview
This library enables powerful feature flag management with aggressive dead code elimination. It works in two phases:
- Build-time (SWC Plugin): Marks feature flag usage locations by replacing flag identifiers with
__SWC_FLAGS__markers - Runtime (Standalone Crate): Substitutes flag values and eliminates dead code branches
Features
- ✅ Multiple usage patterns: Direct destructuring, indirect destructuring, and property access
- ✅ Customizable function names: Not hardcoded to specific function names
- ✅ Scope-safe: Uses SWC's
Idsystem to handle variable shadowing correctly - ✅ Dead code elimination: Removes unreachable code branches
- ✅ Statistics tracking: Reports bytes removed and branches eliminated
- ✅ Minifier-safe markers: Uses
__SWC_FLAGS__pattern that minifiers preserve
Architecture
Phase 1: Build-Time Transformation
The build-time plugin (@swc/plugin-feature-flags) performs these transformations:
Input:
import from '@their/library';
Output:
The plugin:
- Tracks imports from configured libraries
- Detects destructuring from configured flag functions
- Replaces flag identifiers with
__SWC_FLAGS__.flagNamemarkers - Removes import statements and hook calls
Supported Usage Patterns
The build-time plugin supports multiple ways of accessing feature flags:
Pattern 1: Direct Destructuring
import from '@their/library';
const = ;
if
Pattern 2: Indirect Destructuring
import from '@their/library';
const flags = ;
const = flags;
if
Pattern 3: Property Access
import from '@their/library';
const flags = ;
if
All three patterns are transformed identically and can be mixed in the same file.
Phase 2: Runtime Transformation
The runtime transformer substitutes flag values and eliminates dead code:
Input (from Phase 1):
Runtime Config:
Output:
Installation
Rust API
Add to your Cargo.toml:
[]
= "0.1"
SWC Plugin (WASM)
Usage
Rust API
use ;
use HashMap;
use resolver;
use Mark;
// Build-time configuration
let mut libraries = new;
libraries.insert;
let build_config = BuildTimeConfig ;
// Apply resolver first (required for scope safety)
let unresolved_mark = new;
let top_level_mark = new;
program = program.apply;
// Apply build-time pass
program = program.apply;
// Runtime configuration
let mut flag_values = new;
flag_values.insert;
flag_values.insert;
let runtime_config = RuntimeConfig ;
// Apply runtime pass
program = program.apply;
SWC Plugin (.swcrc)
Configuration
Build-Time Config
interface BuildTimeConfig {
/** Library configurations: library name -> config */
libraries: Record<string, LibraryConfig>;
/** Global object name for markers (default: "__SWC_FLAGS__") */
markerObject?: string;
}
interface LibraryConfig {
/** Function names to detect (e.g., ["useExperimentalFlags"]) */
functions: string[];
}
Runtime Config
Dead Code Elimination
The runtime transformer eliminates:
If Statements
// Input
if else
// Output
console.log;
Ternary Expressions
// Input
const result = __SWC_FLAGS__. ? 'On' : 'Off'; // false
// Output
const result = 'Off';
Logical Operators
// Input
const a = __SWC_FLAGS__. && ; // true
const b = __SWC_FLAGS__. && ; // false
const c = __SWC_FLAGS__. || ; // true
// Output
const a = ;
const b = false;
const c = true;
Negation
// Input
const notA = !__SWC_FLAGS__.; // true
// Output
const notA = false;
Scope Safety
The library uses SWC's Id system (symbol + syntax context) to handle variable shadowing correctly:
import from '@their/library';
Output:
Statistics
When collect_stats is enabled, the runtime transformer tracks:
Testing
# Run all tests
# Run fixture tests only
License
Apache-2.0
Contributing
Contributions are welcome! Please ensure:
- All tests pass
- Code follows Rust formatting guidelines
- New features include tests