magnars / optimus

A Ring middleware for frontend performance optimization.
364 stars 23 forks source link

optimus.assets/load-bundle can't find file in uberjar #40

Closed sodiumjoe closed 9 years ago

sodiumjoe commented 9 years ago

At dev time with lein ring server, this works fine:

(ns app.assets
  (:require [optimus.assets :as assets]))

(defn get-assets []
  (concat
    (assets/load-bundle "." "main.js" ["/js/main.js"])))

But after

$ lein uberjar
Compiling app.assets
Created app/target/uberjar+uberjar/app-0.1.0-SNAPSHOT.jar
Created app/target/uberjar/app-0.1.0-SNAPSHOT-standalone.jar
$ java -jar target/uberjar/app-0.1.0-SNAPSHOT-standalone.jar

At runtime, I get this exception:

java.io.FileNotFoundException: /js/main.js
        at optimus.assets.creation$existing_resource.invoke(creation.clj:25)
        at optimus.assets.creation$load_text_asset.invoke(creation.clj:60)
        at optimus.assets$fn__185.invoke(assets.clj:5)
        at clojure.lang.MultiFn.invoke(MultiFn.java:231)
        at optimus.assets.creation$load_asset_and_refs.invoke(creation.clj:71)
        at optimus.assets.creation$load_assets$fn__149.invoke(creation.clj:99)

The file is in resources:

$ ls resources/js
main.js

And the file does appear to be in the root of the jar:

$ jar tf target/uberjar/app-0.1.0-SNAPSHOT-standalone.jar | grep 'js\/main\.js'
js/main.js

What am I missing?

magnars commented 9 years ago

I'm guessing the "." public directory is messing it up. The uberjar isn't a file system. Moving your assets into resources/public should solve it.

sodiumjoe commented 9 years ago

Thanks! That appears to have been the issue.

So, my use-case here is that instead of using optimus in a canonical way at runtime, I'm compiling assets statically once. It's still at runtime, but just once at startup. This is why I had the source files in resources instead of resources/public. For this workaround, I've moved the source files to resources/public/src, but this doesn't seem very clean. Is there a more idiomatic way to do what I'm trying to do?

Should the behavior with the "." public directory be considered a bug?

I'm thinking I should figure out how to do this asset compilation at compile time instead of runtime, but it seems like I would still run into this problem.

Thanks for building a great library and I appreciate any help.

magnars commented 9 years ago

Compiling assets once at startup is canonical for a production environment, using the serve-frozen-assets strategy. What is it you are trying to accomplish?

sodiumjoe commented 9 years ago

Well, I want to compile static assets to files and then just serve them from nginx instead of hitting the java application.

magnars commented 9 years ago

Ah yes. I do something similar with varnish. Can you abide one request to the Java app? http://nginx.com/resources/admin-guide/caching/ søn. 28. jun. 2015 kl. 23.37 skrev Joe Moon notifications@github.com:

Well, I want to compile static assets to files and then just serve them from nginx instead of hitting the java application.

— Reply to this email directly or view it on GitHub https://github.com/magnars/optimus/issues/40#issuecomment-116344932.

sodiumjoe commented 9 years ago

Unfortunately can't afford $1500/year for my personal projects, but I might look into setting up varnish. For now, the public/src workaround will be ok. Thanks for your help!

magnars commented 9 years ago

Ahh, doh. Didn't know that was a paid feature. Varnish is pretty great tho.

You could also compile "resources/src" into "resources/target" or some such.

sodiumjoe commented 9 years ago

Ah, yes, that's a great idea, I should've thought of that!

magnars commented 9 years ago

Glad to be of help! man. 29. jun. 2015 kl. 08.57 skrev Joe Moon notifications@github.com:

Ah, yes, that's a great idea, I should've thought of that!

— Reply to this email directly or view it on GitHub https://github.com/magnars/optimus/issues/40#issuecomment-116484808.