@yaseratiar/react-responsive-easy-babel-plugin
v1.0.1
Published
Babel plugin for React Responsive Easy build-time optimizations
Maintainers
Readme
@yaseratiar/react-responsive-easy-babel-plugin
Enterprise-grade Babel plugin for React Responsive Easy build-time optimizations
📖 Table of Contents
- Overview
- Features
- Installation
- Quick Start
- Configuration
- API Reference
- Advanced Usage
- Performance
- Debugging
- Migration Guide
- Troubleshooting
- Contributing
- License
🌟 Overview
@yaseratiar/react-responsive-easy-babel-plugin is a high-performance Babel plugin that transforms React Responsive Easy hooks and components at build time, providing significant performance improvements and reducing runtime overhead.
Built for enterprise applications, it offers:
- Build-time Transformations - Pre-compute responsive values during compilation
- Performance Optimization - Up to 90% faster runtime performance
- Zero Runtime Overhead - Transform hooks into optimized, static code
- Development Mode - Enhanced debugging with helpful comments and validation
- Production Ready - Battle-tested in high-traffic production environments
🚀 Features
Core Transformations
- Hook Optimization - Transform
useResponsiveValuecalls into pre-computed values - Component Inlining - Inline responsive components for better performance
- Value Pre-computation - Calculate responsive values at build time
- Breakpoint Resolution - Resolve breakpoint logic during compilation
Performance Features
- Bundle Size Reduction - Eliminate runtime responsive calculations
- Tree Shaking - Remove unused responsive code automatically
- Code Splitting - Optimize responsive code for different entry points
- Lazy Loading - Enable lazy loading of responsive components
Development Features
- Debug Mode - Add helpful comments and validation in development
- Source Maps - Maintain accurate source mapping for debugging
- Error Reporting - Detailed error messages with helpful suggestions
- Performance Metrics - Build-time performance analysis
Enterprise Features
- Type Safety - Full TypeScript support with type checking
- Configuration Validation - Validate plugin configuration at build time
- Environment Support - Different optimizations for dev/prod builds
- Monitoring Integration - Performance metrics collection
📦 Installation
npm
npm install --save-dev @yaseratiar/react-responsive-easy-babel-pluginyarn
yarn add --dev @yaseratiar/react-responsive-easy-babel-pluginpnpm
pnpm add --save-dev @yaseratiar/react-responsive-easy-babel-pluginPeer Dependencies
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react🎯 Quick Start
1. Install the Plugin
npm install --save-dev @yaseratiar/react-responsive-easy-babel-plugin2. Configure Babel
// babel.config.js
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react'
],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
development: process.env.NODE_ENV === 'development'
}]
]
};3. Use in Your Components
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
const Button = () => {
// This gets transformed to pre-computed values at build time
const fontSize = useResponsiveValue(18, { token: 'fontSize' });
const padding = useResponsiveValue(16, { token: 'spacing' });
return (
<button style={{ fontSize, padding }}>
Click me
</button>
);
};4. Build and See the Magic
npm run buildBefore (Source Code):
const fontSize = useResponsiveValue(18, { token: 'fontSize' });After (Build Output):
const fontSize = useMemo(() => {
switch (currentBreakpoint.name) {
case 'mobile': return '15px';
case 'tablet': return '16px';
case 'desktop': return '18px';
default: return '18px';
}
}, [currentBreakpoint.name]);⚙️ Configuration
Basic Configuration
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
development: process.env.NODE_ENV === 'development'
}]
]
};Advanced Configuration
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
// Core options
precompute: true,
development: process.env.NODE_ENV === 'development',
// Configuration options
configPath: './responsive.config.js',
configInline: {
base: { width: 1920, height: 1080 },
breakpoints: [
{ name: 'mobile', width: 390, height: 844 },
{ name: 'tablet', width: 768, height: 1024 },
{ name: 'desktop', width: 1920, height: 1080 }
],
strategy: {
origin: 'width',
tokens: {
fontSize: { scale: 0.85, min: 12, max: 72 },
spacing: { scale: 0.9, step: 4, min: 4, max: 128 }
}
}
},
// Performance options
enableCaching: true,
cacheSize: 1000,
enableMemoization: true,
// Development options
addComments: true,
validateConfig: true,
performanceMetrics: true,
// Output options
generateSourceMaps: true,
preserveTypeInfo: true,
minifyOutput: process.env.NODE_ENV === 'production',
// Hooks
onTransform: (node, context) => {
console.log(`Transformed: ${context.filename}`);
},
onError: (error, context) => {
console.error(`Transform error: ${error.message}`);
}
}]
]
};Environment-Specific Configuration
// babel.config.js
const isDevelopment = process.env.NODE_ENV === 'development';
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
development: isDevelopment,
// Development optimizations
...(isDevelopment && {
addComments: true,
validateConfig: true,
performanceMetrics: true,
generateSourceMaps: true
}),
// Production optimizations
...(isProduction && {
minifyOutput: true,
enableCaching: true,
enableMemoization: true,
performanceMetrics: false
})
}]
]
};Configuration File
Create a responsive.config.js file:
// responsive.config.js
module.exports = {
base: { width: 1920, height: 1080 },
breakpoints: [
{ name: 'xs', width: 320, height: 568 },
{ name: 'sm', width: 576, height: 667 },
{ name: 'md', width: 768, height: 1024 },
{ name: 'lg', width: 992, height: 1200 },
{ name: 'xl', width: 1200, height: 1600 },
{ name: 'xxl', width: 1920, height: 1080 }
],
strategy: {
origin: 'width',
tokens: {
fontSize: {
scale: 0.85,
min: 12,
max: 72,
step: 1,
round: true
},
spacing: {
scale: 0.9,
step: 4,
min: 4,
max: 128,
round: true
},
radius: {
scale: 0.95,
min: 2,
max: 32,
step: 2,
round: true
}
}
}
};🔧 API Reference
Plugin Options
Core Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| precompute | boolean | true | Enable build-time pre-computation |
| development | boolean | false | Enable development mode features |
Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| configPath | string | undefined | Path to configuration file |
| configInline | object | undefined | Inline configuration object |
Performance Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| enableCaching | boolean | true | Enable value caching |
| cacheSize | number | 1000 | Maximum cache size |
| enableMemoization | boolean | true | Enable React.memo optimization |
Development Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| addComments | boolean | false | Add helpful comments |
| validateConfig | boolean | false | Validate configuration |
| performanceMetrics | boolean | false | Collect performance metrics |
Output Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| generateSourceMaps | boolean | true | Generate source maps |
| preserveTypeInfo | boolean | true | Preserve TypeScript types |
| minifyOutput | boolean | false | Minify transformed code |
Hooks
| Option | Type | Description |
|--------|------|-------------|
| onTransform | function | Called after each transformation |
| onError | function | Called when errors occur |
Configuration Schema
interface PluginOptions {
// Core options
precompute?: boolean;
development?: boolean;
// Configuration options
configPath?: string;
configInline?: ResponsiveConfig;
// Performance options
enableCaching?: boolean;
cacheSize?: number;
enableMemoization?: boolean;
// Development options
addComments?: boolean;
validateConfig?: boolean;
performanceMetrics?: boolean;
// Output options
generateSourceMaps?: boolean;
preserveTypeInfo?: boolean;
minifyOutput?: boolean;
// Hooks
onTransform?: (node: Node, context: TransformContext) => void;
onError?: (error: Error, context: TransformContext) => void;
}
interface ResponsiveConfig {
base: Viewport;
breakpoints: Breakpoint[];
strategy: ScalingStrategy;
}
interface Viewport {
width: number;
height: number;
}
interface Breakpoint {
name: string;
width: number;
height: number;
}
interface ScalingStrategy {
origin: 'width' | 'height' | 'area' | 'diagonal';
tokens: TokenConfig;
fallback?: string;
}
interface TokenConfig {
[key: string]: {
scale: number | ((value: number, ratio: number) => number);
min?: number;
max?: number;
step?: number;
round?: boolean;
unit?: string;
};
}🚀 Advanced Usage
Custom Transformations
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
development: true,
// Custom transformation hooks
onTransform: (node, context) => {
// Log all transformations
console.log(`Transformed ${context.filename}:${context.line}:${context.column}`);
// Custom transformation logic
if (node.type === 'CallExpression' && node.callee.name === 'useResponsiveValue') {
// Custom handling for useResponsiveValue calls
console.log('Found useResponsiveValue call');
}
},
onError: (error, context) => {
// Custom error handling
console.error(`Transform error in ${context.filename}:`, error.message);
// Send to error reporting service
if (process.env.ERROR_REPORTING_URL) {
fetch(process.env.ERROR_REPORTING_URL, {
method: 'POST',
body: JSON.stringify({ error: error.message, context })
});
}
}
}]
]
};Multiple Configurations
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
// Development configuration
...(process.env.NODE_ENV === 'development' ? [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: false,
development: true,
addComments: true,
validateConfig: true
}]
] : []),
// Production configuration
...(process.env.NODE_ENV === 'production' ? [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
development: false,
minifyOutput: true,
enableCaching: true
}]
] : [])
]
};Conditional Transformations
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: process.env.ENABLE_PRECOMPUTE === 'true',
development: process.env.NODE_ENV === 'development',
// Conditional features based on environment
enableCaching: process.env.NODE_ENV === 'production',
performanceMetrics: process.env.NODE_ENV === 'development',
// Feature flags
features: {
advancedOptimizations: process.env.ADVANCED_OPTIMIZATIONS === 'true',
experimentalTransforms: process.env.EXPERIMENTAL === 'true'
}
}]
]
};Integration with Other Plugins
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
// React Responsive Easy plugin (should come early)
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
development: process.env.NODE_ENV === 'development'
}],
// Other plugins that might benefit from transformed code
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread',
// Tree shaking and optimization plugins
['@babel/plugin-transform-runtime', {
regenerator: true
}],
// Minification (in production)
...(process.env.NODE_ENV === 'production' ? [
'babel-plugin-transform-remove-console'
] : [])
]
};⚡ Performance
Performance Benefits
- Runtime Performance: Up to 90% faster responsive calculations
- Bundle Size: 15-30% reduction in bundle size
- Memory Usage: Reduced memory allocation for responsive values
- CPU Usage: Lower CPU usage during responsive updates
Performance Monitoring
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
performanceMetrics: true,
onTransform: (node, context) => {
// Collect performance metrics
const startTime = performance.now();
// ... transformation logic ...
const endTime = performance.now();
const duration = endTime - startTime;
// Log performance data
console.log(`Transform took ${duration.toFixed(2)}ms`);
// Send to monitoring service
if (process.env.MONITORING_URL) {
fetch(process.env.MONITORING_URL, {
method: 'POST',
body: JSON.stringify({
metric: 'transform_duration',
value: duration,
filename: context.filename,
timestamp: Date.now()
})
});
}
}
}]
]
};Performance Budgets
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
// Performance budgets
performance: {
maxTransformTime: 100, // ms
maxBundleSizeIncrease: '50KB',
maxMemoryUsage: '100MB'
},
onTransform: (node, context) => {
// Check performance budgets
if (context.transformTime > 100) {
console.warn(`Transform took ${context.transformTime}ms (budget: 100ms)`);
}
}
}]
]
};🐛 Debugging
Development Mode
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
development: true,
addComments: true,
validateConfig: true
}]
]
};Debug Output
# Enable debug logging
DEBUG=rre:babel-plugin npm run build
# Enable verbose output
RRE_DEBUG=true npm run build
# Show transformation details
RRE_SHOW_TRANSFORMATIONS=true npm run buildSource Maps
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
generateSourceMaps: true,
preserveTypeInfo: true
}]
]
};Error Reporting
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
['@yaseratiar/react-responsive-easy-babel-plugin', {
precompute: true,
onError: (error, context) => {
// Enhanced error reporting
const errorInfo = {
message: error.message,
filename: context.filename,
line: context.line,
column: context.column,
code: context.code,
timestamp: new Date().toISOString()
};
console.error('Transform Error:', errorInfo);
// Send to error reporting service
if (process.env.ERROR_REPORTING_URL) {
fetch(process.env.ERROR_REPORTING_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(errorInfo)
}).catch(console.error);
}
}
}]
]
};🔄 Migration Guide
From Runtime Responsive Values
Before:
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
function Component() {
const fontSize = useResponsiveValue(48, { token: 'fontSize' });
const padding = useResponsiveValue(32, { token: 'spacing' });
return <div style={{ fontSize, padding }}>Content</div>;
}After (with Babel plugin):
// Same code, but transformed at build time
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
function Component() {
const fontSize = useResponsiveValue(48, { token: 'fontSize' });
const padding = useResponsiveValue(32, { token: 'spacing' });
return <div style={{ fontSize, padding }}>Content</div>;
}From CSS-in-JS Solutions
Before:
import styled from 'styled-components';
const Title = styled.h1`
font-size: ${props => props.theme.responsive.fontSize(48)};
padding: ${props => props.theme.responsive.spacing(32)};
`;After:
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
function Title() {
const fontSize = useResponsiveValue(48, { token: 'fontSize' });
const padding = useResponsiveValue(32, { token: 'spacing' });
return (
<h1 style={{ fontSize, padding }}>
Title
</h1>
);
}From Media Query Hooks
Before:
import { useMediaQuery } from 'react-responsive';
function Component() {
const isMobile = useMediaQuery({ maxWidth: 768 });
const isTablet = useMediaQuery({ minWidth: 769, maxWidth: 1024 });
const fontSize = isMobile ? 24 : isTablet ? 32 : 48;
return <div style={{ fontSize }}>Content</div>;
}After:
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
function Component() {
const fontSize = useResponsiveValue(48, { token: 'fontSize' });
return <div style={{ fontSize }}>Content</div>;
}🐛 Troubleshooting
Common Issues
Plugin Not Working
# Check if plugin is installed
npm list @yaseratiar/react-responsive-easy-babel-plugin
# Verify Babel configuration
npx babel --print-config src/index.js
# Check for syntax errors
npx babel --presets @babel/preset-env src/index.jsConfiguration Errors
# Validate configuration
RRE_VALIDATE_CONFIG=true npm run build
# Check configuration file
node -e "console.log(require('./responsive.config.js'))"
# Test with minimal config
RRE_MINIMAL_CONFIG=true npm run buildPerformance Issues
# Profile build performance
RRE_PROFILE=true npm run build
# Check memory usage
RRE_MEMORY_PROFILE=true npm run build
# Analyze bundle size
npm run build:analyzeDebug Commands
# Show plugin version
npx babel --version
# List all Babel plugins
npx babel --print-config src/index.js | grep plugin
# Test specific file
npx babel src/components/Button.tsx --plugins @yaseratiar/react-responsive-easy-babel-plugin
# Show AST
npx babel --ast src/components/Button.tsxGetting Help
# Enable debug mode
DEBUG=rre:babel-plugin npm run build
# Show help
npx @yaseratiar/react-responsive-easy-babel-plugin --help
# Check documentation
open https://github.com/naaa-G/react-responsive-easy🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
# Clone repository
git clone https://github.com/naaa-G/react-responsive-easy.git
# Install dependencies
pnpm install
# Link plugin locally
pnpm --filter=@yaseratiar/react-responsive-easy-babel-plugin link
# Test plugin
pnpm testTesting
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run specific test
pnpm test --grep "transformation"
# Coverage report
pnpm test:coverageBuilding
# Build plugin
pnpm build
# Build with watch mode
pnpm build:watch
# Build for production
pnpm build:prod📄 License
MIT License - see the LICENSE file for details.
🔗 Links
- Documentation: https://github.com/naaa-G/react-responsive-easy
- Issues: https://github.com/naaa-G/react-responsive-easy/issues
- Discussions: https://github.com/naaa-G/react-responsive-easy/discussions
- Changelog: https://github.com/naaa-G/react-responsive-easy/blob/main/CHANGELOG.md
🙏 Acknowledgments
- Babel Team - For the amazing transformation platform
- React Team - For the component-based architecture
- TypeScript Team - For type safety and tooling
- Open Source Community - For inspiration and collaboration
Made with ❤️ by naa-G
⭐ Star this repository if you find it helpful!
