Migrating assests from a subfolder to a JAR

For some reasons (mostly reuse and clean versionning), we need to move some of our assets code (CSS, handlebars templates, and some cross-projects cljs-based React.js components) from being simply a subfolder referenced as a :resource-paths as standalone project.

What would be the good strategy to do the migration ? A collegue already managed to do the packaging as a standalone JAR, now we need to use what’s in this JAR in our project. We already deployed the JAR in our internal repository, so the “include-it-in-your-dependencies” part is already done.

I’m really a noob when it comes to JAR/JVM stuff, classpath, sources-paths, resources-paths etc. (coming from npm where this problem doesn’t exist doesn’t help).

We’re using Boot, if that helps.

Help mucho appreciated.

Hey Khalid, good question!

So when you depend on jars all their “entries” (~files) are available on the classpath. If you depend on a jar that contains an entry djebbz/app/main.css you can access that file using

(clojure.java.io/resource "djebbz/app/main.css")

Something to watch out for here is that there may be “conflicts” meaning that in theory multiple jars might contain an entry with the same path. There are still ways to get references to those files but it becomes a bit more complex and is usually something you want to avoid if possible.
The easy way to solve this is properly nesting files in Java-style package directories which you “own”. E.g. com/yourcompany/project/....

When you package Clojure or ClojureScript code it is also important to make sure that the path to the file corresponds to the namespace. E.g. a jar entry com/yourcompany/project/app.cljs should contain the namespace com.yourcompany.project.app. If I’m not mistaken this how the respective compiler finds sources for namespaces.

Now you should be good with the Clojurescript stuff and know how you can get a handle on other files inside your jar.

What’s left is probably serving those files with ring or similar. Since CLJSJS also packages some non-JS Assets there is some help for that in the CLJSJS wiki.

Fundamentally your options are:

  1. Write some ring middleware or similar that looks up files from your jar and returns them (see ring-cljsjs)
  2. Import the files into a directory where your existing HTTP server will serve them (done at build time).

What you will want to do depends on the overall motivation for introducing this kind of split.
I would also be curious to hear more about that.

Hope this helps!

3 Likes

Thanks a lot for this valuable answer!
I’ll look more closely normally next week and get back to you here.