Creating websites with shadow-cljs + gatsby or next.js


#1

Gatsby.js is a static PWA (Progressive Web App) generator.

gatsby is a pretty popular JS tool to build websites using React. The question whether its possible to use it with CLJS has come up a few times in the past and I got curious in how shadow-cljs could help with that.

For anyone interested I created a sample repo that recreates parts of their default starter template.

The basic idea is that you create normal CLJS defn per “page” and slap some metadata on it. The metadata will be used by a shadow-cljs build-hook to create the src/pages files that gatsby will look for. The files basically just map to the the CLJS defn to the data that gatsby expects. All code is written in CLJS and no JS code is used. The site directory was generated by gatsby new and the shadow-cljs build will output the relevant files to site/src.

I would not recommend that anyone actually builds a full site using this since it is a pretty bad fit IMHO. gatsby has certain assumptions that don’t map well to CLJS. What doesn’t work at all is the use of their StaticQuery component since they process the actual JS AST to extract the queries at compile time. Since it doesn’t understand the code generated by CLJS it just fails to extract the queries. Not sure if that can be “fixed”.

I don’t ever plan on using gatsby myself but maybe this is useful for someone.


#2

Thanks for this.

I use Gatsby a lot and I’ve been itching to get it working with cljs. But, like you mentioned, they do some weird “magic” things with the raw js code that makes it a difficult to get working.


#3

Thanks for your efforts. I played a bit with Gatsby and came to the conclusion that it’s too much overhead for simple projects to mess around with Cljs tooling.


#4

I did the same experiment with next.js and it also works ok-ish.

The “major” problem however is that their SSR support serializes all data to JSON which means it’ll lose important CLJS type such as sets, keywords, symbols when converting back to EDN. This however could probably be worked around.

As with gatsby I don’t think this is a good fit for CLJS but it does work ok-ish.


#5

I’ve looked at a lot of the options out there and was not happy with the overall experience working with these tools. I am quite happy with the experience I have had with Shadow Cljs and think we can put something nice together which is much more closer and integrated with Clojure and Clojurescript (possibly even more stable and simpler). Depending on these other tools to create websites doesn’t offer much other than the large number of plugins produced by the community. Despite this people are still very productive and are making awesome stuff in Clojure and Clojurescript.


#6

In the future next.js might cut the dependency on webpack, not sure if that would make things easier. Would it be possible to use transit to keep everything in the json?


#7

transit is probably possible but still won’t be very efficient since I don’t think you can hook into this globally. So you end up with maybe calling transit once per Object. I did not spend too much time with next.js though, so it may be possible to customize all of this.

After looking at both options however I do agree that we can probably build something more usable in CLJS itself. I may experiment myself a bit given how much of the heavy-lifting shadow-cljs in regards to CLJS/JS already does. Generating a bit of boilerplate code + HTML should not be that difficult.


#8

All the work I am doing towards creating a Clojure tool similar to Gatsby etc can be tracked here.