This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-12
Channels
- # beginners (102)
- # boot (5)
- # cider (1)
- # cljs-dev (15)
- # cljsjs (1)
- # cljsrn (20)
- # clojure (104)
- # clojure-austin (1)
- # clojure-europe (8)
- # clojure-italy (39)
- # clojure-nl (17)
- # clojure-spec (38)
- # clojure-uk (23)
- # clojurescript (34)
- # cursive (31)
- # data-science (5)
- # datomic (3)
- # emacs (28)
- # joker (1)
- # kaocha (5)
- # klipse (1)
- # leiningen (1)
- # off-topic (66)
- # quil (4)
- # reagent (35)
- # ring-swagger (1)
- # rum (1)
- # shadow-cljs (121)
- # test-check (1)
- # tools-deps (33)
- # uncomplicate (2)
- # vim (15)
- # yada (1)
Is there a way to declare NPM dependencies in libraries so that those deps will be included in dependant projects that depend on those libraries ? i.e. how to declare transitive NPM deps without having to duplicate it in every dependent project ?
@superstructor you can include a deps.cljs
with {:npm-deps {"foo" "version"}}
in your .jar
Ok thanks, but that will just issue a warning not actually provide the deps ? Is there a good way to also provide transitive deps ? @thheller
shadow-cljs will run an npm install
on the packages listed in deps.cljs
on startup? (if they aren't already in package.json
)
Is that behaviour any different between using the Node.js shadow-cljs
CLI and running via lein with lein run -m shadow.cljs.devtools.cli
and :lein true
?
which warning are you refering to? makes things easier if I know what you are talking about 😛
Ah I see it is the difference between :npm-deps
and :foreign-libs
? For example
The required namespace "react" is not available, it was required by "day8/re_frame_10x/inlined_deps/reagent/v0v8v0/reagent/core.cljs".
The namespace was provided via :foreign-libs which is not supported.
Please refer to for more information.
You may just need to run:
npm install react
Ok I think that is clearer now. So that is for libs, but for apps themselves you still need to have your own mechanism for npm deps like package.json
?
Ok awesome, that is clear. Thank you! 😄
In the user guide there is only one mention of :npm-deps
. May I ask where the source is and if you accept pull requests on docs ? I also wanted to add :external-config
to the compiler options which is missing.
Not sure. :compiler-options { :external-config {:devtools/config {:features-to-install [:formatters :hints]}}}
does work for cljs devtools.
My bad, you are correct. After looking it up I see it does (get-in @cljs.env/*compiler* [:options :external-config :devtools/config])
. :thumbsup:
it is only under the :external-config
key because of figwheel which had "strict" validation of the compiler-options map
I see. Thanks I wasn't aware of that history.
One more question re earlier :npm-deps
/ :foreign-libs
. For something like re-frame that needs to maintain compatibility with multiple build systems would it be recommended to simply declare both ?
just using cljsjs/react
etc works but is helped by including a deps.cljs with :npm-deps
I can't see one in reagent or re-frame. react itself is probably a reagent PR to be more accurate. That explains how things should be going forward so it is clear, thank you! 🙂
Are you familiar with the lein-shadow
plugin @thheller?
In my opinion, the implementation has too much coupling of different tasks/concepts, but regardless my follow up question is:
Currently it gets :npm-deps
out of project.clj
. Might it make more sense from a design perspective for such a plugin to get that out of deps.cljs
directly ?
Because then 1. apps and libs using lein could both declare npm-deps in the same way; and 2. when working directly in a libs repo, there would otherwise be duplication of deps between project.clj
and deps.cljs
.
Yep it generates package.json
from :npm-deps
key in project.clj
. A bit of a hack, but it works.
so you NEED to hold onto your package.json
AND the lockfiles (eg. package-lock.json
) if you want anything remotely reliable
Re your comment libs should use deps.cljs
- If you are working directly in a libs project (in this case, it behaves like an 'app') you would need to duplicate deps between both package.json
and deps.cljs
?
this is NOT maven where you can somewhat rely on dependencies not chaning unless you change them
Yep, correct. But if you choose to serialise package.json
as deps.cljs
; i.e. it is repeatable. Then it is OK ?
Ok, so I guess that answers my question. That if you want to do that manual step automatically (ala lein-sahdow
) :npm-deps
should be taken from a deps.cljs
not from project.clj
.
problem with taking it from deps.cljs
is that you need to run a JVM with the full classpath to get them
I think that apps should maintain a package.json
. period. don't outsource it to anything else.
libraries with deps.cljs
is problematic but works ok-ish until you run into version conflicts
Thanks. That's a good summary of the issues.
I think the distinction between apps and libs becomes less interesting once your a lib developer, because then you run the lib as an 'app' (i.e. not a transitive dep) and you end up maintaining a package.json there too.
So you end up duplicating deps in 2 files at every layer of your dependency tree, which does suck.
Not only duplicating between files, but duplicating between dependent projects.
as a lib developer you'll need to be much more careful with you declared dependencies anyways
Would it be worth considering shadow-cljs being responsible for managing/generation of package.json
based on deps.cljs
as a standard or is that a space you don't want to go ?
I'm pretty close to completely replacing npm and just downloading and managing dependencies manually
that is: read all found deps.cljs
with :npm-deps
on startup, do a best effort conflict resolution, run npm install the-package@version
if the package is not in package.json
already
Ok thanks, it is clear what the current extent of responsibility is :thumbsup: Yeah, if you choose to replace npm completely that would obviously avoid the mess and solve the issue, but npm does a lot of stuff. Its questionable how much of that CLJS users would actually need though for shadow-cljs to be viable.
As-in, if shadow-cljs did ever download/manage deps directly itself, I'm not sure it would actually need to cover 100% of npm's feature set related to that.
But yeah, I get its also a big scope increase, best avoided if possible.
the reason I haven't done that already is because it would only be practical for browser builds
as that is the only thing that doesn't actually need the node_modules
folder structure
but most things do actually need that stuff (eg. node, react-native) so if we were to manage dependencies we'd have another system to worry about deps
Yeah that would be a formidable maintenance burden.
my recommendation if you want to avoid the npm horrors as best you can: use package.json, managed via npm install
etc. and keep the lock files in version control
so there is no guarantee that 2 people running npm install the-thing
will end up with the same dependencies
Yep, that's burned me before.
Yep, software is hard.
Thanks again for all the insights. Much appreciated. If I think up any possibly reasonable solutions to this I'll definitely ping you.
Absolutely, its a tough position to be in. Overall, I want to say despite that shadow-cljs is amazing work and a huge leap forward in CLJS development. Its a good problem to have! It wasn't long ago that every time I needed a new JS dep it required a PR to CLJSJS!
too many times were I try to upgrade one tiny dep with a minor version bump and everything breaks 😛
Yeah, its a blessing and a curse. Unfortunately its non-trivial to replace all the JS things with CLJS things.
The set of functionality available in JS is always going to be greater than CLJS, so interop is a key part of CLJS's strength just like Clojure and the JVM w/ Java libs.
but there are still a bunch of widely used npm packages that aren't very high quality
JS world is also still rapidly changing so I guess its something we have to live with for a while
to be fair to JS though they need to solve things that JVM mostly doesn't care about
Yep. Its nice to be insulated mostly from that churn by abstractions in the CLJS world, but the interaction at the interop/deps layer is going to be a pain point for awhile.
It'll be interesting to see how things play out. Looks like JS is becoming very much a compile target, esp with asm.js, TypeScript etc.
So a selling feature of CLJS would also be reliability of dependencies?
I started a PR on reagent to add deps.cljs
as per above - https://github.com/reagent-project/reagent/pull/441 @thheller