bhauman / lein-figwheel

Figwheel builds your ClojureScript code and hot loads it into the browser as you are coding!
Eclipse Public License 1.0
2.88k stars 210 forks source link

figwheel doesn't generate correct cljs_deps.js when :npm-deps is present in project.clj #701

Closed retrogradeorbit closed 6 years ago

retrogradeorbit commented 6 years ago

I have been encountering errors such as:

    at visitNode (base.js:1357)
    at visitNode (base.js:1355)
    at visitNode (base.js:1355)
    at visitNode (base.js:1355)
    at Object.goog.writeScripts_ (base.js:1369)
    at Object.goog.require (base.js:706)
    at (index):73

when using figwheel to build a project that includes an :npm-dep setting.

I believe other people may have been hitting this issue and adding their comments to #576

You can leave figwheel running, then in another terminal do a lein clean; lein cljsbuild once and then when complete, reload your app and it now works. It continues to work until you save a file that :require's a dep that is an npm-dep. As soon as you save this file you break the deps, the application stops loading and the error returns.

Digging in I found that what is happening is the cljs_deps.js file, when built with figwheel is missing a line that is there when build with cljsbuild.

Heres an excerpt from my cljs_deps.js under cljsbuild:

goog.addDependency("../cljs_time/coerce.js", ['cljs_time.coerce'], ['goog.date.UtcDateTime', 'cljs.core', 'cljs_time.core', 'cljs_time.format']);
goog.addDependency("../cljs_time/local.js", ['cljs_time.local'], ['cljs.core', 'cljs_time.core', 'cljs_time.coerce', 'cljs_time.format', 'goog.date.DateTime']);
goog.addDependency("../myproject/ws/utils.js", ['myproject.ws.utils'], ['cljs.core']);
goog.addDependency("../node_modules/lz-string/libs/lz-string.js", ['module$home$crispin$dev$clojure$myproject$node_modules$lz_string$libs$lz_string'], []);
goog.addDependency("../cljsjs/react/development/react.inc.js", ['cljsjs.react'], []);
goog.addDependency("../cljsjs/create-react-class/development/create-react-class.inc.js", ['cljsjs.create_react_class'], ['cljsjs.react']);

And here is the same section of the file constructed by figwheel:

goog.addDependency("../cljs_time/coerce.js", ['cljs_time.coerce'], ['goog.date.UtcDateTime', 'cljs.core', 'cljs_time.core', 'cljs_time.format']);
goog.addDependency("../cljs_time/local.js", ['cljs_time.local'], ['cljs.core', 'cljs_time.core', 'cljs_time.coerce', 'cljs_time.format', 'goog.date.DateTime']);
goog.addDependency("../myproject/ws/utils.js", ['myproject.ws.utils'], ['cljs.core']);
goog.addDependency("../cljsjs/react/development/react.inc.js", ['cljsjs.react'], []);
goog.addDependency("../cljsjs/create-react-class/development/create-react-class.inc.js", ['cljsjs.create_react_class'], ['cljsjs.react']);

note the missing goog.addDependency() call registering the dependencies for "../node_modules/lz-string/libs/lz-string.js".

If this dependency is not registered, when it comes time to walk the dependency tree for a (ns some-module (:require [lz-string])) it blows up with the error at the top.

I started digging further into the rabithole, and I can see where figwheel sourcecode generates the deps file, but I went looking in the clojurescript source for where cljsbuild generates the deps file and got totally lost.

Do you have any pointers here that could help me get figwheel's cljs_dep builder working with npm-deps?

retrogradeorbit commented 6 years ago

Sorry. Digging further I see you are reading in cljs_deps.js not writing it. I'm going to try and find out why the deps file is missing node modules under figwheel. It seems all the npm magic occurs here: https://github.com/clojure/clojurescript/blob/6950aff480174a25a77c2308aa87a099a774a6e8/src/main/clojure/cljs/closure.clj

retrogradeorbit commented 6 years ago

Ok. This doesn't seem to be a figwheel issue, but an issue with execution environments. Perhaps even related to the running of node during the build.

I have been getting the issue as I switch between running figwheel inside emacs (cider-jack-in-clojurescript), and then running a build from the command line.

If I stop figwheel in one environment, I then have to lein clean, and then restart figwheel in the new environment from scratch for it to work. If I don't lein clean or dont restart figwheel, the error arises. Although I haven't fully discovered the root cause, the underlying cljsbuild does a lot of javascript file manipulation and executing of node commands with regards to special node packages ('cljs-oss/module-deps' that it installs). When the execution environment changes, it seems something happens that causes cljsbuild to ignore the npm-deps when it builds its cljs_deps.js, and a broken build emerges.

So in summary I found that lein clean alone is not enough to get the build working. But to shut down the running figwheel (say in the terminal), lein clean, and then start up the new running figwheel (say inside cider).