0
votes

I have looked for an answer to this online, google etc..but I can't find anything to help me do what I'm trying :

Here's the scenario - I've clojure code running a jetty server instance and serving content including html generated by hiccup.

I've added clojurescript into the mix to serve frontend using reagent. E.g. the page served by jetty has and div id="app" and the reagent compiled app.js rewrites the dom for this.

So far everything works ..I've configured lein to run the clojure code and build clojurescript code into app.js and put it in asset path in my lein config.

Now I'm trying hot reloading of this app.js code by using figwheel-main..but I'm not getting anywhere. Using figwheel-main, it opens a separate browser url which can hot reload stuff..but this is not connected to the clojure backend which is serving the content. i.e figwheel-main showing the clojurescript code on localhost:9500 whereas jetty is running on port 3000.

I want to be able to see hot reloading of app.js served by the jetty instance when i modify clojurescript code.

I can't figure out how to get this done.

I've tried the configs from figwheel-main tutorial -i.e deps.edn etc. but can't figure out how to intergrate it with the existing clojure code.

(defproject myproject "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :dependencies [[org.clojure/clojure "1.10.0"]
                 [metosin/reitit "0.3.7"]
                 [ring "1.7.1"]
                 [migratus "1.2.3"]
                 [com.h2database/h2 "1.4.199"]
                 [org.postgresql/postgresql "42.2.5"]
                 [org.clojure/java.jdbc "0.7.9"]
                 [cumulus "0.1.2"]
                 [com.layerware/hugsql "0.4.9"]
                 [selmer "1.12.12"]
                 [ring-webjars "0.2.0"]
                 [ring/ring-anti-forgery "1.3.0"]
                 [hiccup "1.0.5"]
                 [org.clojure/clojurescript "1.10.520" :scope "provided"]
                 [reagent "0.8.1"]
                 [cljs-ajax "0.8.0"]
                 [org.webjars.npm/bulma "0.7.4"]
                 [org.webjars/font-awesome "5.3.1"]]
  :main ^:skip-aot myproject.core
  :source-paths ["src/clj"]
  :resource-paths ["resources" "target/public"]
  :target-path "target/%s"
  :clean-targets ^{:protect false}
  [:target-path
   [:cljsbuild :builds :app :compiler :output-dir]
   [:cljsbuild :builds :app :compiler :output-to]]
  :cljsbuild {:builds
              [{:source-paths ["src/cljs"]
                :compiler {:main "myproject.core"
                           :asset-path "js/out"
                           :optimizations :none
                           :source-map true
                           :pretty-print true
                           :output-to "target/cljsbuild/public/js/app.js"
                           :output-dir "target/cljsbuild/public/js/out"}}]}
  :plugins [[lein-cljsbuild "1.1.7"]]
  :profiles {:uberjar {:aot :all}
             :dev {:repl-options
                   {:init-ns myproject.core}}

I expect figwheel-main to work with the content already being served by jetty

2

2 Answers

2
votes

Please keep in mind that you have two programs running now, one in CLJS in the browser and another one in CLJ on the backend. They communicate over the network which adds in more complexity.

If you are already using Reagent in your CLJS code, you should add the hiccup there (as a Reagent component) instead of on the backed.

If you have data on the backend, then grab it from the backend CLJ code via an AJAX call, then render it on the frontend via hiccup, SVG, etc. We do this with a large CLJ + CLJS app at work, where the backend code is only accessed via AJAX calls (basically an asynchronous subroutine call).

1
votes

One option could be to have a web server (say, Nginx listening on port 9000) running during development that would mask the different ports where Figwheel and Jetty are running.

You could configure Nginx serve the location / for static files by forwarding the request to Figwheel on port 3449 and the location /api to Jetty on port 3000 (where your backend is served by Jetty).

During development, you'd connect to port 9000 and it would look like everything is running on that port. One thing that I'm not sure is the websocket that Figwheel uses, but it's worth trying.

You can look for an example in the Nginx documentation: https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/ but an example configuration would look like this:

server {
  listen 9000;
  listen [::]:9000;

  location / {
      proxy_pass http://localhost:3449/;
  }

  location /api {
      proxy_pass http://localhost:3000/;
  }

}