CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pmmmwh--react-refresh-webpack-plugin

Webpack plugin to enable React Fast Refresh (Hot Reloading) for React components during development

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

client-utilities.mddocs/

Client Utilities

Browser-side utilities for error handling, webpack error formatting, and connection retry logic used by the React Refresh client-side runtime.

Capabilities

Error Event Handlers

Utilities for handling runtime errors and unhandled promise rejections in the browser.

const { handleError, handleUnhandledRejection } = require('@pmmmwh/react-refresh-webpack-plugin/client/utils/errorEventHandlers');

/**
 * Creates an error event handler for runtime errors
 * @param {Function} errorReporter - Function to report errors to overlay
 * @returns {Function} - Error event handler function
 */
function handleError(errorReporter: (error: Error) => void): (event: ErrorEvent) => void;

/**
 * Creates an unhandled rejection handler for promise rejections
 * @param {Function} errorReporter - Function to report errors to overlay
 * @returns {Function} - Unhandled rejection event handler function
 */
function handleUnhandledRejection(errorReporter: (error: Error) => void): (event: PromiseRejectionEvent) => void;

Usage Example:

const { handleError, handleUnhandledRejection } = require('@pmmmwh/react-refresh-webpack-plugin/client/utils/errorEventHandlers');

// Error reporting function
function reportError(error) {
  console.error('Runtime error:', error);
  // Send to error overlay
  window.__react_refresh_error_overlay__.handleRuntimeError(error);
}

// Set up global error handlers
const errorHandler = handleError(reportError);
const rejectionHandler = handleUnhandledRejection(reportError);

// Install handlers
window.addEventListener('error', errorHandler);
window.addEventListener('unhandledrejection', rejectionHandler);

// Cleanup function
function removeErrorHandlers() {
  window.removeEventListener('error', errorHandler);
  window.removeEventListener('unhandledrejection', rejectionHandler);
}

Format Webpack Errors

Formats webpack compilation errors for display in the error overlay with ANSI color support and stack trace processing.

/**
 * Formats webpack compilation errors for display
 * @param {string[]} errors - Array of raw webpack error messages
 * @returns {FormattedError[]} - Array of formatted error objects
 */
function formatWebpackErrors(errors: string[]): FormattedError[];

interface FormattedError {
  message: string;
  stack?: string;
  file?: string;
  lineNumber?: number;
  columnNumber?: number;
}

Usage Example:

const formatWebpackErrors = require('@pmmmwh/react-refresh-webpack-plugin/client/utils/formatWebpackErrors');

// Raw webpack errors from compilation
const rawErrors = [
  "Module not found: Error: Can't resolve './missing-component' in '/src'",
  "SyntaxError: Unexpected token '}' (15:4)\n  at Parser.pp$4.raise (/webpack/lib/Parser.js:349:13)"
];

// Format errors for display
const formattedErrors = formatWebpackErrors(rawErrors);

formattedErrors.forEach(error => {
  console.log('Error message:', error.message);
  console.log('File:', error.file);
  console.log('Line:', error.lineNumber);
  if (error.stack) {
    console.log('Stack trace:', error.stack);
  }
});

// Display in error overlay
formattedErrors.forEach(error => {
  window.__react_refresh_error_overlay__.showCompileError(error.message);
});

Connection Retry Logic

Retry utility for socket connections with exponential backoff and maximum retry limits.

/**
 * Runs a function with retry logic and exponential backoff
 * @param {Function} fn - Function to execute with retry
 * @param {number} maxAttempts - Maximum number of retry attempts
 * @param {number} baseDelay - Base delay between retries in milliseconds
 * @returns {Promise} - Promise that resolves when function succeeds or rejects after max attempts
 */
function runWithRetry<T>(
  fn: () => Promise<T>,
  maxAttempts?: number,
  baseDelay?: number
): Promise<T>;

Usage Example:

const runWithRetry = require('@pmmmwh/react-refresh-webpack-plugin/client/utils/retry');

// Function that might fail (e.g., socket connection)
async function connectToWebSocket() {
  return new Promise((resolve, reject) => {
    const socket = new WebSocket('ws://localhost:8080');
    
    socket.onopen = () => resolve(socket);
    socket.onerror = (error) => reject(error);
    
    // Timeout after 5 seconds
    setTimeout(() => reject(new Error('Connection timeout')), 5000);
  });
}

// Retry connection with exponential backoff
runWithRetry(connectToWebSocket, 5, 1000)
  .then(socket => {
    console.log('Connected successfully:', socket);
  })
  .catch(error => {
    console.error('Failed to connect after retries:', error);
  });

// Custom retry configuration
runWithRetry(
  () => fetch('/api/health-check'),
  3,    // Max 3 attempts
  500   // Start with 500ms delay
)
.then(response => response.json())
.then(data => console.log('Health check:', data))
.catch(error => console.error('Health check failed:', error));

Advanced Usage Patterns

Comprehensive Error Handling Setup

Set up complete error handling for a React application:

const { handleError, handleUnhandledRejection } = require('@pmmmwh/react-refresh-webpack-plugin/client/utils/errorEventHandlers');
const formatWebpackErrors = require('@pmmmwh/react-refresh-webpack-plugin/client/utils/formatWebpackErrors');

class ErrorManager {
  constructor() {
    this.errorOverlay = window.__react_refresh_error_overlay__;
    this.setupErrorHandlers();
  }
  
  setupErrorHandlers() {
    // Report runtime errors to overlay
    const reportRuntimeError = (error) => {
      if (this.errorOverlay) {
        this.errorOverlay.handleRuntimeError(error);
      }
      // Also log to console for debugging
      console.error('Runtime error:', error);
    };
    
    // Set up global error handlers
    const errorHandler = handleError(reportRuntimeError);
    const rejectionHandler = handleUnhandledRejection(reportRuntimeError);
    
    window.addEventListener('error', errorHandler);
    window.addEventListener('unhandledrejection', rejectionHandler);
    
    // Store handlers for cleanup
    this.errorHandler = errorHandler;
    this.rejectionHandler = rejectionHandler;
  }
  
  handleCompilationErrors(errors) {
    if (errors && errors.length > 0) {
      const formatted = formatWebpackErrors(errors);
      
      // Show first error in overlay
      if (this.errorOverlay && formatted[0]) {
        this.errorOverlay.showCompileError(formatted[0].message);
      }
      
      // Log all errors to console
      formatted.forEach((error, index) => {
        console.group(`Compilation Error ${index + 1}:`);
        console.error(error.message);
        if (error.file) console.log('File:', error.file);
        if (error.lineNumber) console.log('Line:', error.lineNumber);
        if (error.stack) console.log('Stack:', error.stack);
        console.groupEnd();
      });
    }
  }
  
  clearErrors() {
    if (this.errorOverlay) {
      this.errorOverlay.clearRuntimeErrors();
      this.errorOverlay.clearCompileError();
    }
  }
  
  cleanup() {
    if (this.errorHandler) {
      window.removeEventListener('error', this.errorHandler);
    }
    if (this.rejectionHandler) {
      window.removeEventListener('unhandledrejection', this.rejectionHandler);
    }
  }
}

// Initialize error management
const errorManager = new ErrorManager();

// Handle webpack hot updates
if (module.hot) {
  module.hot.addStatusHandler(status => {
    if (status === 'idle') {
      errorManager.clearErrors();
    }
  });
}

Resilient Socket Connection Manager

Create a robust socket connection with retry logic:

const runWithRetry = require('@pmmmwh/react-refresh-webpack-plugin/client/utils/retry');
const { handleError } = require('@pmmmwh/react-refresh-webpack-plugin/client/utils/errorEventHandlers');

class SocketManager {
  constructor(url, options = {}) {
    this.url = url;
    this.maxRetries = options.maxRetries || 10;
    this.baseDelay = options.baseDelay || 1000;
    this.socket = null;
    this.isConnecting = false;
    this.messageHandlers = [];
    
    // Set up error handling
    this.errorHandler = handleError((error) => {
      console.error('Socket error:', error);
      this.handleConnectionError(error);
    });
  }
  
  async connect() {
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
      return this.socket;
    }
    
    if (this.isConnecting) {
      return new Promise((resolve) => {
        this.once('connected', resolve);
      });
    }
    
    this.isConnecting = true;
    
    try {
      this.socket = await runWithRetry(
        () => this.createConnection(),
        this.maxRetries,
        this.baseDelay
      );
      
      this.isConnecting = false;
      this.emit('connected', this.socket);
      return this.socket;
      
    } catch (error) {
      this.isConnecting = false;
      throw error;
    }
  }
  
  createConnection() {
    return new Promise((resolve, reject) => {
      const socket = new WebSocket(this.url);
      
      socket.onopen = () => {
        console.log('Socket connected');
        resolve(socket);
      };
      
      socket.onmessage = (event) => {
        this.handleMessage(JSON.parse(event.data));
      };
      
      socket.onclose = () => {
        console.log('Socket disconnected');
        this.handleDisconnection();
      };
      
      socket.onerror = (error) => {
        console.error('Socket connection failed:', error);
        reject(error);
      };
      
      // Connection timeout
      setTimeout(() => {
        if (socket.readyState === WebSocket.CONNECTING) {
          socket.close();
          reject(new Error('Connection timeout'));
        }
      }, 10000);
    });
  }
  
  handleMessage(message) {
    this.messageHandlers.forEach(handler => {
      try {
        handler(message);
      } catch (error) {
        this.errorHandler({ error });
      }
    });
  }
  
  handleConnectionError(error) {
    // Attempt reconnection after delay
    setTimeout(() => {
      if (!this.socket || this.socket.readyState === WebSocket.CLOSED) {
        this.connect().catch(retryError => {
          console.error('Reconnection failed:', retryError);
        });
      }
    }, this.baseDelay);
  }
  
  handleDisconnection() {
    // Auto-reconnect after short delay
    setTimeout(() => {
      this.connect().catch(error => {
        console.error('Auto-reconnect failed:', error);
      });
    }, 2000);
  }
  
  onMessage(handler) {
    this.messageHandlers.push(handler);
  }
  
  // Simple event emitter methods
  once(event, handler) {
    const onceHandler = (...args) => {
      handler(...args);
      this.off(event, onceHandler);
    };
    this.on(event, onceHandler);
  }
  
  on(event, handler) {
    if (!this.events) this.events = {};
    if (!this.events[event]) this.events[event] = [];
    this.events[event].push(handler);
  }
  
  off(event, handler) {
    if (!this.events || !this.events[event]) return;
    const index = this.events[event].indexOf(handler);
    if (index > -1) this.events[event].splice(index, 1);
  }
  
  emit(event, ...args) {
    if (!this.events || !this.events[event]) return;
    this.events[event].forEach(handler => handler(...args));
  }
}

// Usage
const socketManager = new SocketManager('ws://localhost:8080');

socketManager.onMessage((message) => {
  console.log('Received message:', message);
  
  // Handle different message types
  switch (message.type) {
    case 'errors':
      errorManager.handleCompilationErrors(message.errors);
      break;
    case 'ok':
      errorManager.clearErrors();
      break;
  }
});

// Connect with retry logic
socketManager.connect()
  .then(() => console.log('Socket ready'))
  .catch(error => console.error('Failed to establish connection:', error));

Install with Tessl CLI

npx tessl i tessl/npm-pmmmwh--react-refresh-webpack-plugin

docs

client-utilities.md

error-overlay.md

index.md

loader-configuration.md

plugin-configuration.md

plugin-utilities.md

runtime-utilities.md

socket-integrations.md

tile.json