1

I wrote a web application in Reagent, and I develop and run it locally using Figwheel, which is great. Now I want to deploy it, so I ran "lein ring uberwar". It says "Compiling ClojureScript..." (3 times!), which sounds promising. But then when I deploy the war file and visit the page, I get a flash of:

ClojureScript has not been compiled!
please run lein figwheel in order to start the compiler

before the application kicks in.

Should Figwheel even be involved in production deploys? Can I build an uberwar that doesn't have this FOUC-like flash?

I found How do I deploy a single-page app. written in ClojureScript / Figwheel to a static server? but it seems to start from scratch (not Reagent-specific), and a lot of the links are dead.

I'm not familiar with how figwheel/uberwar work so I don't even know what to try.

This happens even with a plain 0.8.1 Reagent project, AFAICT.

I see a Figwheel warning text very briefly, when I first visit the page. I'd like to see nothing at all, until the page loads. (Or maybe let me put in a custom spinner or something, but one thing at a time.) I'd also like to not have to package and send unnecessary Figwheel code to every client, because it's not big but it should never be needed there.

2 Answers2

0

I think you are looking for lein uberjar:

~/expr/cljs-enflame > lein uberjar
Created /home/alan/expr/cljs-enflame/target/cljs-enflame-0.1.0-SNAPSHOT.jar
Created /home/alan/expr/cljs-enflame/target/cljs-enflame-0.1.0-SNAPSHOT-standalone.jar

You can then deploy the standalone version, and kick off your program with a command like:

> java -jar target/cljs-enflame-0.1.0-SNAPSHOT-standalone.jar

where you specify the main program entry point in project.clj like:

:main  demo.hello
Alan Thompson
  • 29,276
  • 6
  • 41
  • 48
  • Hmm, everything you say is true, and the reagent template includes the correct `:main` already, so I do get a jar file which compiles everything into a single impressively compact "app.js". But then it's not a war file, so I can't just pass it to my Tomcat server as-is -- it looks like I'd need to provision a new server environment with a different platform. Is there any way to get the benefits of uberjar compilation, but in an uberwar? – user11317845 Apr 05 '19 at 17:43
  • I have not used a uberwar before. Usually have a clj backend, and the cljs file `myapp.js` is under ./resources/public/compiled/myapp.js` and referenced from the clj server code. However, if you are getting `app.js` compiled OK, can't you just deploy it like any other JS app? – Alan Thompson Apr 05 '19 at 17:52
  • A reagent app has client-side JS, server-side code, minified CSS, etc. That's the benefit of a single warfile: I hand it to Tomcat and it just works. Making an uberjar (for compilation) only to unpack it and re-deploy the pieces individually sounds like more work (and more opportunity for me to screw up) than re-provisioning my production server for a Tomcat-less Java SE platform. – user11317845 Apr 05 '19 at 18:07
  • ...`re-provisioning my production server for a Tomcat-less Java SE platform`... That's what I meant. It is easy if the Java main() method (could be Clojure) kicks off a Jetty server, and then everything is in a single uberjar file. – Alan Thompson Apr 05 '19 at 18:50
  • OK, I've resigned myself to this for the afternoon, but ideally I would have liked to have avoided that. Is there no way to uberwar a reagent app with full AOT compilation? These two (uberjar/uberwar) even share the same lein profile -- why such a drastic difference in output functionality? – user11317845 Apr 05 '19 at 19:30
  • Maybe re-title your question, specifically asking for uberwar help. – Alan Thompson Apr 05 '19 at 19:54
0

I think your packaging process will require two steps:

  • First: Compile the ClojureScript code with a production profile. You probably have something like that available with lein cljsbuild prod once or a similar target. The idea is that you want the production profile to produce that single, optimized JavaScript file that will be served by Tomcat as a static resource.

  • Second: build the WAR file for Tomcat, with lein ring uberwar.

Depending on how you serve static files from your web application, the path to the static resources may change, but unless you add any other configuration, you'll be either serving the static resources as explained in this answer: https://stackoverflow.com/a/7820392/483566

Denis Fuenzalida
  • 3,271
  • 1
  • 17
  • 22