Skip to content

HMR and Server-Side rendering results in window is not defined #925

Closed
@arminfro

Description

@arminfro

Steps to reproduce

  • start webpack-dev-server
  • <%= react_component('HelloWorld', { greeting: 'hello' }, prerender: true) %>

webpacker.yml ( diff to default, docker environment )

dev_server:
    host: 0.0.0.0
    public: 0.0.0.0:3035
    hmr: true

Expected behavior

Rendering of page

Actual behavior

ExecJS::ProgramError ReferenceError: window is not defined

System configuration

Sprockets or Webpacker version: 3.12.0
React-Rails version: 2.4.7
Rect_UJS version: 2.4.4
Rails version: 4.2
Ruby version: 2.3


When I request the page without server rendering (e.g. <%= react_component('HelloWorld', { greeting: 'ho' }) %>) or when I disable HMR (e.g. hmr: false) it works fine. But leaving it results in described error.

Since there is a fixed issue with the same error in #615 I wonder if I'm missing something obvious? Something like prerender_polyfill.js doesn't seem to work in my case.

Stack trace beginning from a view file:

/app/javascript/components recursive ^\.\/.*$.map../GoodbyeWorld ((execjs):39:41)
(execjs):762:10
(execjs):34182:14
global ((execjs):1:102)
Object.<anonymous> ((execjs):1:120)
Module._compile (module.js:652:30)
Object.Module._extensions..js (module.js:663:10)
Module.load (module.js:565:32)
tryModuleLoad (module.js:505:12)
Function.Module._load (module.js:497:3)
execjs (2.7.0) lib/execjs/external_runtime.rb:39:in `exec'
execjs (2.7.0) lib/execjs/external_runtime.rb:14:in `initialize'
execjs (2.7.0) lib/execjs/runtime.rb:57:in `new'
execjs (2.7.0) lib/execjs/runtime.rb:57:in `compile'
execjs (2.7.0) lib/execjs/module.rb:27:in `compile'
react-rails (2.4.7) lib/react/server_rendering/exec_js_renderer.rb:13:in `initialize'
react-rails (2.4.7) lib/react/server_rendering/bundle_renderer.rb:30:in `initialize'
react-rails (2.4.7) lib/react/server_rendering.rb:17:in `new'
react-rails (2.4.7) lib/react/server_rendering.rb:17:in `block in reset_pool'
connection_pool (2.2.2) lib/connection_pool/timed_stack.rb:171:in `try_create'
connection_pool (2.2.2) lib/connection_pool/timed_stack.rb:83:in `block (2 levels) in pop'
connection_pool (2.2.2) lib/connection_pool/timed_stack.rb:79:in `loop'
connection_pool (2.2.2) lib/connection_pool/timed_stack.rb:79:in `block in pop'
connection_pool (2.2.2) lib/connection_pool/timed_stack.rb:78:in `synchronize'
connection_pool (2.2.2) lib/connection_pool/timed_stack.rb:78:in `pop'
connection_pool (2.2.2) lib/connection_pool.rb:93:in `checkout'
connection_pool (2.2.2) lib/connection_pool.rb:62:in `block in with'
connection_pool (2.2.2) lib/connection_pool.rb:61:in `handle_interrupt'
connection_pool (2.2.2) lib/connection_pool.rb:61:in `with'
react-rails (2.4.7) lib/react/server_rendering.rb:26:in `render'
react-rails (2.4.7) lib/react/rails/component_mount.rb:67:in `prerender_component'
react-rails (2.4.7) lib/react/rails/component_mount.rb:34:in `block in react_component'
actionview (4.2.10) lib/action_view/helpers/capture_helper.rb:38:in `block in capture'
actionview (4.2.10) lib/action_view/helpers/capture_helper.rb:202:in `with_output_buffer'
haml (5.0.1) lib/haml/helpers/action_view_xss_mods.rb:6:in `with_output_buffer_with_haml_xss'
actionview (4.2.10) lib/action_view/helpers/capture_helper.rb:38:in `capture'
haml (5.0.1) lib/haml/helpers/action_view_mods.rb:47:in `capture_with_haml'
actionview (4.2.10) lib/action_view/helpers/tag_helper.rb:106:in `content_tag'
haml (5.0.1) lib/haml/helpers/action_view_mods.rb:56:in `content_tag_with_haml'
react-rails (2.4.7) lib/react/rails/component_mount.rb:50:in `react_component'
react-rails (2.4.7) lib/react/rails/view_helper.rb:21:in `react_component'
app/helpers/application_helper.rb:389:in `react_component'
app/views/shop_manage/galleries.html.erb:12:in `_app_views_shop_manage_galleries_html_erb__1251111634569882468_205190840'

In case you wonder react_component in application_helper does nothing exciting, just sets instance variable and calls super.

Activity

BookOfGreg

BookOfGreg commented on Aug 21, 2018

@BookOfGreg
Member

This is a common error, normally caused by someone trying to include npm packages which only run client-side.

Just tested on a blank rails app with webpack-dev-server running and rendering server-side.
image

It's possible you have included some JS that is badly behaved and tried to access Window when rendering server-side. That package wouldn't run on a normal NodeJS server so it won't run in SSR anyway.

What I checked:

rails new foo --webpack=react
cd foo
# Add react-rails to gemfile
bundle install
rails g scaffold bar
rails g react:install
rails g react:component bar
# add <%= react_component 'Bar', {}, prerender: true %> to index.html.erb
# add <%= javascript_pack_tag 'application' %> to application.html.erb
# run bin/webpack-dev-server in one tab
# run rails s in another tab
open http://localhost:3000/bars

Can you provide a more complete reproduction? The gem works when following the start of the Readme in the standard case, so there is information that I'm missing in order to help you.

arminfro

arminfro commented on Aug 23, 2018

@arminfro
Author

Reproduction script:

#!/bin/bash 

gem install rails --version=4.2.0 --no-ri --no-rdoc
rails _4.2.0_ new foo
cd foo
bundle install
bin/rails g scaffold bar
echo "gem 'webpacker'" >> Gemfile
echo "gem 'react-rails'" >> Gemfile
bundle install
bin/rake webpacker:install
bin/rake webpacker:install:react
bin/rake db:migrate RAILS_ENV=development
bin/rails g react:install
bin/rails g react:component HelloWorld greeting:string
echo "<%= react_component('HelloWorld', { greeting: 'hello' }, prerender: true) %>" >> app/views/bars/index.html.erb
# adding "<%= javascript_pack_tag 'application' %>" to `body` in app/views/layouts/application.html.erb
# change 'hmr: false' to 'hmr: true' in 'config/webpacker.yml'
# start 'bin/webpack-dev-server'
# start 'bundle exec rails server -e development'
# request 'http://localhost:3000/bars'

The last five steps needs to be done manually, the lines before can be executed as a shell script and results in the described ReferenceError: window is not defined

changed the title [-]HMR and ServerSide Rendering results in `window is not defined`[/-] [+]HMR and Server-Side rendering results in `window is not defined`[/+] on Aug 23, 2018
BookOfGreg

BookOfGreg commented on Aug 23, 2018

@BookOfGreg
Member

Thank you a bunch for the reproduction, that clears it up.

I'll make a guess that HMR is causing SSR to fail, which would make sense as there is no reloading in a serverside world.

We don't currently have the ability to support HMR so I'm unable to help you at this time. It is a desirable feature though.

arminfro

arminfro commented on Aug 23, 2018

@arminfro
Author

Thank you for the confirmation ( and for your work on react-rails gem ;)

My team is just starting to migrate our project to use react-rails and webpacker, so this is all new to us.

As you pointed out it does not make sense to have HMR in server rendering mode, but as far as I understand it, this is only true for the first rendering, isn't it?
Cause all the webpack (and react) sources gets send to the client anyway and further renderings will be done on client-side. That brings me to the assumption that webpacker just needs a case for not relying on the window object on first render, which (maybe) means the issue should be addressed in webpacker gem, I'm not sure.

BookOfGreg

BookOfGreg commented on Aug 23, 2018

@BookOfGreg
Member

For now I recommend not using HMR when using SSR in this gem. It's part of the longer-term plan that I would like it to work successfully but I haven't had the time to be able to enable it yet.

It's possible to get them to work together as I'm keeping my eye on the renchap/webpacker-react project as they are working at merging the HMR with SSR in this PR.

It's definitely our project to sort as the upstream webpacker gem does let you use HMR, we just need to be clever about not running the module.hot code serverside.

arminfro

arminfro commented on Aug 23, 2018

@arminfro
Author

Interesting, thanks for the explanation! I'm looking forward to it 😊

andrewscarani

andrewscarani commented on Dec 10, 2019

@andrewscarani

Is there any way for me to configure react-rails such that it would ignore prerender: true when hmr: true in webpacker.yml? Thus I could turn SSR on/off via the single hmr flag?

gencer

gencer commented on Dec 17, 2019

@gencer

Interestingly, I have hmr set to false. But still face with this issue.

gencer

gencer commented on Dec 17, 2019

@gencer

Well, It is because somewhere in the config i setup jQuery. This was the reason for window issue.

7 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jakeonfire@BookOfGreg@alkesh26@justin808@gencer

        Issue actions

          HMR and Server-Side rendering results in `window is not defined` · Issue #925 · reactjs/react-rails