6
votes

So, I took my large Clojure project and split it into two.

I compiled the core part and made an Uberjar.

Then typed :

lein deploy clojars

to make that jar public, and then added it as a dependency in the project.clj file for my application.

This code is written in cljx so it can compile to javascript.

What are the equivalent steps I need to make my two cljx codebases into two separate javascript libraries, without having the whole ClojureScript virtual machine repeated twice?

Update : Just to clarify a couple of things.

1) I know I can move to .cljc rather than .cljx. My only concern is that this seems pretty new and I don't know if existing users of my code are likely to have it. But I probably will make this move shortly. Answers in terms of cljc are also welcome.

2) I am already successfully compiling my code to a single monolithic main.js file. What I'm looking for is how to compile separate libraries of cljs that can be included in other cljs projects. As every time I currently compile something in cljs I get a main.js file with the entire clojurescript VM.

3) One of my motivations for coming back to this question is that I want to start using Figwheel. So I want to be able to make libraries in clojurescript that I can drop into a new clojurescript project I'm developing through Figwheel. So I imagine I'd be referencing them in this new project's project.clj file, and including them within the web-page as already compiled .js files. Am I wrong about this?

2
Would be great if you can share the project.clj from both projects. There are multiple things that can go wrong in a .cljx configuration: :output-path, :source-path, :resource-path, also how you declare the dependency (using :aot could be a problem), if you are calling cljx once before deploy clojars or not...nberger
thanks @nberger. I can, but what I'm really looking for is an overview / tutorial (or pointer to one) on how this works. So I can understand it. I'm not trying to debug my current setup. Just a basic explanation would be great.interstar
I added an answer that I think pinpoints the most important parts you should take into account, and also includes some links if you want to dig deeper.nberger
Looking to your updated question, I would say: yes, you are wrong, you don't want to include them as compiled .is files. You want the library to provide the clojurescript code as if they were resources in the class path, so they are going to be available in the cljsbuils environment of the project using the library.nberger
AFAIK you would only consume your library as .js coffee if you are going to do it from .js ( not cljs) code. In that case you would have to :export the "public" symbols so their names do not get munged among other thingsnberger

2 Answers

2
votes

It's difficult to say what's wrong or missing from your configuration without having more details about your project.clj, but I'll try to cover the most important parts where you should take a look at.

Do not use cljx. Use Reader Conditionals!

Nowadays, cljx is deprecated in favor of Reader Conditionals (cljc). If you have the chance to upgrade to clojure 1.7.0 then my suggestion is to do that and leave cljx behind: You'll avoid much of the issues from cljx because instead of using a build tool (that needs to be in sync with the rest of the build pipeline) cljc is something that the clojure compiler is aware of.

If you are still going to use cljx...

I won't repeat all the stuff covered in the excellent README from cljx but just pinpoint some relevant parts:

  1. You have to be sure cljx once is called before other tasks down in the pipeline (javac, compile, uberjar and even test or cljsbuild test). So you might want to create aliases or modify the default :prep-tasks in your project.clj. More info: see the Installation section

  2. Your cljx :output-path should be added to your cljsbuild :source-paths. See the Usage section

Last but not least:

  1. Do not declare your dependency as :classifier "aot" in your dependencies vector when using cljsbuild. Use it only if you know what you are doing. Remove it during development if you have dependency issues. This applies whether you are using cljx, cljc or just plain cljs.

  2. Take a look to other projects cljx configurations. For example: Prismatic/schema and the "Switch to reader conditionals" commit in Sablono