Skip to content

Conversation

@pesterhazy
Copy link
Contributor

This PR adds surrogate packages for cljsjs/react, cljsjs/react-dom and cljsjs/react-dom-server. These packages are like their non-surrogate counterparts, except that the contained javascript file is empty. The packages do contain externs for React.

Libraries like reagent require the cljsjs.react, cljsjs.react.dom and cljsjs.react.dom.server namespaces. If you use a Rect version provided by some other means, you need to make sure these requires don't fail. A common way to do this is to faux src/cljsjs/react.cljs etc. files containing empty namespaces.

With this PR, you can add these coordinates to your project.clj instead:

[cljsjs/react-surrogate "15.5.4-0"]
[cljsjs/react-dom-surrogate "15.5.4-0"]
[cljsjs/react-dom-server-surrogate "15.5.4-0"]

This is a cleaner solution than adding empty namespaces. Note that you also need to exclude all cljsjs react packages. The best way is to add global exclusions:

:exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server]

react/build.boot Outdated
(comp
(surrogate :filename (format "cljsjs/%1$s/development/%1$s.inc.js" (name project))
:project project)
(surrogate :filename (format "cljsjs/%1$s/production/%1$s.min.inc.js" (name project))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minified file is not required, so this could be removed to simplify this a bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if :file-min is not set in deps.cljs, :file is used automatically? The reason I left this in was because I wasn't clear on the mechanism by which the minified file is selected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Deraen nice, I've pushed a version that doesn't build a .min variant

@martinklepsch
Copy link
Member

Maybe document why these packages exist + recommended usage in the package readme as well?

@pesterhazy
Copy link
Contributor Author

@martinklepsch good point. I think the README could use a overhaul in general. Can this be done in a separate PR?

@martinklepsch
Copy link
Member

Sure

@thheller
Copy link
Contributor

thheller commented Jun 6, 2017

I think this is dangerous.

Like @pesterhazy said :exclusions would need to be global but I'm not sure lein even supports that.

In shadow-cljs I added an option to ignore any :foreign-libs JS that will also auto-create empty :provides from these. :externs are still used but none of the JS. This isn't ideal as well since it is not obvious that cljsjs.react provides the js/React variable.

I think the proper way forward for all this is through: https://dev.clojure.org/jira/browse/CLJS-2061

Creating work arounds for work arounds needs to stop.

@pesterhazy
Copy link
Contributor Author

pesterhazy commented Jun 6, 2017

@thheller Could you elaborate why this PR is dangerous? I don't see how shadow-cljs is relevant.

Of course global exclusions are supported in lein and in boot.

@thheller
Copy link
Contributor

thheller commented Jun 6, 2017

This is dangerous because it sets the precedent.

Want to use native package? Use cljsjs/foo-surrogate instead of cljsjs/foo.

So soon we would have foo-surrogate for every foo because all of this is not just limited to react, it just is the most common NOW and the most obvious example.

I mentioned shadow-cljs as an example for a different solution that doesn't require surrogate packages at all but achieves the same thing. Of course there should be an official solution for that not something shadow-cljs only.

@thheller
Copy link
Contributor

thheller commented Jun 6, 2017

CLJSJS and :foreign-libs is a work around since it isn't simple to just consume native packages.

It shouldn't require another work around to actually be able to use native packages again.

@pesterhazy
Copy link
Contributor Author

I agree that we should be working on a better solution to the general problem of accessing native packages.

But I don't agree that as an interim solution, surrogate react packages are dangerous. This is a workaround of course, but it's significantly less hacky than the existing solution of adding empty namespace. Every cljs react native project uses this hack.

The same problem arises today when you use webpack to build a second bundle as explained in this post. It's much better to have all the dependency information in one place, i.e. project.clj or build.boot.

I think this is mostly needed for React (which is why this PR only addresses React).

@thheller
Copy link
Contributor

thheller commented Jun 6, 2017

Interim solutions are dangerous since they tend to become permanent or make things significantly more complicated to new users. These things tend to stick around since all this stuff isn't easily discovered and finding 3 different solutions via google without knowing which the "current" one is really sucks for the user.

I'd rather just say "don't use :foreign-libs" at one point in my configuration over switching dependencies and adding global :exclusions for every dependency I want to override.

IMHO, YMMV.

@martinklepsch
Copy link
Member

martinklepsch commented Jun 6, 2017

How about we go forward w/ this, but clearly label it as advanced & link relevant JIRA tickets etc?

I see the points @thheller is making and agree. But it's also clear that this is a pain for many (experienced) CLJS devs working with React Native and merging this would ease that pain until we have a more permanent solution.

@thheller
Copy link
Contributor

thheller commented Jun 6, 2017

Opened: https://dev.clojure.org/jira/browse/CLJS-2074

Vote it up if you agree that this is important.

@Deraen Deraen added the wontfix label Jun 6, 2017
@Deraen
Copy link
Member

Deraen commented Jun 6, 2017

Lets see if/what other solutions we can come up with. This has been an issue for a long while already so I think it is best to not hurry too much.

@Deraen
Copy link
Member

Deraen commented Jul 12, 2017

After https://dev.clojure.org/jira/browse/CLJS-2214, https://dev.clojure.org/jira/browse/CLJS-2213 & co. this has pretty much been solved in ClojureScript compiler now.

Libraries can (:require [react :as react]) and React can be provided by Node + module processing, Node require if targetting Node, or by foreign-lib in Cljsjs package.

@Deraen
Copy link
Member

Deraen commented Jul 29, 2017

React packages now use :global-exports: #1275
Next Reagent will use this to require React: reagent-project/reagent#306

I think these changes will solve the problems of using Reagent/React in different environments.

@Deraen Deraen closed this Jul 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants