@yaseratiar/react-responsive-easy-next-plugin
Version:
Next.js plugin for React Responsive Easy integration
978 lines (770 loc) • 24.5 kB
Markdown
# @yaseratiar/react-responsive-easy-next-plugin
> Enterprise-grade Next.js plugin for React Responsive Easy integration and SSR optimization
[](https://badge.fury.io/js/%40yaseratiar%2Freact-responsive-easy-next-plugin)
[](https://opensource.org/licenses/MIT)
[](https://www.typescriptlang.org/)
[](https://nextjs.org/)
[](https://reactjs.org/)
## 📖 Table of Contents
- [Overview](#overview)
- [Features](#-features)
- [Installation](#-installation)
- [Quick Start](#-quick-start)
- [Configuration](#-configuration)
- [API Reference](#-api-reference)
- [Advanced Usage](#-advanced-usage)
- [SSR & SSG Support](#-ssr--ssg-support)
- [Performance](#-performance)
- [Migration Guide](#-migration-guide)
- [Troubleshooting](#-troubleshooting)
- [Contributing](#-contributing)
- [License](#-license)
## 🌟 Overview
`@yaseratiar/react-responsive-easy-next-plugin` is a powerful Next.js plugin that seamlessly integrates React Responsive Easy into your Next.js applications, providing server-side rendering support, static generation optimization, and enhanced performance.
Built for enterprise applications, it offers:
- **SSR Support** - Perfect server-side rendering compatibility
- **SSG Optimization** - Static generation with responsive pre-computation
- **Zero Configuration** - Works out of the box with Next.js
- **TypeScript Support** - Full type safety with intelligent IntelliSense
- **Enterprise Integration** - Seamless integration with CI/CD pipelines
## 🚀 Features
### Core Integration
- **Next.js Native** - Built specifically for Next.js architecture
- **Plugin System** - Leverages Next.js's powerful plugin ecosystem
- **App Router Support** - Full compatibility with Next.js 13+ App Router
- **Pages Router Support** - Backward compatibility with Pages Router
### SSR & SSG Support
- **Server-Side Rendering** - Responsive values computed on the server
- **Static Generation** - Pre-computed responsive values at build time
- **Incremental Static Regeneration** - Dynamic responsive updates
- **Edge Runtime** - Edge function compatibility
### Development Experience
- **Zero Configuration** - Automatic setup with sensible defaults
- **Hot Reloading** - Instant updates with responsive debugging tools
- **Source Maps** - Accurate source mapping for debugging
- **Error Overlay** - Rich error reporting with helpful suggestions
### Build Optimization
- **Pre-computation** - Build-time responsive value calculation
- **Tree Shaking** - Remove unused responsive code automatically
- **Code Splitting** - Optimize responsive code for different chunks
- **Bundle Analysis** - Detailed bundle size and performance reports
### 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
```bash
npm install --save-dev @yaseratiar/react-responsive-easy-next-plugin
```
### yarn
```bash
yarn add --dev @yaseratiar/react-responsive-easy-next-plugin
```
### pnpm
```bash
pnpm add --save-dev @yaseratiar/react-responsive-easy-next-plugin
```
### Peer Dependencies
```bash
npm install --save-dev next react react-dom
```
## 🎯 Quick Start
### 1. Install the Plugin
```bash
npm install --save-dev @yaseratiar/react-responsive-easy-next-plugin
```
### 2. Configure Next.js
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy({
ssr: true,
precompute: true
})({
// your Next.js config
});
```
### 3. Use in Your Components
```tsx
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
const Hero = () => {
const fontSize = useResponsiveValue(48, { token: 'fontSize' });
const padding = useResponsiveValue(32, { token: 'spacing' });
return (
<h1 style={{ fontSize, padding }}>
Responsive Hero Title
</h1>
);
};
```
### 4. Start Development
```bash
npm run dev
```
## ⚙️ Configuration
### Basic Configuration
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy()({
// your Next.js config
});
```
### Advanced Configuration
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy({
// Core options
enabled: true,
configPath: './responsive.config.js',
// Configuration options
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 },
radius: { scale: 0.95, min: 2, max: 32 }
}
}
},
// SSR options
ssr: true,
ssg: true,
edgeRuntime: false,
// Build options
precompute: true,
generateCustomProperties: true,
generateSourceMaps: true,
// Performance options
enableCaching: true,
cacheSize: 1000,
enableOptimization: true,
// Development options
addComments: process.env.NODE_ENV === 'development',
validateConfig: true,
performanceMetrics: process.env.NODE_ENV === 'development',
// Hooks
onTransform: (module, context) => {
console.log(`Transformed: ${context.filename}`);
},
onError: (error, context) => {
console.error(`Transform error: ${error.message}`);
}
})({
// your Next.js config
experimental: {
appDir: true
}
});
```
### Configuration File
Create a `responsive.config.js` file:
```javascript
// 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
}
}
}
};
```
### Environment-Specific Configuration
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
const isDevelopment = process.env.NODE_ENV === 'development';
const isProduction = process.env.NODE_ENV === 'production';
module.exports = withReactResponsiveEasy({
enabled: true,
// Development optimizations
...(isDevelopment && {
addComments: true,
validateConfig: true,
performanceMetrics: true,
generateSourceMaps: true
}),
// Production optimizations
...(isProduction && {
ssr: true,
ssg: true,
precompute: true,
enableOptimization: true,
enableCaching: true,
performanceMetrics: false
})
})({
// your Next.js config
});
```
### TypeScript Configuration
```typescript
// next.config.ts
import { withReactResponsiveEasy } from '@yaseratiar/react-responsive-easy-next-plugin';
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
experimental: {
appDir: true
}
};
export default withReactResponsiveEasy({
ssr: true,
precompute: true,
generateCustomProperties: true
})(nextConfig);
```
## 🔧 API Reference
### Plugin Options
#### Core Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | `boolean` | `true` | Enable/disable the plugin |
| `configPath` | `string` | `undefined` | Path to configuration file |
| `configInline` | `object` | `undefined` | Inline configuration object |
#### SSR & SSG Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `ssr` | `boolean` | `true` | Enable server-side rendering support |
| `ssg` | `boolean` | `true` | Enable static generation support |
| `edgeRuntime` | `boolean` | `false` | Enable Edge Runtime support |
#### Build Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `precompute` | `boolean` | `true` | Enable build-time pre-computation |
| `generateCustomProperties` | `boolean` | `true` | Generate CSS custom properties |
| `generateSourceMaps` | `boolean` | `true` | Generate source maps |
#### Performance Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enableCaching` | `boolean` | `true` | Enable value caching |
| `cacheSize` | `number` | `1000` | Maximum cache size |
| `enableOptimization` | `boolean` | `true` | Enable build optimization |
#### Development Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `addComments` | `boolean` | `false` | Add helpful comments |
| `validateConfig` | `boolean` | `false` | Validate configuration |
| `performanceMetrics` | `boolean` | `false` | Collect performance metrics |
#### Hooks
| Option | Type | Description |
|--------|------|-------------|
| `onTransform` | `function` | Called after each transformation |
| `onError` | `function` | Called when errors occur |
### Configuration Schema
```typescript
interface PluginOptions {
// Core options
enabled?: boolean;
configPath?: string;
configInline?: ResponsiveConfig;
// SSR & SSG options
ssr?: boolean;
ssg?: boolean;
edgeRuntime?: boolean;
// Build options
precompute?: boolean;
generateCustomProperties?: boolean;
generateSourceMaps?: boolean;
// Performance options
enableCaching?: boolean;
cacheSize?: number;
enableOptimization?: boolean;
// Development options
addComments?: boolean;
validateConfig?: boolean;
performanceMetrics?: boolean;
// Hooks
onTransform?: (module: Module, 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
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy({
ssr: true,
precompute: true,
development: true,
// Custom transformation hooks
onTransform: (module, context) => {
// Log all transformations
console.log(`Transformed ${context.filename}:${context.line}:${context.column}`);
// Custom transformation logic
if (module.type === 'js' && module.code.includes('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 })
});
}
}
})({
// your Next.js config
});
```
### Multiple Configurations
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy({
// Development configuration
...(process.env.NODE_ENV === 'development' ? {
precompute: false,
development: true,
addComments: true,
validateConfig: true
} : {}),
// Production configuration
...(process.env.NODE_ENV === 'production' ? {
ssr: true,
ssg: true,
precompute: true,
enableOptimization: true,
enableCaching: true
} : {})
})({
// your Next.js config
});
```
### Integration with Other Plugins
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true'
});
const withPWA = require('next-pwa')({
dest: 'public'
});
module.exports = withBundleAnalyzer(
withPWA(
withReactResponsiveEasy({
ssr: true,
precompute: true
})({
// your Next.js config
experimental: {
appDir: true
}
})
)
);
```
### Environment Variables Integration
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy({
ssr: process.env.ENABLE_SSR === 'true',
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'
}
})({
// your Next.js config
env: {
RRE_VERSION: process.env.npm_package_version,
RRE_ENV: process.env.NODE_ENV
}
});
```
## 🔄 SSR & SSG Support
### Server-Side Rendering
```tsx
// pages/index.tsx (Pages Router)
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
export default function HomePage() {
const fontSize = useResponsiveValue(48, { token: 'fontSize' });
const padding = useResponsiveValue(32, { token: 'spacing' });
return (
<div style={{ fontSize, padding }}>
<h1>Server-Side Rendered</h1>
</div>
);
}
// app/page.tsx (App Router)
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
export default function HomePage() {
const fontSize = useResponsiveValue(48, { token: 'fontSize' });
const padding = useResponsiveValue(32, { token: 'spacing' });
return (
<div style={{ fontSize, padding }}>
<h1>App Router Page</h1>
</div>
);
}
```
### Static Generation
```tsx
// pages/blog/[slug].tsx
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
export default function BlogPost({ post }) {
const fontSize = useResponsiveValue(24, { token: 'fontSize' });
const margin = useResponsiveValue(32, { token: 'spacing' });
return (
<article style={{ fontSize, margin }}>
<h1>{post.title}</h1>
<div>{post.content}</div>
</article>
);
}
export async function getStaticProps({ params }) {
// Fetch post data
const post = await fetchPost(params.slug);
return {
props: { post },
revalidate: 60 // ISR with 60 seconds
};
}
export async function getStaticPaths() {
// Generate static paths
const posts = await fetchPosts();
return {
paths: posts.map(post => ({ params: { slug: post.slug } })),
fallback: 'blocking'
};
}
```
### Edge Runtime Support
```tsx
// app/api/edge/route.ts
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
export const runtime = 'edge';
export async function GET() {
const fontSize = useResponsiveValue(16, { token: 'fontSize' });
return Response.json({
message: 'Edge Runtime Response',
fontSize
});
}
```
### Dynamic Imports
```tsx
// components/DynamicComponent.tsx
import dynamic from 'next/dynamic';
import { useResponsiveValue } from '@yaseratiar/react-responsive-easy-core';
const DynamicComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <div>Loading...</div>,
ssr: true
});
export default function Wrapper() {
const padding = useResponsiveValue(24, { token: 'spacing' });
return (
<div style={{ padding }}>
<DynamicComponent />
</div>
);
}
```
## ⚡ Performance
### Performance Benefits
- **Build-time Processing** - Zero runtime responsive calculations
- **Bundle Optimization** - Optimize bundle size and loading
- **Tree Shaking** - Remove unused responsive code automatically
- **Code Splitting** - Intelligent code splitting for responsive features
### Performance Monitoring
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy({
ssr: true,
precompute: true,
performanceMetrics: true,
onTransform: (module, 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()
})
});
}
}
})({
// your Next.js config
});
```
### Performance Budgets
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy({
ssr: true,
precompute: true,
// Performance budgets
performance: {
maxTransformTime: 100, // ms
maxBundleSizeIncrease: '50KB',
maxMemoryUsage: '100MB'
},
onTransform: (module, context) => {
// Check performance budgets
if (context.transformTime > 100) {
console.warn(`Transform took ${context.transformTime}ms (budget: 100ms)`);
}
}
})({
// your Next.js config
});
```
## 🔄 Migration Guide
### From Create React App
**Before:**
```javascript
// package.json
{
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build"
}
}
```
**After:**
```javascript
// package.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy()({
// your Next.js config
});
```
### From Vite
**Before:**
```javascript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { reactResponsiveEasy } from '@yaseratiar/react-responsive-easy-vite-plugin';
export default defineConfig({
plugins: [
react(),
reactResponsiveEasy()
]
});
```
**After:**
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy()({
// your Next.js config
});
```
### From Webpack
**Before:**
```javascript
// webpack.config.js
module.exports = {
plugins: [
new ReactResponsiveEasyWebpackPlugin()
]
};
```
**After:**
```javascript
// next.config.js
const { withReactResponsiveEasy } = require('@yaseratiar/react-responsive-easy-next-plugin');
module.exports = withReactResponsiveEasy()({
// your Next.js config
});
```
## 🐛 Troubleshooting
### Common Issues
#### Plugin Not Working
```bash
# Check if plugin is installed
npm list @yaseratiar/react-responsive-easy-next-plugin
# Verify Next.js configuration
npx next --version
# Check for syntax errors
npx next build
```
#### Configuration Errors
```bash
# 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 build
```
#### Build Failures
```bash
# Check build output
npm run build -- --verbose
# Enable debug mode
DEBUG=rre:next-plugin npm run build
# Show transformation details
RRE_SHOW_TRANSFORMATIONS=true npm run build
```
### Debug Commands
```bash
# Show plugin version
npx next --version
# List all Next.js plugins
npx next info
# Test specific file
npx next build pages/index.tsx
# Show build info
npx next build --mode development
```
### Getting Help
```bash
# Enable debug mode
DEBUG=rre:next-plugin npm run dev
# Show help
npx @yaseratiar/react-responsive-easy-next-plugin --help
# Check documentation
open https://github.com/naaa-G/react-responsive-easy
```
## 🤝 Contributing
We welcome contributions! Please see our [Contributing Guide](https://github.com/naaa-G/react-responsive-easy/blob/main/CONTRIBUTING.md) for details.
### Development Setup
```bash
# 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-next-plugin link
# Test plugin
pnpm test
```
### Testing
```bash
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run specific test
pnpm test --grep "transformation"
# Coverage report
pnpm test:coverage
```
### Building
```bash
# Build plugin
pnpm build
# Build with watch mode
pnpm build:watch
# Build for production
pnpm build:prod
```
## 📄 License
MIT License - see the [LICENSE](https://github.com/naaa-G/react-responsive-easy/blob/main/LICENSE) file for details.
## 🔗 Links
- **Documentation**: [https://github.com/naaa-G/react-responsive-easy](https://github.com/naaa-G/react-responsive-easy)
- **Issues**: [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](https://github.com/naaa-G/react-responsive-easy/discussions)
- **Changelog**: [https://github.com/naaa-G/react-responsive-easy/blob/main/CHANGELOG.md](https://github.com/naaa-G/react-responsive-easy/blob/main/CHANGELOG.md)
## 🙏 Acknowledgments
- **Next.js Team** - For the amazing full-stack framework
- **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](https://github.com/naaa-G)**
**[⭐ Star this repository](https://github.com/naaa-G/react-responsive-easy)** if you find it helpful!