A poc of rendering a React single page app on the server for the initial page load.
JavaScript Clojure
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
resources/public/js
src/react_nashorn_example
.gitignore
README.md
project.clj

README.md

react-nashorn-example

Blog post: http://augustl.com/blog/2014/jdk8_react_rendering_on_server/

This is a single page web app, where the initial page is also served as plain HTML, without any extra work or code duplication required!

When you click links in the web site (and JS is enabled), the single page web app will do all the page loading with JS. But because the initial page (and all pages) is loaded from the backend, your app will be indexable by Google, and also really fast! You don't have to wait for the JS to load to see the content, since it's served statically from the backend.

Running

You need JDK1.8, see next section if you don't have it.

Run the app with:

lein server

Then open http://localhost:4567 in a browser, and enjoy!

Leiningen is Clojure's build tool, if you don't have it, see https://github.com/technomancy/leiningen

Installing JDK1.8

Linux

Use your package manager!

Alternatively, if you don't want to replace your system java, do the following:

  • curl -LO -b oraclelicense=a http://download.oracle.com/otn-pub/java/jdk/8-b132/jdk-8-linux-x64.tar.gz
  • For 32bit, replace x64 in the end of the URL with i586
  • Extract
  • export PATH=/path/to/jdk1.8.0/bin:$PATH

Mac OS X

Please contribute a pull request :)

Windows

Please contribute a pull request :)

Tradeoffs

Your React code has to use plain JS only, and not invoke any 3rd party components that requires a DOM. Facebook React supports rendering to a string without a DOM, which is what we actually do on the back-end. If a component invokes a jQuery plugin, you'll get an exception and the backend won't be able to render that page.

I'm not an experienced React user, so I'm not sure how this problem is typically solved. Pull requests are welcome.

TODO

This is a POC. It would be nice with some kind of reusable library. That can probably happen when this todo-list becomes empty.

  • Use a real router, not a simple if/return/regexp based home made thingie.
  • Is it OK that the JS performs a request to the API for the data a second time, when the JS loads? Time has passed so you risk getting different data. Serializing the props used in the HTML is a possibility. Using Datomic is another, put the datomic T that was used by the backend in the HTML somewhere so the scripts can read and use it.

Copyright

Copyright © 2014 August Lilleaas