Fork me on GitHub
#shadow-cljs
<
2022-03-14
>
murtaza5211:03:38

I have a cljs project (`first project`) with the following shadow-cljs.edn -

{:source-paths
 ["src"]

 :dependencies
 [[re-frame "1.3.0-rc3"]
  [com.degel/iron "0.4.0"]]

 :builds
 {:library
  {:target :node-library
   :output-to "out/re_frame_firebase.js"
   :exports {:initializeApp com.degel.re-frame-firebase.core/initialize-app}}}}
This project is imported as an npm dependency in another project's (`second project`) package.json. On npm install the first project's npm module gets installed successfully. When I run the second project with shadow-cljs watch app this is the error I get -
[:app] Build failure:
The required JS dependency "re-frame-firebase/out" is not available, it was required by "app/fb/init.cljs".
I have checked the the npm_modules of the second project -
$ ls node_modules/re-frame-firebase/out
re_frame_firebase.js
Why cant the second project find the above dependency, what am I doing wrong ?

wombawomba13:03:55

How can I call a function in a dynamically loaded module? Edit: nevermind; resolve did the trick

thheller13:03:27

@murtaza52 you absolutely should not be including a compiled CLJS build in another CLJS build. just include the sources directly instead

thheller13:03:42

@wombawomba how are you loading the module? avoid resolve if you can, it is not ideal.

wombawomba14:03:09

@thheller I'm using shadow.loader/load

wombawomba14:03:23

shadow.lazy looks really useful — thanks!

wombawomba14:03:28

you should include it in the user's guide

thheller14:03:56

lazy-component helper based on shadow.lazy

thheller14:03:03

(if you are using react)

murtaza5214:03:20

@thheller this is a third party library (`re-frame-firebase`), that we are using in a project. We had to fork it make changes to it. (we converted it to a shadow-cljs project) Now I am having trouble using it in my project ? As you suggested include the sources, you mean just copy all the sources in the project, or is there a better way ? (bcoz that will defeat the purpose behind having libraries)

thheller14:03:30

you can package it as your own library

thheller14:03:35

or include it from a local directory

thheller14:03:44

or use deps.edn and use a git dependency

thheller14:03:46

many options, dunno what exactly you need but I including a compiled version is definitely the last thing you should be doing

thheller14:03:31

if the changes you made are only done for your second project it is fine to include the sources directly too. no point in writing libraries with exactly one consumer 😉

murtaza5214:03:11

@thheller thanks that is what we were trying to do - include it from a local directory

murtaza5214:03:12

this is the dep entry in package.json for the second project "re-frame-firebase": "file:../re-frame-firebase",

murtaza5214:03:42

and npm install includes the compiled version along with sources under the node_modules

thheller14:03:44

no, that is not what you are doing. I mean yes, but you are trying to include the wrong thing

thheller14:03:27

CLJS libraries are never compiled, they are included from source only

thheller14:03:40

so you should do the same. include the source

thheller14:03:04

you can do so via shadow-cljs.edn by adding :source-paths ["src" "../that-library/src"]

wombawomba14:03:23

@thheller thanks for that blog post. It's pretty much exactly what I was trying to build :)

👍 1
thheller14:03:45

or publishing that modified lib to clojars (pretty easy if it is already using leiningen)

thheller14:03:57

and then just adding it as a regular dependency

murtaza5214:03:03

aah so I should never use it via package.json through npmjs . But why at the end its a regular js file, how does it matter if I distribute it via clojars (jar) or npmjs (node module) ?

thheller14:03:58

the compiled version will include its own version of firebase, reframe, cljs.core and whatever else it is using. it will not be compatible with the one you are using in your project.

murtaza5214:03:52

ok thanks. so If I do a lein install on the re-frame-firbase (first project), the jar will just include the sources, and then the shadow-cljs in the second-project will compile it to js ?

murtaza5214:03:54

great, thanks, let me try it out

djanus17:03:53

heya! is there a way to write a macro that will expand to a (def ^:export ...) ?

djanus17:03:30

I’ve tried this:

(defmacro defoo [name]
  `(def ^:export ~name 42))
but inspecting the output (I’m targeting :npm-module) the resulting def doesn’t appear to be exported:
(defoo bar)
compiles to
myns.bar = (42);
Object.defineProperty(module.exports, "bar", { enumerable: false, get: function() { return myns.bar; } });

djanus17:03:05

looking at the shadow-cljs code, it should be enumerable: true if the def is exported

djanus17:03:29

I’ll answer myself – this works:

(defmacro defoo [name]
  `(def ~(with-meta name {:export true}) 42))