5

My project.clj has,

  :cljsbuild {:builds
              {:app
               {:source-paths ["src/cljs" "src/cljc"]
                :compiler {:output-to "target/cljsbuild/public/js/app.js"
                           :output-dir "target/cljsbuild/public/js/out"
                           :main "my.core"
                           :asset-path "/js/out"
                           :optimizations :none
                           :source-map true
                           :pretty-print true}}}}

and I include app.js in my list.html, using Selmer, like so,

{% block page-scripts %}
{% script "/js/app.js" %}
{% endblock %}

at the end of my list.cljs, I have

(r/render [list] (.getElementById js/document "content"))

so far so good.

Now, I would like to have another page, say detail.cljs, that I also like to render similarly,

(r/render [detail] (.getElementById js/document "content"))

The problem is, I just have a single app.js and including that in detail.html will render list content there too. Btw, I want one url for list page, and another for detail.

Question:

How should I go about it?

Adeel Ansari
  • 39,541
  • 12
  • 93
  • 133

2 Answers2

3

Using shadow-cljs, you can specify several modules with different init-fns in your build spec.

Your shadow-cljs.edn could contain something like this:

{:builds {:client {:target "browser"
                   :modules {:some-page {:init-fn org.example.foo/run}
                             :another-page {:init-fn org.example.bar/run
                                            :depends-on #{:some-page}}}}}}

The names of the .js files are determined from the module name, here some-page.js and another-page.js.

Svante
  • 50,694
  • 11
  • 78
  • 122
  • 3
    Ideally you would have a `:shared` module that both pages depend on. That way each page only gets exactly what is needed. If you make one page depend on another like the example then both `:init-fn` calls will execute when visiting `:another-page`. – Thomas Heller Feb 19 '20 at 09:56
2

ClojureScript development for the past 2 years is much easier to do using the Deps/CLI facility along with Figwheel Main (a.k.a Figwheel 2.0) rather than the older Leiningen method. Just look at the page Create a Build at figwheel.org, and then create multiple *.cljs.edn files such as:

some-page.cljs.edn
another-page.cljs.edn
...

Each of these can be as simple as:

{:main some-page.core}

and compile via:

clojure -m figwheel.main --build-once some-page

which will produce an output file

target/public/cljs-out/some-page-main.js

Be sure to see Code Splitting documentation for Figwheel, and Code Splitting on clojurescript.org. Of course, be sure to go through all of the Tutorial and Documentation from the start. Enjoy!

For shadow-cljs, there is Code Splitting ClojureScript example app and a blog entry.


Note: You could also look at the Extra Mains feature, but this is more limited.

Adeel Ansari
  • 39,541
  • 12
  • 93
  • 133
Alan Thompson
  • 29,276
  • 6
  • 41
  • 48
  • 1
    If you make 2 completely independent builds the user will have to download all code again for each page. If the user is likely to visit many pages then it is much better to split the code using `:modules` and re-using the shared/cached code as that can substantially reduce the download size. – Thomas Heller Feb 19 '20 at 09:54