How we embedded ClojureScript in our GitHub pages

Ever wondered if you can embed ClojureScript in a GitHub blog? The answer is:
of course you can! At the end of the day, ClojureScript just translates to
plain old JavaScript that can be included in any web page.

Here at Scalac, we are always trying to be innovative and creative in
everything we do. This is why when I heard that we were planning to write some
blog post on Clojure/ClojureScript, I asked myself: why can’t I write a
ClojureScript post in ClojureScript itself?

The advantage of this is evident, our pages will be way more interactive and
therefore interesting to read, play with and learn from.

In order to start, I want first to give the reader some general notion on how
the compiler works and why it is so powerful. I am not going to spend too much
time on it because you can find better detailed articles out there.

The most significant difference between Clojure and ClojureScript is that
ClojureScript concretely isolates the code interpretation phase (reading in
Lisp terms) from the actual compilation phase (analysis and emission). The text
that a programmer writes is read by the ClojureScript reader, then passed to
the macro expansion stage and ultimately to the analyzer. The outcome is the
abstract syntax tree (AST), a tree-like metadata-reach version of it.

This is paramount for a bunch of obvious reasons, but mostly because you have
separation of concerns between tools that understand text and tools that
understand ASTs, like compilers. Indeed this is why ClojureScript can actually
target disparatekinds of
platforms: in order to emit
instructions belonging to the X programming language you “only” need your own
compiler to read the AST, prune it and emit. This is also how currently the
Google Closure Compiler is employed in order to emit optimized JavaScript.

GitHub blog posts are nothing but standard .md files that Jekyll builds
locally and then serves. The Markdown syntax allows adding standard HTML tags
and consequently JavaScript <script> tags. Therefore, embedding ClojureScript
was relatively easy once I got pass configuring it. This is
mainly why I thought writing a blog post might be a good idea and save some
folk’s time.

I wanted to be able to plug my changes in transparently, still allowing to
create posts without Clojure. A simple start.sh was previously used to create
.md files in Jekyll’s _posts folder that then had to be worked on by the
author and committed.

Instead, I needed to create fully-fledged ClojureScript projects, potentially
one per blog post, somewhere. I chose to hide them in a brand new _cljs
folder as git submodules and for this reason I added a few lines to
start.sh for:

Performing git submodule add.

Materializing the project with lein new <template> <project-name>.

As before, copy the .md template to _posts.

Now switching to the project folder was showing me the reassuring sight of the
project.clj file.

I wanted to be smarter about emitting JavaScript and tried to deploy directly
inside Jekyll’s scripts folder. According to my template default, the
JavaScript was emitted to <project-name>/resources/public/js/compiled so I
changed my <project-name>/project.clj to:

Remember that we are inside a project folder under _cljs, therefore Jekyll’s
root is two directories up. Typically, only :output-to is significant for the
final version as this option contains the path of the generated (and minified)
.js file. In jekyll-dev though, you can also specify :output-dir, which
is where temporary files used during compilation are written, and
:asset-path, that sets where to find :output-dir files at run-time. This
way you have full visibility of the output.

Now I was finally able to cd to my project, execute lein cljsbuild once
jekyll, and see my generated .js in scripts. Hooray!

The last piece of the puzzle was to run the actual JavaScript code inside the
Markdown blog page. There are many ways to do this, but the one I found most
intuitive and straightforward was by using
reagent. This is not a post about
reagent per se (we wrote about it some time
ago),
but its lean and unopinionated architecture struck me as the way to
go. Reagent, a React wrapper, dynamically mounts DOM elements and
re-renders them when necessary, effectively hiding the complications of
managing React component’s life cycle.

Consequently, on the HTML side I needed to: define a mounting point,
include the compiled .js and trigger the JavaScript main() which mounts my
app. My .md became:

Note that it is very important to prepend a slash to script and replace
dashes with underscores in the last JavaScript call. The reason is that the
compiler always transforms namespace dashes in underscores.

On the ClojureScript side instead I needed to ensure that the <div> with id
cljs-on-gh-pages was correctly mounted:

Now every time the blog post page is shown, reagent intercepts the div and
renders anything our main() returns, typically
Hiccup-crafted react components,
like page above.

If you have had the patience of reading till the end, here is a reward for you: a
ClojureScript REPL to toy with!

Thanks to highly skilled
ClojureScripthackers and Clojure being a
homoiconic language, it is not
surprising that it can compile itself and run into a self-hosted environment.

Self-hosted means that the language provides itself the environment where to
run, which in this case is the set of JavaScript functions that are performing
the code evaluation. The JavaScript, in turn, being compiled from ClojureScript
source. Convoluted and awesome.

Not everything works in this ClojureScript-in-ClojureScript habitat at
the moment. However, thanks to other inspiring implementations, here too
you have access to Clojure’s superpowers. Note that the REPL has history (up
to start, up/down to navigate) plus
other handy shortcuts. Enjoy!