Last weekend I worked my way through the introductory tutorial for React.js. It’s very well written and easy to follow, I was really happy with it overall.
For the uninitiated, React.js is a framework that provides a means to create reusable javascript components that emit HTML in a very intuitive way. Taking that concept a step further, its possible to use React on the backend, utilizing the same components to build the UI that is served to the user initially. The end result is very interesting. React prescribes an intuitive and scalable approach to building complex, dynamic user interfaces as highly reusable components.
These user interfaces avoid the redundancy of generating and manipulating HTML twice – once on the server, and again in the browser.
The server-side rendering feels like a natural pattern in a Node.js environment, but there are examples in the wild of doing server-side rendering with other platforms, most notably clojure. This is exciting stuff.
React has been around for a while, but this is the first time I’ve taken a close look at it.
The tutorial focuses on building a simple font-end application rendered entirely in the browser. Initially, you work with a standalone HTML page, and near the end, you integrate it with a simple web application.
The source repository for the tutorial provides some example applications written in Python, Ruby and Node.js.
A simple application like this seemed like an ideal use case for a simple boot script, so I decided to write one of my own. Here’s the code inline, but I’ve forked the repository if you’d like to examine the code along-side its cohorts.
#!/usr/bin/env boot
(set-env!
:dependencies
#(into % '[[org.clojure/data.json "0.2.5"]
[ring/ring-core "1.3.2"]
[ring/ring-jetty-adapter "1.3.2"]]))
(require '[ring.adapter.jetty :as jetty]
'[clojure.data.json :as json]
'[ring.middleware.params :refer [wrap-params]]
'[ring.util.response :refer [file-response response]])
(defn static
[request]
"Handle static file delivery"
(let [uri (:uri request)
path (str "./public" uri)]
(if (= uri "/comments.json")
(file-response "./_comments.json")
(file-response path))))
(defn save-comments
[request]
"Save the comments to the json file, and return the new data"
(let [data (json/read-str (slurp "./_comments.json"))
input (:form-params request)
out (concat data [input])
new-json (json/write-str out)]
(spit "./_comments.json" new-json)
(response new-json)))
(defn handler
[request]
"Simple handler that delegates based on the request type"
(case (:request-method request)
:post (save-comments request)
:get (static request)))
(def app
"Add middleware to the main handler"
(wrap-params handler))
(defn -main
[& args]
(jetty/run-jetty app {:port 3000}))
Essentially, it sets up two handlers, and then a dispatcher that proxies between them depending on the type of request. If the request is a GET, a static file is assumed. This serves the html and any local dependencies. If the request is specifically for comments.json
, the handler serves the _comments.json
file.
If the request is a POST, its assumed that the body of the request contains a JSON-encoded comment to add. It deserializes that data and the _comments.json
file, and appends the new comment to the list. The result is then saved to the filesystem.
Obviously, there is little in the way of error checking going on here. This tracks with the scope of the other example applications.
Note: It’s not clear to me exactly why they used _comments.json
to store the data – in my initial prototype I named it comments.json
and placed it with the other static files.
Interestingly, this boot script also serves as a minimalistic example of a web application using ring – including adding middleware.
This was a fun way to finish up a really informative tutorial – I’m excited to continue exploring what React.js can do, especially with Clojure!
Special thanks to alandipert and ul from #hoplon for code review and some great advice on cleaning up my initial implementation!
DevOps Is Bullshit: Why One Programmer Doesn’t Do It Anymore
I’ve always been handy with hardware. I was one of “those kids” you hear about that keeps taking things apart just to see how they work – and driving their parents nuts in the process. When I was a teenager, I toyed with programming but didn’t get serious with it until I decided I wanted to get into graphic design. I found out that you don’t have to write HTML yourself, you can use programming to do it for you!
But I never stopped tinkering with hardware and systems. I used Linux and BSD on my desktop for years, built my LAMP stacks from source, and simulated the server environment when I couldn’t – when I used windows for work, and when I eventually adopted Apple as my primary platform, I first started with cross-compiled versions of the components, and eventually got into virtualization.
Continue reading →
Share this: