Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.

Conversation

@mandarini
Copy link
Contributor

@mandarini mandarini commented Aug 12, 2025

What kind of change does this PR introduce?

Bug fix / Compatibility improvement - Eliminates bundler warnings and runtime failures caused by dynamic imports while simplifying WebSocket detection logic.

What is the current behavior?

Dynamic imports cause widespread compatibility issues:

  • Bundler warnings: Critical dependency: the request of a dependency is an expression in Webpack builds
  • Runtime failures: Edge runtime crashes, Cloudflare Workers deployment failures
  • Environment-specific bugs: Inconsistent WebSocket detection across Node.js versions and deployment platforms
  • Production breakage: Realtime subscriptions failing to work in various environments

Related Issues:

  • supabase/supabase-js#1437 - 54 comments from users experiencing production failures
  • Affects official Next.js template (npx create-next-app -e with-supabase)
  • Multiple reports across SvelteKit, Solid-Start, Vercel, and other platforms

Current problematic code:

// Causes bundler warnings and runtime failures
private static dynamicRequire(moduleId: string): any {
  try {
    if (typeof require !== 'undefined') {
      return require(moduleId) // Webpack: "Critical dependency"
    }
    return null
  } catch {
    return null
  }
}

What is the new behavior?

Clean, explicit WebSocket configuration that works universally:

  • Zero bundler warnings across all bundlers (Webpack, Vite, Turbo, etc.)
  • Universal compatibility - works in all runtimes (Browser, Node.js, Edge, Workers)
  • Predictable behavior - no magic detection that fails in edge cases
  • Better error messages with clear migration paths

For most users (Browser, Node.js 22+): No changes required
For Node.js < 22 users: Simple one-time migration to explicit configuration

// Before (problematic)
import { createClient } from '@supabase/supabase-js'
const client = createClient(url, key)

// After (explicit, reliable)  
import { createClient } from '@supabase/supabase-js'
import ws from 'ws'
const client = createClient(url, key, {
  realtime: { transport: ws }
})

Enhanced error messages guide users through migration:

To use Realtime in Node.js, you need to provide a WebSocket implementation:

Option 1: Use Node.js 22+ which has native WebSocket support
Option 2: Install and provide the "ws" package:

  npm install ws

  import ws from "ws"
  const client = new RealtimeClient(url, {
    ...options,
    transport: ws
  })

Additional context

Why This Journey Led Here

The Problem Evolution:

  1. Original: isows dependency caused "missing isows" issues
  2. First Fix: Removed isows but reintroduced bundler warnings with dynamic imports
  3. Attempted Solution: Dual export pattern (PRs feat: separate entry point for dynamic imports #511 and #1527) - too complex, required changes in both realtime-js and supabase-js
  4. Final Solution: This PR - clean break that solves root cause

Why This Is NOT a Breaking Change

Current behavior is already broken for many users:

Production Failures (from Issue #1437):

  • Vercel deployments failing with 500 errors
  • Cloudflare Workers unable to deploy due to require() calls
  • Edge runtimes crashing with WebSocket detection
  • Official Supabase templates generating bundler warnings
  • Users forced to pin old versions (2.49.8) to avoid issues

This PR fixes broken functionality rather than breaking working functionality.

Ecosystem Readiness

  • Node.js 22+ (2024+): Native WebSocket support eliminates this issue entirely
  • Production apps: Already manage dependencies explicitly for reliability
  • Bundle size: Removes complex dynamic detection code (~100 lines)
  • Security: Eliminates need for eval() or dynamic require() workarounds

User Impact Analysis

Environment Impact Migration Required
Browser ✅ No change None
Node.js 22+ ✅ No change None
Edge Runtime Fixed (was broken) None
Cloudflare Workers Fixed (was broken) None
Node.js < 22 ⚠️ Explicit config needed One-time setup

Long-term Benefits

  • Future-proof: Aligns with Node.js native WebSocket roadmap
  • Maintainable: Eliminates complex environment detection code
  • Reliable: Explicit configuration prevents environment-specific failures
  • Performance: Removes runtime detection overhead
  • Security: No dynamic imports that could be exploited

Alternative Approaches Considered

  1. eval(require) workaround: Rejected due to CSP violations and security concerns
  2. Dual exports (feat: separate entry point for dynamic imports #511/#1527): Rejected due to complexity and maintenance overhead
  3. Better dynamic detection: Tried in multiple iterations, fundamentally unreliable

@mandarini mandarini self-assigned this Aug 12, 2025
@mandarini mandarini force-pushed the feat/remove-require branch from 74626c8 to d4b37e0 Compare August 12, 2025 08:04
@mandarini mandarini marked this pull request as ready for review August 12, 2025 08:58
@mandarini mandarini requested review from filipecabaco and grdsdev and removed request for filipecabaco August 12, 2025 08:58
@mandarini mandarini merged commit ba084f8 into supabase:master Aug 12, 2025
6 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2.49.9 breaks application code on Vercel (error 500)

2 participants