reagent-template icon indicating copy to clipboard operation
reagent-template copied to clipboard

Deploying to Heroku gives 'ClojureScript has not been compiled!'

Open boyentenbi opened this issue 8 years ago • 7 comments

I've created an app using this template (great stuff btw) and am now trying to deploy using Heroku as per the README instructions.

In the project directory I run

lein do clean, uberjar
git init
git add .
git commit -m "init"
heroku create
git push heroku master

After the last command, the remote deploys the app and verifies it. One of the messages during deployment is: Compiling "target/cljsbuild/public/js/app.js" from ["src/cljs" "src/cljc" "env/prod/cljs"] which seems to be correct.

However, the app gives the message 'ClojureScript has not been compiled!' which I am familiar with from local development. Locally this just means I haven't run lein figwheel yet, but I'm not sure what I ought to do since this is the deployed version.

Any help is appreciated, cheers!

boyentenbi avatar Aug 23 '16 16:08 boyentenbi

Looking in the console log, I see the following error:

Uncaught TypeError: (intermediate value)(intermediate value)(intermediate value).qg is not a function

It's usually an indication that some external Js function got munged during advanced compilation. You probably just have to add externs for any Js libraries you're using.

yogthos avatar Aug 23 '16 22:08 yogthos

Just to give more detail on what's happening. The compiler will minify the Js code it produces, so if it sees something like someFunction, then it will create a shortened name from it such as qg.

The compiler is able to track all the names it converts in ClojureScript code and core JavaScript functions. However, when you use code from a library, the compiler won't know about it. This is where externs come in. The externs tell the compiler what symbols need to be guarded against renaming, so they're not munged during compilation.

In most cases you can just supply the library as its own extern. For example, if you have your libraries under resources/public/js, then you just add them in the compiler options as follows:

{:source-paths ["src/cljs"]
     :compiler
                   {:output-to     "target/cljsbuild/public/js/app.js"
                    :output-dir    "target/uberjar"
                    :externs       ["react/externs/react.js"]
                                   ["public/js/mylib.js"] ;; <-- your js library
                    :optimizations :advanced
                    :pretty-print  false}}

yogthos avatar Aug 24 '16 13:08 yogthos

This "reloading" seems to still occur for me when deployed to heroku despite adding all my javascript files. (By the way, is each extern it's own vector? Seems un-clojurelike to me. Would have expected a single vector with all strings / filenames as elements)

Could this be because I'm including javascript from a web resource (via Reagent)

 (include-js "https://code.jquery.com/jquery-2.2.3.min.js")

ekhall avatar Jan 24 '17 03:01 ekhall

Sorry, the externs is a typo. It should be a single vector:

["react/externs/react.js"
 "public/js/mylib.js"]

You would need the resources to be available on the classpath/filesystem during the compilation step. So, if you're including the resource from a CDN, you would need a local copy to compile the externs.

yogthos avatar Jan 24 '17 03:01 yogthos

You're a rockstar @yogthos - thank you. I'm still getting the "compiling" thing on heroku with the reagent lein template and all local js and things setup as above but I'll keep digging.

Ps - whatever's minimizing jquery (Google Closure?) gives a mess of errors when optimizing jquery :)

ekhall avatar Jan 25 '17 02:01 ekhall

Sorry to hear you're still having problems. One more thing to look at might be cljsjs repository. If the libraries you're using are packaged there, then they will have externs packaged with them. There's also more externs info on here.

The compiler shouldn't be doing anything to jQuery itself. What happens when externs are generated is that it tries to infer the function signatures from the library. That can give a lot of warnings. You can suppress these by adding the following to your cljsbuild:

:closure-warnings {:externs-validation :off}

yogthos avatar Jan 25 '17 05:01 yogthos

@ekhall @yogthos So what status this issues have? Have you resolved it?

alehatsman avatar Apr 26 '17 06:04 alehatsman