I’d like to share intermediate results of my work with Universal (aka “Isomorphic”) JavaScript apps, based on React library from Facebook and Ruby on Rails as a backend.
Actually, it’s not that much about Rails, but about JSON API. So if you don’t use/like Rails, just take it as an abstract API and keep reading.
If you haven’t heard about isomorphic javascript concept, here is the link that explains what it’s all about.
I’ve been trying to implement JS server side rendering within Rails app using react-rails gem, but it’s not the way to go. Tools play best in environments, for which they were designed. So I cut the whole front-end stuff out of Rails and moved it to Node.js
.
Here is the first draft:
Rails, which became simply JSON API, is responsible for data and React handles UI part using the same javascript codebase on the server and on the client. Worth to note, we can use Rails as API for mobile app and other services interested in our data.
Let’s go deeper. When user hits http://my-app.com
, request goes to a Node.js server with Express on top. We need data to render initial html and send a response. So we fetch it from Rails API via http request. When data are arrived, React renders a view and Express sends html to the client with JS app, which takes control over the flow. When a user hits some link on the site, app makes an ajax call to fetch new data and updates views on the client.
Front-end app lives on the main domain: http://my-app.com
. But for API we have options:
Next we need to decide how data will be fetched from API.
Because of the same-origin policy we can’t make ajax requests from one location to another (even if a target resource on the same domain but different port). To enable such kind of requests we must apply Cross-Origin Resource Sharing (CORS) mechanism.
If you’ll choose to go this way, you need to set special http headers on a Rails side. This way browser is verifying that caller have the rights to send ajax requests to this server.
Keep in mind that by enabling CORS (especially public access) you dig potential CSRF security hole. Read this carefully to mitigate CSRF attacks.
Instead of enabling CORS, we can proxy requests through nginx
front-end server. Every call goes to the same domain: my-app.com
. Nginx splits it in two directions:
/api
, which are proxied to Rails API.This approach is more secure and the whole system looks solid from outside. So we will go this way, but it requires some additional setup on local machine.
Install nginx
:
Edit nginx.conf
:
Extend http
block in the config with upstreams:
Finally, run nginx:
Now you can visit http://lvh.me
in your browser. There will be nginx error message. It’s ok, because Node.js app is not yet running.
Stop nginx for now:
Also, you may want to add lvh.me
to hosts
file to avoid unnecessary roundtrips:
And add:
You can find other posts of this series on my medium but they are pretty much out of date at this point.