shakacode / react_on_rails

Integration of React + Webpack + Rails + rails/webpacker including server-side rendering of React, enabling a better developer experience and faster client performance.
https://www.shakacode.com/react-on-rails/docs/
MIT License
5.08k stars 627 forks source link

Server side rendering window behaves differently than Node.js? #1597

Closed damassi closed 5 months ago

damassi commented 5 months ago

Environment

  1. Ruby version: 3.0.2
  2. Rails version: 6.1.7
  3. Shakapacker/Webpacker version: 7.2.1
  4. React on Rails version: 13.4

Expected behavior

SSR-compatible react component renders server-side

Actual behavior

React on Rails throws error saying window is not available.

Small, reproducible repo

Description of issue

Hi! Excellent library and very well written codebase (ty!)

I have a quick question around server side rendering react components and code execution.

We've been SSR rendering our primary web app (using styled-components) with Node.js with no trouble and I am certain that SSR is well supported at the library level. However, attempting to render the same code using this library in Rails yields problems around window. My operating assumption is that said code could seamlessly transfer to a react on rails environment, but perhaps i'm missing a detail somewhere.

I'm wondering if this might be related to how ExecJS might be evaluating the code? Does this ring any bells?

(And to be extra clear, this error executes when evaluating styled components lib code, which is guarded against window.)

justin808 commented 5 months ago

Hi @damassi,

I'm 100% sure that you can use React on Rails Pro with Styled Components SSR. I've helped many companies use Styled Components with React on Rails Pro.

For an example, you can check the page source of SkillBreak.

oneflare uses React on Rails Pro and Styled Components for their admin app.

Please book a time to meet me, and I can tell you more—or email me.

damassi commented 5 months ago

Thanks. I figured the pro version would be compatible due to how we've worked with styled components in our Node app. I was mostly wondering about possible ExecJS evaluation issues that might be obvious, but which I'm overlooking.

Ie, I would assume that code guarded with

if (typeof window !== "undefined") {
  window.foo = "bar"
} else {
  // is server 
}

would be safe to run in a standard React on Rails SSR environment, but if that is not the case it would be good to know.

justin808 commented 5 months ago

For sure, window is not available in SSR in any environment, Node, or ExecJS.

damassi commented 5 months ago

Right! However, many libraries that might have some window based functionality (like a CSS-in-JS library) still support SSR rendering, like styled-components, and they do so by guarding client-based code against execution in a server-based environment (via typeof window !== 'undefined').

(Using typeof foo !== 'undefined' is the canonical way in which one checks for the existence of certain classes of objects from within different environments. It does not evaluate the object, and is different from, say, if (!window), which does.)

I am wondering why this check and / or typeof (seems) to not be respected when executing within ExecJS / React on Rails, where the exact same code in Node is properly guarded against, and correctly SSR rendered. My assumption is that I would be able to literally copy and paste simple react code between the two environments and it would just work.

If this doesn't ring any bells feel free to close this issue and I'll continue digging a bit deeper at the lib level and try to get to the bottom of what's going on.

justin808 commented 5 months ago

@damassi, why not try out React on Rails Pro? There are many other benefits to it, and you're supporting the open-source efforts.

damassi commented 5 months ago

If we had the budget for it, perhaps, but whatever the issue might be does seem solvable. (And in any case, for our use-case, we're trying to upgrade a legacy app where this is less of a priority.)

Thanks for the very cool lib, though. In all other cases React on Rails seems to work perfectly and the codebase is a beauty.

I'll open a PR or reopen the issue if I discover something obvious.

Judahmeek commented 4 months ago

@damassi A stack trace of the error should tell you if the guard clause is failing to properly protect references to window or if react_on_rails is detecting the window reference prematurely.