hung-phan / generator-rails-react-webpack

Integrate Ruby on Rails with React.js and Webpack
56 stars 9 forks source link

server side render does not work #14

Open luizkowalski opened 8 years ago

luizkowalski commented 8 years ago

Although the gemfile contains react-rails, when one tries to server side render with

render component: 'Dashboard', props: { key: auth_hash['credentials'] }

The following error appears

Encountered error "ReferenceError: Dashboard is not defined" when prerendering Dashboard with {"key":
....
hung-phan commented 8 years ago

Did you try to expose that components to the window environment? You can try via expose-loader or even use:

import Component from 'path/to/component;
window.Component = Component;
hung-phan commented 8 years ago

Also the react-rails is for rendering simple components that are in the assets folder. The current build is using webpack, so I suggest to use hypernova instead

hung-phan commented 8 years ago

Also this will have to follow this guide, can you check?

luizkowalski commented 8 years ago

Hypernova is an overkill for what I'm trying to do, IMO and yes, I checked the react-rails docs, but as you pointed, it is for rendering components that live under assets folder. I also tried to add a new route /dashboard on routes.js but as I thought, when a redirect to this route, rails says it doesn't exists. I see two options here: go full react-rails or full js (no rails)

hung-phan commented 8 years ago

Oh, that part redirects to react route. You need to write a custom handler for that (Same as the wildcard for route). This could be an example for that https://github.com/hung-phan/koa-react-isomorphic/blob/master/app/server/controllers/application.js.

  router.get('*', async (ctx) => {
    ctx.body = await ctx.prerender('application/index.marko');
  });

This will be the routing in the server. And then we handle the prerender and push data to client side. It could be quite complex to achieve with rails server.

You can configure your pool of JS virtual machines and specify where it should load code:

# config/environments/application.rb
# These are the defaults if you don't specify any yourself
MyApp::Application.configure do
  # Settings for the pool of renderers:
  config.react.server_renderer_pool_size  ||= 1  # ExecJS doesn't allow more than one on MRI
  config.react.server_renderer_timeout    ||= 20 # seconds
  config.react.server_renderer = React::ServerRendering::SprocketsRenderer
  config.react.server_renderer_options = {
    files: ["react-server.js", "components.js"], # files to load for prerendering
    replay_console: true,                 # if true, console.* will be replayed client-side
  }
end

My guess is some how we can rewrite this config.react.server_renderer = React::ServerRendering::SprocketsRenderer then we are good to go.

hung-phan commented 8 years ago

By the way, in the prerender method, it will check for the route in react-router. It will throw error if it cannot find that route. It is the current implementation in my project.

hung-phan commented 8 years ago

Let me try to integrate with the rails server, and post it here. Just keep this one open.