I am trying to build on the Pedestal tutorial app available here.
I am trying to add cljs functionality and trying to setup a unified clojurescript and clojure environment.
My deps.edn file looks as follows:
{:paths ["src"]
:deps {io.pedestal/pedestal.service {:mvn/version "0.5.7"}
io.pedestal/pedestal.route {:mvn/version "0.5.7"}
io.pedestal/pedestal.jetty {:mvn/version "0.5.7"}
org.slf4j/slf4j-simple {:mvn/version "1.7.28"}
org.clojure/core.async {:mvn/version "1.3.610"}
org.clojure/tools.namespace {:mvn/version "1.1.0"}
org.clojure/tools.logging {:mvn/version "1.1.0"}
org.clojure/data.json {:mvn/version "1.1.0"}
org.clojure/clojurescript {:mvn/version "1.10.758"}
thheller/shadow-cljs {:mvn/version "2.11.23"}
selmer/selmer {:mvn/version "1.12.33"}
hiccup/hiccup {:mvn/version "1.0.5"}}
:mvn/repos {"central" {:url "https://repo.maven.apache.org/maven2/"}
"clojars" {:url "https://clojars.org/repo/"}}}
My Shadow-cljs.edn file is as follows
{:source-paths ["src/cljs"]
:nrepl {:port 9000}
:dependencies [[cider/cider-nrepl "0.21.0"]]
:builds {:app {:target :browser
:output-dir "resources/public/js"
:modules {:main {:init-fn frontend.core/init-fn}}}}}
My Folder structure looks as follows:
The website doesn't do anything different from the pedestal tutorial, aside from using selmer to render an HTML template to create a H1 tag with "Hello, World!" or "Hello, name!". Inside the html I've included the main.js generated from clojurescript by shadow-cljs.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello, {{name}}</h1>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
My core.clj has the following route definition
(def routes
(route/expand-routes
#{["/hello" :get [coerce-body content-neg-intc respond-hello] :route-name :greet]
["/echo" :get echo]}))
(defn create-server
[]
(http/create-server
{::http/routes routes
::http/type :jetty
::http/port 8800
::http/join? false
::http/resource-path ["resources/public" "resources/public/js" "resources/public/js/cljs-runtime"]
::http/secure-headers {:content-security-policy-settings {:object-src "none"}}}))
As you can see I have added the resources folder in the resource-path.
I am able to run the shadow-cljs and clj in parallel terminals and host the server as follows:
When I look at chrome for the hosted page I get the following.
No matter what I do I can't add the public folder in resources to the html path on the client. Such that I can not load the main.js with the page. Why is that? I am a newbie with both clojure and pedestal so maybe I am missing something obvious. Please can someone help me with this problem? I am not sure how to proceed. The Pedestal documentation is not very detailed in this regard.
There are two problems with your setup:
::http/resource-path
takes a single element and not a vector.In your case, you can do the following:
add "resources"
to the :src
in your deps.edn file (the maven repo config is not necessary as maven central and clojars are always included);
use "public"
as value for the key ::http/resource-path
.
Your edn file becomes:
{:paths ["src" "resources"]
:deps {io.pedestal/pedestal.service {:mvn/version "0.5.7"}
io.pedestal/pedestal.route {:mvn/version "0.5.7"}
io.pedestal/pedestal.jetty {:mvn/version "0.5.7"}
org.slf4j/slf4j-simple {:mvn/version "1.7.28"}
org.clojure/core.async {:mvn/version "1.3.610"}
org.clojure/tools.namespace {:mvn/version "1.1.0"}
org.clojure/tools.logging {:mvn/version "1.1.0"}
org.clojure/data.json {:mvn/version "1.1.0"}
org.clojure/clojurescript {:mvn/version "1.10.758"}
thheller/shadow-cljs {:mvn/version "2.11.23"}
selmer/selmer {:mvn/version "1.12.33"}
hiccup/hiccup {:mvn/version "1.0.5"}}}
Your server config becomes:
(defn create-server
[]
(http/create-server
{::http/routes routes
::http/type :jetty
::http/port 8800
::http/join? false
::http/resource-path "public"
::http/secure-headers {:content-security-policy-settings {:object-src "none"}}}))