-
Notifications
You must be signed in to change notification settings - Fork 85
Explore CLJS require
from node_modules
#130
Comments
Oh, this would be awesome, together with |
This one is a little tough because (the way I see it) it will have to rely on convention. We can easily support requiring CLJS namespaces from a
IMO, we could easily solve 1. and 2. by piggybacking on the Node.js convention of placing that information in the package's |
Totally agree with your analysis and definitely agree with storing info in |
NPM standardizes a Here's a suggestion: {
"name": "my-package",
"directories": {
"lib": "src",
"cache": "./lumo-cache"
}
} Lumo could then simply add |
Sounds sensible to me |
First step towards this done in 3cddd1d. Future enhancements are:
|
👍 |
I am trying this out, one thing I have noticed in my debugging is that (of course) other libraries are using the
So I was kind of wondering if we should have our own convention...or maybe not...we could skip inspecting the above libs if so...but I don't think it makes a big difference in terms of performance. |
I tried to include a child project in my project, so it's working but it fails to require the node dependencies of the child module (I have |
Just want to add that children with dependencies that are already present in the parent work as long as the have the |
This works pretty well thanks to the approach in #302 and #300 for scoped packages 🎉 I was able to publish a ClojureScript npm package and consume it from I was wondering though one thing, should we default |
great thread here, this would be a pretty nice efficiency boost for my workflow with lumo so I'm +1 on the general idea. I've been solving this a different way by running a starting script that reads node_module deps from a file and then shell execs out to lumo with all the required classpaths passed in to the cli. I believe this is more or less how leiningen does it. Perhaps this is a case to separate some dependency loading from lumo itself so it can focus on providing a generic environment |
Lumo has experimental support for ClojureScript npm packaging now: anmonteiro/lumo#130 This means we can deploy to npm seamlessly and then require namespaces at the REPL. Macrovich is massively important for converting JVM ClojureScript to self-host ClojureScript so I think it should be the first one who gets this new approach so that it can be used as npm dependency as well.
Lumo has experimental support for ClojureScript npm packaging now: anmonteiro/lumo#130 This means we can deploy to npm seamlessly and then require namespaces at the REPL. Macrovich is massively important for converting JVM ClojureScript to self-host ClojureScript so I think it should be the first one who gets this new approach so that it can be used as npm dependency as well.
@arichiardi I think defaulting to |
At the moment we skip the read from the dependencies that don't have the |
@arichiardi I've been doing this sort of 'manually' here where for a given lumo based project, I specify cljs-via-npm deps in a For library implementors though, it seems to me that they may wish to simply provide a bootstrapped cljs compatible library via npm which has no explicit requirements on lumo. If other cljs platform tools are born, would we ask those library owners to add a |
Hello everyone. The request to be able to publish/consume CLJS packages via npm instead of clojars has come up quite a lot for The problem we need to address is the classpath issue. Fundamentally for the JVM the classpath is constructed by multiple paths that are tested in order to look for things. npm/node does not have a classpath and follows completely different rules. So as far as I see it we need a way for CLJS packages to declare the "root" paths that should be added to the classpath. Either packages can just publish sources and use their source paths or hook into the I do not like using the default "directories" property for this since JS packages may be using that and I don't want random JS packages on my classpath. So one option would be to add a Example {
"name": "something",
"clojurescript": {
"source-paths":[
"src/main"
],
"dependencies":[
["some-lib", "version", {"exclusions":["foo/bar"]}]
]
},
// ...
} I think I'd prefer a There could be other keys added for caches and stuff although I'd be very careful with this since caches might not be compatible since different compiler versions might be incompatible. One problem would be classpath ordering but I guess we could follow the same ordering the JVM does by resolving the dependencies in order. Another issue is that Thoughts? |
Hello Thomas, thanks for pitching in. One note before continuing: that I agree though that if you want to start having a full replacement of We are already doing this in One disadvantage is the split between node and JVM deps so that is why I started asking around if we could publish So this goes back to a custom I would definitely love to coordinate with you this effort. |
As I said the problem I have with using the default "directories" is that JS libs may be using it for other purposes than marking a "classpath root". Just want to avoid running into some JS lib convention I don't know about that would end up putting X files onto the classpath. I'm sort of opposed to this whole idea since it IMHO doesn't solve anything unless EVERYTHING is published to Currently we have maven-style for CLJS and they can declare JS deps via Cross package manager resolving is hard. Which artifact do you pick if lib A depends on I don't think we can solve the split issue since npm is never going to become the default. The more surface area the split gets the harder everything becomes so why make it bigger? The only argument I have heard FOR publishing to What other arguments are there? |
The other argument for Enterprise is dependency mirroring, with the split in place you need two...in general though what you say is probably the best approach...unifying is going to be hard anyways and if we start from what we have, for instance At the very least a simple |
Using @thheller I think that having a reserved directory like My vote would be to use |
disregarding the technical limitation for a second, I think locating cljs (especially for bootstrapped) deps in npm would go a long way towards welcoming js devs into the clojurescript ecosystem. Making the modules searchable in a public forum such as npm could greatly aid discover-ability and adoption. I think many folks out there don't know what they're missing :) |
Yeah, I think there's a huge value in making ClojureScript ecosystem seamlessly accessible to JavaScript developers using tools they're already familiar with. |
I'd like to chime in from the TypeScript (TS) side of the JS ecosystem. I think the example of TS is relevant because it is widely used and faces similar questions. Please forgive any ignorance in the CLJS side of things, I am still learning it. TS users have a very big incentive to ship Despite this, the golden rule in packaging TS and Angular libraries has always been "don't ship TS". Nothing really stops you from doing it. But doing it usually has bad results (more on that later). Instead, TS libraries are encouraged to also publish additional declaration files that complement the Angular libraries publish that and more. They have their own guidelines in what's called the Angular Package Format (APF). The APF seeks allow for many different consumers of npm libraries, both on the platform and on the tool level (node, browser, Webpack, Closure, Rollup, UMD, TS, Angular AOT, script tags, etc). Both TS and Angular piggyback on You might think all of this complexity stems from TS, but it is not so. Even with just JS you will need to make special allowances for your various consumers. To be fair with impending ES modules and several ES versions out in the wild already, this is a bit of a timebomb. The JS community will need to figure out both forwards and backwards multi-platform compat in All this to say that I don't think there is anything inherently wrong with piggybacking on When you don't, these are the problems that can happen:
Despite all these problems, it is still common practice to ship whatever is handy on closed source situations like inside companies that have a NPM proxy. In this case NPM is just where artifacts are stored. And since the consumers are tightly controlled, it's not a problem. But if you want to distribute packages freely you should be mindful of these issues. If you want to package CLJS libraries, then One important point about packaging ES5 code compiled from CLJS is bundle size. As mentioned on thheller/shadow-cljs#200 (comment), you can end up with multiple versions of The (browser) JS world is very sensitive to bundle sizes nowadays, as it should be. No one wants to have multiple 93k overheads from importing a couple of different libraries. There still isn't a bundler/minifier that is as good as the Closure compiler, but good usage of Rollup/Webpack/Terser can get you very close, and with a lot more compatibility. The Angular project expends significant effort in keeping their libraries optimizer-friendly and free from toplevel eval side-effects. So I think that if you ever want to make compiled CLJS libraries usable by non CLJS consumers, the most important problem to tackle is the possible multiplicity of It's generally fine to package unoptimized ES5 code and to let consumers optimize it, so I don't think you need to care about the Closure compiler when packaging libraries. The important bit is to provide a way for multiple libraries to be using the same existing Maybe something similar could be done for I can imagine a CLJS library on npm that looks something like this:
Where the This way a JS consumer of this lib can use it as JS and has a chance at not bundling |
One feature that other compile-to-JS languages don't have to deal with is macros. A big part of ClojureScript is macros and a lot of CLJS libraries will have one or more. Therefore it is often undesirable to have CLJS code directly accessible from JS since you can't really "consume" a macro from JS. Having a generic mechanism for CLJS where each package is directly consumable from Another issue is that ClojureScript was very much built with the Closure Compiler in mind. That buys us a lot of freedom in how to design packages and we generally don't need to worry about "big" namespaces since Closure will just remove the stuff we don't use. Since we expect to run through the CLJS code can still be easily accessible from JS so integrating it into existing JS projects is quite easy, it just requires a separate build step (just like calling Pre-compiled code on The problem with shipping source of course is that you need a tool to compile it and you need to define a minimal subset of supported features. Given the rate of change JS is still going through that is unlikely to find any consensus anytime soon. |
It's true that macros cannot be used by a JS consumer, but from an exports point of view it doesn't sound like it change much. Going back to the TS example, TS libs include interfaces for the TS consumers, but they cannot be used by the JS consumers either. The library API for JS consumers is a subset of the "full" API that is only available for TS consumers. I agree that there's no point in just publishing the source in Regarding the Closure Compiler I really have to reiterate that you can get most of the way there with other tools. Not all the way, but most of the way. A new Angular app is ~3.5mb in dev mode and 0.18mb in prod mode. Using some advanced optimization modes we get 14k basic apps starting from the same base library. Property renaming is great but that is just part of the story. But I also don't really know how big whole of Notwithstanding the problems of polyfills and the sort, I don't agree that shipping pre-compiled code is always worse than having access to the source in TS. In that case I think the pre-compiled code is better. In Angular we also use Bazel, which makes it pretty easy to depend directly on sources. We did that for a while and decided it was better to depend on the pre-compiled JS instead. There are advantages in depending on source but it's not without problems. |
I actually think there is a lot of value pushing source to |
A bit of off-topic, the biggest problem with the current JS port of the GCC is speed - no even close. Until that is fixed is we are never probably going to see I have recently found out about TeaVM and was kind of wondering how fast that would be. |
FWIW
clojurescript-npm
supports it.See: https://github.com/nasser/clojurescript-npm/blob/master/lib/register.js
The text was updated successfully, but these errors were encountered: