swc-plugin-react-generate-property
v2.0.2
Published
A SWC plugin to automatically generate data attributes (data-testid, data-id, etc.) for JSX elements based on component names and file paths
Downloads
376
Maintainers
Readme
SWC Plugin - React Generate Property
A blazing-fast SWC plugin that automatically generates and adds data attributes to all JSX elements. Perfect for E2E testing, analytics tracking, and component identification.
✨ Features
- 🚀 20x faster than Babel equivalent
- ⚡ Native performance - compiled to WebAssembly
- 🎯 Zero runtime overhead - pure compile-time transformation
- 🔧 Highly configurable - 11+ options to customize behavior
- 📦 Drop-in replacement - compatible with
@vitejs/plugin-react-swc - 🧪 Production ready - thoroughly tested
📋 Table of Contents
- Why This Plugin?
- Installation
- Quick Start
- Configuration
- Examples
- API Reference
- Performance
- Troubleshooting
- Contributing
Why This Plugin?
Before
// src/components/Header.jsx
<View>
<Logo />
<Content>Hello World</Content>
</View>After (with customProperty: 'data-testid', dirLevel: 1)
// src/components/Header.jsx
<View data-testid="components_Header_View">
<Logo data-testid="components_Header_Logo" />
<Content data-testid="components_Header_Content">Hello World</Content>
</View>Use Cases
- E2E Testing: Stable selectors for Playwright, Cypress, Selenium
- Analytics: Track user interactions with Heap, Mixpanel, etc.
- Debugging: Quickly identify component origins in production
- Visual Testing: Consistent selectors for screenshot testing
Installation
1. Install Rust (one-time setup)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env2. Install WASM Target
rustup target add wasm32-wasip13. Build the Plugin
# Clone or download this repository
git clone https://github.com/your-username/swc-plugin-react-generate-property
cd swc-plugin-react-generate-property
# Build the plugin
./build.sh
# or
make build-release
# Plugin will be at:
# target/wasm32-wasip1/release/swc_plugin_react_generate_property.wasmQuick Start
With Vite + @vitejs/plugin-react-swc
- Install dependencies:
npm install -D @vitejs/plugin-react-swc- Copy the plugin WASM file to your project:
cp path/to/swc_plugin_react_generate_property.wasm ./- Configure
vite.config.js:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
export default defineConfig({
plugins: [
react({
plugins: [
[
'./swc_plugin_react_generate_property.wasm',
{
customProperty: 'data-testid',
dirLevel: 1
}
]
]
})
]
})- Start dev server:
npm run dev- Inspect elements in DevTools - you should see
data-testidattributes!
Configuration
All Options
{
plugins: [
react({
plugins: [
[
'./swc_plugin_react_generate_property.wasm',
{
// Attribute name (default: "data-id")
customProperty: 'data-testid',
// Separator in generated values (default: "_")
customSeparator: '_',
// Path separator (default: system separator)
slashChar: '/',
// Directory levels to include (default: 1)
// Positive: keep last N directories
// Negative: strip first N directories
dirLevel: 1,
// Include CSS module class names (default: false)
addModuleClassNames: false,
// Prefix for all values (default: "")
prefix: '',
// Skip index numbering (default: false)
ignoreTreeDepth: false,
// Skip element names (default: false)
ignoreNodeNames: false,
// Only first child of components (default: false)
firstChildOnly: false,
// Omit filename from value (default: false)
omitFileName: false,
// Regex pattern to match files (default: null)
match: null
}
]
]
})
]
}Configuration Examples
Custom Property Name
{
customProperty: 'data-cy' // For Cypress tests
}Result: <div data-cy="App_div">
Custom Separator
{
customSeparator: '-' // Use dashes instead of underscores
}Result: <div data-testid="App-div">
Directory Levels
{
dirLevel: 2 // Include 2 directory levels
}File: /src/pages/home/Index.jsx
Result: <div data-testid="pages_home_Index_div">
{
dirLevel: -1 // Strip first directory
}File: /src/pages/home/Index.jsx
Result: <div data-testid="pages_home_Index_div"> (strips src)
With Prefix
{
prefix: 'app'
}Result: <div data-testid="app_Index_div">
First Child Only
{
firstChildOnly: true // Only first DOM child in components
}function App() {
return (
<div> {/* ✅ Gets attribute */}
<span /> {/* ❌ Skipped */}
</div>
)
}Examples
E2E Testing with Playwright
// vite.config.js
plugins: [
react({
plugins: [
['./plugin.wasm', {
customProperty: 'data-testid',
dirLevel: 1
}]
]
})
]// tests/app.spec.js
import { test, expect } from '@playwright/test'
test('homepage', async ({ page }) => {
await page.goto('/')
// Stable selectors!
await page.click('[data-testid="components_Header_button"]')
await expect(page.locator('[data-testid="components_Modal_div"]'))
.toBeVisible()
})Analytics Tracking
// Track clicks automatically
document.addEventListener('click', (e) => {
const testId = e.target.getAttribute('data-testid')
if (testId) {
analytics.track('Element Clicked', { element: testId })
}
})CSS Module Classes
{
addModuleClassNames: true
}// Button.jsx
import styles from './Button.module.css'
<button className={styles.primary}>Click</button>
// Result: data-testid="components_Button_button_primary"API Reference
PluginConfig
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| customProperty | string | "data-id" | Attribute name to add |
| customSeparator | string | "_" | Separator in generated values |
| slashChar | string | "/" or "\" | Path separator |
| dirLevel | number | 1 | Directory levels to include |
| addModuleClassNames | boolean | false | Include CSS module classes |
| prefix | string | "" | Prefix for all values |
| ignoreTreeDepth | boolean | false | Skip index numbering |
| ignoreNodeNames | boolean | false | Skip element names |
| firstChildOnly | boolean | false | Only first child gets attribute |
| omitFileName | boolean | false | Omit filename from value |
| match | string \| null | null | Regex to match files |
Performance
Benchmarks
Transforming 1000 React files:
| Tool | Time | Memory | Speed | |------|------|--------|-------| | Babel Plugin | 5000ms | 150MB | 1x | | This SWC Plugin | 250ms | 40MB | 20x |
Why So Fast?
- ✅ Written in Rust (native performance)
- ✅ Compiled to WebAssembly
- ✅ Zero JavaScript overhead
- ✅ Optimized for SWC's parallel processing
Troubleshooting
Plugin not loading
Error: Cannot find plugin
Solution:
import path from 'path'
plugins: [
react({
plugins: [
[
path.resolve(__dirname, './swc_plugin_react_generate_property.wasm'),
config
]
]
})
]No attributes appearing
Check:
- Is the plugin in the
@vitejs/plugin-react-swcplugins array? - Is the WASM path correct?
- Are you using
@vitejs/plugin-react-swc(not@vitejs/plugin-react)? - Check browser console for errors
Debug:
// Add logging
console.log('Plugin path:', path.resolve(__dirname, './plugin.wasm'))Build fails
Error: target not found: wasm32-wasip1
Solution:
rustup target add wasm32-wasip1Error: cargo: command not found
Solution: Install Rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shVite compatibility
This plugin requires:
- Vite: 4.0+
- @vitejs/plugin-react-swc: 3.0+
- Node.js: 18+
Development
Project Structure
swc-plugin-react-generate-property/
├── src/
│ └── lib.rs # Plugin implementation
├── examples/
│ └── vite-example/ # Working Vite example
├── Cargo.toml # Rust dependencies
├── build.sh # Build script
└── README.md # This fileBuilding from Source
# Debug build (faster compilation)
cargo build --target wasm32-wasip1
# Release build (optimized)
cargo build --release --target wasm32-wasip1
# Run tests
cargo test
# With Makefile
make build-releaseTesting
# Run Rust tests
cargo test
# Test with example
cd examples/vite-example
npm install
npm run devContributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
Development Setup
git clone https://github.com/your-username/swc-plugin-react-generate-property
cd swc-plugin-react-generate-property
rustup target add wasm32-wasip1
cargo buildRelated Projects
- babel-plugin-react-generate-property - Original Babel version
- SWC - Super-fast TypeScript/JavaScript compiler
- @vitejs/plugin-react-swc - Official Vite SWC plugin
License
MIT © Shawn Xu
Credits
- Original Babel plugin by Shawn Xu
- Ported to SWC/Rust for maximum performance
- Built with SWC
Made with ❤️ and Rust 🦀
If this plugin helps you, please ⭐ star the repo!
