How to create a multi-page application with Figwheel and Leiningen? - clojure

I have a simple Figwheel application which is built with Leiningen.
I want to have multiple pages in it:
index.html should use the code from hello-figwheel.core.
page2.html should use the code from hello-figwheel.page2
I assume I have to somehow modify the project.clj file:
:compiler {:main hello-figwheel.core
:asset-path "js/compiled/out"
:output-to "resources/public/js/compiled/hello_figwheel.js"
:output-dir "resources/public/js/compiled/out"
:source-map-timestamp true
;; To console.log CLJS data-structures make sure you enable devtools in Chrome
;; https://github.com/binaryage/cljs-devtools
:preloads [devtools.preload]}}
How can I tell Leiningen to compile
hello-figwheel.core to resources/public/js/compiled/hello_figwheel.js and
hello-figwheel.page2 to resources/public/js/compiled/page2.js?
There is a similar question. The difference to this one is that Leiningen is used to run Figwheel.
Update 1: I added the following to the project.clj file:
{
:id "page2"
:source-paths ["src"]
:compiler {
:output-dir "resources/public/js/compiled/page2"
:output-to "resources/public/js/compiled/page2/main.js"
:main hello-figwheel.page2
:asset-path "js/compiled/out"
:source-map-timestamp true
;; To console.log CLJS data-structures make sure you enable devtools in Chrome
;; https://github.com/binaryage/cljs-devtools
:preloads [devtools.preload]}
:figwheel {:on-jsload "hello-figwheel.page2/on-js-reload"
;; :open-urls will pop open your application
;; in the default browser once Figwheel has
;; started and compiled your application.
;; Comment this out once it no longer serves you.
:open-urls ["http://localhost:3449/page2.html"]}
}
When I run lein figwheel, the REPL is unable to connect to my web application:
It says Prompt will show when Figwheel connects to your application, but it never happens.
Also, if I open http://localhost:3449/page2.html in the browser, update page2.cljs, and refresh the page in the browser, the changes are not visible there.

Related

Cannot get REPL prompt with figwheel-main and Clojure Tools

My goal is to have a ClojureScript REPL (targeting Node.js) using Figwheel and Clojure Tools (not Leiningen). But when I launch Figwheel it seems to start correctly but never completes.
deps.edn
{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
org.clojure/clojurescript {:mvn/version "1.11.60"}}
:aliases {:fig {:extra-deps {com.bhauman/figwheel-main {:mvn/version "0.2.18"}}}}
:paths ["src" "target" "resources"]}
dev.cljs.edn
{:main cljs-example.foo
:target :nodejs
:optimizations :none
:pretty-print true
:source-map true
:asset-path "js/dev"
:output-to "resources/public/js/dev.js"
:output-dir "resources/public/js/dev"}
Launch command
clj -M:fig -m figwheel.main -b dev -r
% clj -M:fig -m figwheel.main -b dev -r
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
[Figwheel] Compiling build dev to "resources/public/js/dev.js"
[Figwheel] Successfully compiled build dev to "resources/public/js/dev.js" in 0.708 seconds.
[Figwheel] Watching paths: ("src") to compile build - dev
[Figwheel] Starting Server at http://localhost:9500
[Figwheel] Starting REPL
Prompt will show when REPL connects to evaluation environment (i.e. Node)
Figwheel Main Controls:
(figwheel.main/stop-builds id ...) ;; stops Figwheel autobuilder for ids
(figwheel.main/start-builds id ...) ;; starts autobuilder focused on ids
(figwheel.main/reset) ;; stops, cleans, reloads config, and starts autobuilder
(figwheel.main/build-once id ...) ;; builds source one time
(figwheel.main/clean id ...) ;; deletes compiled cljs target files
(figwheel.main/status) ;; displays current state of system
Figwheel REPL Controls:
(figwheel.repl/conns) ;; displays the current connections
(figwheel.repl/focus session-name) ;; choose which session name to focus on
In the cljs.user ns, controls can be called without ns ie. (conns) instead of (figwheel.repl/conns)
Docs: (doc function-name-here)
Exit: :cljs/quit
Results: Stored in vars *1, *2, *3, *e holds last exception object
Starting node ...
Node output being logged to: resources/public/js/dev/node.log
For a better development experience:
1. Open chrome://inspect/#devices ... (in Chrome)
2. Click "Open dedicated DevTools for Node"
And that's it! :(
It stays like that forever and I never get a prompt such as:
cljs.user=>
Addendum
I don't think my foo.cljs file has an error that would cause Figwheel to hang. When I launch a "native" REPL with:
clj -M -m cljs.main --target node --compile cljs-example.foo --repl
Then I get:
ClojureScript 1.11.60
cljs.user=> (require '[cljs-example.foo])
i am foo!!!!!!!!
nil
cljs.user=>

How to handle the new HTTP configuration for shadow-cljs?

I have been using Clojure, ClojureScript, lein, shadow-cljs, Emacs,
and CIDER to work on a Clojure/ClojureScript dynamic web app project.
Usually, I build the project by executing the command
cider-jack-in-cljs in Emacs, choosing shadow-cljs, then shadow
for REPL type, and, finally, app for the building option.
Things were working fine. I was used to watching changes on the UI on
localhost:3005.
But, an answer from a previous question indicated that the
project was using an old (and deprecated) HTTP configuration for
shadow-cljs.
On shadow-cljs.edn we had:
{:source-paths ["src" "dev"]
:dependencies ...omitted..
:nrepl {:port 8230
:nrepl-middleware [dirac.nrepl/middleware]}
:builds {:app {
:devtools {:after-load app.core/main
:http-root "public"
:http-port 3005
:preloads [shadow.cljs.devtools.client.hud
day8.re-frame-10x.preload
dirac.runtime.preload
devtools.preload]}
}}}}}
After the build was complete, I would see the live application on
localhost:3005. The mini-buffer would direct me to see the
rendered page on the browser.
On shadow-cljs.edn, now, we have:
{:source-paths ["src" "dev"]
:dependencies ...omitted..
:nrepl {:port 8230
:nrepl-middleware [dirac.nrepl/middleware]}
:builds {:app {
:devtools {:after-load app.core/main
:preloads [shadow.cljs.devtools.client.hud
day8.re-frame-10x.preload
dirac.runtime.preload
devtools.preload]}
:dev-http {3005 "public"}
}}}}}
However, the workflow for development is different.
Emacs mini-buffer redirects me on the browser to a different address:
http://localhost:9630/dashboard
Also, old localhost:3005 does not work, even though it is mentioned
on :dev-http {3005 "public"}.
1 - What is the new workflow to change the code and see the changes?
2 - Why is port localhost:3005 not working anymore even though it is mentioned in the source code?
3 - What is the purpose of the dashboard?
:dev-http is a top-level config. It is not part of a build config. It needs to sit at the same level as :nrepl and :builds.
{:source-paths ["src" "dev"]
:dependencies ...omitted..
:nrepl {:port 8230
:nrepl-middleware [dirac.nrepl/middleware]}
:dev-http {3005 "public"}
:builds
{:app
{...
:devtools
{:after-load app.core/main
:preloads
[day8.re-frame-10x.preload
dirac.runtime.preload
devtools.preload]}}}}}}

How to do a release/deploy build of a clojurescript app?

I'm ready to release my clojurescript app. Currently i do lein ring uberjar to create my jar, which does build cljs, but i dont see any documentation on how to do a release build-- do i need to do any concat-ing/minifying/bla bla bla? Are there special release options?
Here is my cljsbuild setup in my project.clj->
{
:builds [{:id "dev"
:source-paths ["src/analyticsjs"]
:figwheel false
:clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]
:compiler {:main "analyticsjs.core"
:asset-path "/js"
:output-to "resources/public/js/cljs.js"
:output-dir "resources/public/js"}}
]
}
All help is appreciated. Thanks!
I was directed in the clojurians slack channel to add :optimizations :advanced inside my :compiler map, which worked.

figwheel build can't find my core cljs namespace

I'm trying to use figwheel build for my project. I use the latest versions of libs and my leiningen version is 2.5.1. My build file looks like this:
(defproject figwheel-issue "1.2.3"
:plugins [[lein-cljsbuild "1.0.6"]
[lein-figwheel "0.3.3"]]
:dependencies [[org.clojure/clojurescript "0.0-3269"]
[org.clojure/clojure "1.7.0-beta3"]]
:cljsbuild {
:builds [{ :id "dev"
:source-paths ["src"]
:figwheel true
:compiler {
:main myproject/core
:hashbang false
:asset-path "js/out"
:output-to "resources/public/js/example.js"
:output-dir "resources/public/js/out"
:optimizations :none}}]})
Normal build works ok. So when I run:
lein cljsbuild once
I get:
Successfully compiled "resources/public/js/example.js" in 0.873 seconds.
But when I try to run:
lein figwheel
Figwheel build can't seem to find my core namespace:
Compiling "resources/public/js/example.js" failed.
clojure.lang.ExceptionInfo: failed compiling file:target/figwheel_temp/dev/figwheel/connect.cljs
at clojure.core$ex_info.invoke (core.clj:4591)
Caused by: clojure.lang.ExceptionInfo: No such namespace: core, could not locate core.cljs, core.cljc, or Closure namespace "core" at line 1 target/figwheel_temp/dev/figwheel/connect.cljs
at clojure.core$ex_info.invoke (core.clj:4591)
Any ideas what could be wrong? I created a minimal github project which demonstrates the issue here:
https://github.com/auramo/figwheel-build-issue
Problem was the namespace, it should be:
:main myproject.core

Clojure Ring: How to determine if development server is running?

I have a project containing both Clojure & ClojureScript code. I would like to include unoptimized ClojureScript when I run my server via lein ring server and optimized ClojureScript otherwise. What is the idiomatic way to do this?
I am using:
[[bidi "1.19.0"]
[hiccup "1.0.5"]
[org.clojure/clojure "1.7.0-beta3"]
[org.clojure/clojurescript "0.0-3269"]]
[[lein-cljsbuild "1.0.4"]
[lein-ring "0.9.4"]]
My handler is just a simple one:
(def app (-> ["/" {:get {"" index-view}}]
(compile-route)
(make-handler)))
and this is my server directive:
:ring {:handler webapp.core/app}
I am looking for a way to be able to do this in my views:
(dev-server? request) ;; => true if it's a development server, otherwise false.
The idiomatic way to do this is to use leiningen profiles, using the :dev profile. You can then ensure inside the dev profile that your ClojureScript build is happening without optimization, cf. the leiningen cljsbuild compilation profiles.
If you want to be able to identify the devserver running, you can use environ -- include :env {:dev true} in your :dev profile and then in your code you can just call (env :dev). You might want to take a look at the reagent-template for inspiration.