-
-
Notifications
You must be signed in to change notification settings - Fork 632
Description
Summary
This issue requests documentation for the timer function limitations in ExecJS-based server-side rendering and the solutions available.
The Problem
When using React on Rails with ExecJS for server-side rendering, the following functions are not available or don't work as expected:
setTimeout- Logs an error instead of executingsetInterval- Logs an error instead of executingclearTimeout- Not functionalclearInterval- Not functional
This causes issues with modern React libraries that rely on timers:
- TanStack Router - Uses timers for route loading
- React Query/TanStack Query - Uses timers for cache management
- Many animation libraries - Use timers for transitions
- Debounce/throttle utilities - Rely on setTimeout
Error Message
When these functions are called during SSR, users see:
[SERVER] setTimeout is not defined for execJS. See https://github.com/sstephenson/execjs#faq
Solutions
1. React on Rails Pro Node Renderer (Recommended)
React on Rails Pro provides a Node.js-based renderer that includes full timer support:
# config/initializers/react_on_rails_pro.rb
ReactOnRailsPro.configure do |config|
config.server_renderer = "NodeRenderer"
endBenefits:
- Full Node.js environment
- Better performance than ExecJS
- Hot reload without server restart
- Support for async operations
2. Custom Polyfills (Workaround)
For libraries that only need basic timer support, polyfills can be added to the server bundle:
// ssr-polyfills.ts - imported at top of server-bundle.js
try {
const globalEval = eval;
globalEval(`
var __ssrTimerId = 0;
setTimeout = function(fn, delay) {
var id = ++__ssrTimerId;
if (delay === 0 || delay === undefined) {
try { fn(); } catch (e) { console.error(e); }
}
return id;
};
clearTimeout = function(id) { /* no-op */ };
setInterval = function() { return ++__ssrTimerId; };
clearInterval = function() { /* no-op */ };
`);
} catch (e) {
// Fallback to globalThis assignment
}Limitations of polyfills:
- Timers execute synchronously (no actual delay)
- Not all timer behaviors are supported
- May not work for all libraries
3. Disable SSR for Affected Components
For components that heavily rely on timers, consider client-side only rendering:
<%= react_component("MyComponent", props: @props, prerender: false) %>Requested Documentation
- Add to SSR troubleshooting guide: Document the timer limitation and error message
- Add solutions section: Document the three approaches above
- Link to React on Rails Pro: Explain Node Renderer benefits
- Add example polyfills: For those who can't use Pro
Related
- TanStack Router Integration Issue: Documentation: Add TanStack Router Integration Guide #2298
- Historical issues: Is it possible to disable the setTimeout error in dev for SSR? #1098, when reboot rails, I get [SERVER] setTimeout is not defined for execJS #372
- Demo with polyfills: Add TanStack Router demo with SSR and TypeScript react_on_rails-demos#104
Context
This documentation would help developers who encounter timer-related errors during SSR understand their options and choose the appropriate solution for their use case.