Fork me on GitHub
#clojurescript
<
2022-06-12
>
Godwin Nicholas02:06:21

Please is Om or Om next still use?.

sansarip03:06:46

I don’t believe that they’re actively maintained, and I would not recommend them! They are still in use in codebases, but probably mainly as legacy code -I can speak from experience here 🙅

danieroux07:06:26

The ideas of Om lives on strong in https://fulcro.fulcrologic.com/

Godwin Nicholas09:06:08

Very grateful for the answers thank you very much

pinkfrog03:06:47

I am looking into RUM these days since I heard people recommending it from time to time. One reason is due to the server side rendering. But other than it, how does it compare to reagent and what pain points does it solve compared to reagent?

pinkfrog03:06:46

Also, for server side rendering, does it assume we have to use nodejs as the backend? Or else how does we invoke react to generate html on the server side?

pinkfrog03:06:35

or some js engine embedded in jvm?

didibus04:06:36

It renders hiccup to html on the server-side, once it is loaded on the client, the html is enhanced to connect to a react component

didibus04:06:08

So it only does SSR for the first page load, if the user than interacts with JS components that will use react on the client side

pinkfrog04:06:05

> It renders hiccup to html on the server-side Is react relevant to this? Sounds like SSR is all about Clojure (hiccup) stuff. My initial impression was, SSR sounds like running react on the server side to pre-generate the html needed.

didibus04:06:56

Well, react is relevant in that the rendered HTML from Rum can connect to a react component on the client side. So it's still an interactive page, just the first render is done on the server

didibus04:06:09

If you don't need interactivity (beyond what HTML can do), you can just use Hiccup directly, no need for anything else, and you don't even need JS and thus Clojurescript

didibus04:06:26

Technically Rum can be used instead of Hiccup, it has its own renderer for Hiccup that's supposedly claimed to be faster. So it can be used without React for just standard HTML SSR without interactivity, but a lot of the features won't be useful, it's just a way to organize hiccup basically.

didibus04:06:36

Generally people want to create a highly interactive web page powered by React, and also have SSR so the first page load is faster and search engine can index the content. That's where Rum shines as it can render the first page and then let React take over for interactivity.

👆 2
simongray11:06:42

SSR with rehydration is a React thing. SSR with Rum is interesting because it doesn't force you to use JS on the server like doing it directly in React would, i.e. if you're rehydrating React components then you're probably using JS on the sever too, but with Rum you can just use JVM Clojure and get the regular Clojure backend experience.

Sam Ritchie11:06:04

Is it possible to inspect a javascript object / package from within a macro environment? I am writing a cljs library that wraps and extends mathbox-react, an npm package with 54 existing React components. I’d like to emit a line like this for each component:

(def ComponentName (r/adapt-react-class mbr/ComponentName))
I know that the user can already call [:> mbr/ComponentName] without my wrapper, but I am going to provide additional components and I don’t want them to have to remember which are raw React and which are higher level. At runtime I can do emit vectors of [symbol component] like this:
(ns example
  (:require ["mathbox-react" :as MB]
            [reagent.core :as r]))

(def sym->component
  (doseq [[k v] (.entries js/Object MB)]
    [(symbol k) (r/adapt-react-class v)]))
is it possible to do something similar in a macro and emit something like (def ~(symbol k) ~(r/adapt-react-class v)) ?

p-himik11:06:46

You can definitely run some JS code within JVM, but that would mean bringing in some extra dependencies for compile-time. This is the commit where shadow-cljs removed similar functionality: https://github.com/thheller/shadow-cljs/commit/6daffeae50d0b7f029aad8e975997b20223955dc It might be tricky to make it work with an NPM dependency, although documentation suggests that it should be straightforward: https://www.graalvm.org/22.1/reference-manual/js/Modules/

p-himik11:06:22

FWIW, a similar wrapper went with a direct approach - all the symbols are already there in the code: https://github.com/arttuka/reagent-material-ui Apart from being the most straightforward implementation, it also gives its user all the static code inspection niceties. And you don't have to write everything by hand - you can have a CLJS script that generates those (def ...)s for you, which you would then commit into a repo.

Sam Ritchie11:06:59

Amazing @U2FRKM4TW !! This is exactly what I needed. Thank you!

👍 1
p-himik11:06:12

Actually, definitely go with the second approach. Because if you gather everything under a single umbrella namespace, DCE will not be possible. An NPM dependency, once required in a loaded namespace, will not be removed - even if you don't use it.

p-himik11:06:08

In the case of arttuka/reagent-material-ui, notice how the author puts every components in its own namespace. You don't want to load a million of icons or whatever just because you needed a single number input field.

Sam Ritchie11:06:50

interesting, that makes sense. in this case all components live in a single file: https://github.com/ChristopherChudzicki/mathbox-react/blob/main/src/components/components.tsx

Sam Ritchie11:06:21

@U2FRKM4TW how would you deal with an import of this components.tsx to allow DCE?

Sam Ritchie11:06:08

for example maybe one namespace per components, but then ["mathbox-react/path/to/components" :refer [SpecificComponent]] in each namespace? would that do it?

Sam Ritchie11:06:35

or is this a change that the mathbox-react library author should address upstream, with separate files for each component

p-himik11:06:17

> how would you deal with an import of this components.tsx to allow DCE? As far as I know, that would not be possible without refactoring the mathbox-react library. :refer doesn't cut it. It has to be its own namespace. When you use :refer, the whole mentioned JS file is still loaded.

p-himik11:06:30

As a piece of reference: https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages Specifically, the rest of the section starting at "Notice that previously we were stuck using bundled code".

Sam Ritchie11:06:43

okay I can push that upstream, that is helpful. I’ll do the right thing in this library and then get that change pushed up. you noted that I could write a cljs script to generate each def; that will let me pull in docstrings too so that’s actually quite nice. the idea is to have the script actually populate the file tree yeah?

p-himik11:06:35

Could even put it into a Git hook and make sure that there are no changes to the generated files before you commit.

p-himik11:06:01

Just to guarantee that your CLJS code is always in sync with whatever NPM library version you depend on.

Sam Ritchie12:06:59

FINAL QUESTION while I have you: I named the library mathbox-cljs, which is a touch awkward. My thought was that, because there is an npm dependency pulled in with the name “mathbox”, that it would be good to disambiguate. If I DID make namespaces like (ns mathbox.blah) , would the compiler become confused with the "mathbox" dependency? typing this out I guess that would only be a problem with a bare mathbox namespace at the top level.

Sam Ritchie12:06:41

so maybe this is actually a question about “is there any good reason to add that suffix”, since it would be definitely clearer for the user to remove it

p-himik12:06:20

I don't think there's a good reason, unless, as you say, you decide to use a single-level mathbox namespace. Just to be sure, I'd check that mathbox.blah doesn't intersect with "mathbox/blah" (of course, you have to find what JS package you can import, and then create a corresponding CLJS namespace). And you'd also have to check with different build tools since AFAIK they resolve or might resolve NPM dependencies differently. But I'm 90% certain that it's not an issue at all.

Sam Ritchie12:06:43

yeah, that would be the issue I’d anticipate, that if I want to mirror mathbox’s tree I’ll end up with clashes. But now that I look, mathbox has all of those nested under “primitives/types”: https://github.com/unconed/mathbox/blob/master/src/primitives/types/operator/grow.js so I won’t clash.

👍 1
p-himik12:06:09

Even if there was a name clash, my intuition suggests that mathbox would be first checked at mathbox.cljs and "mathbox" would be first checked at mathbox.js. But maybe it's wrong, although I'd be surprised.

👍 1
johndoe17:06:39

Advice needed. How would you implement bit masks in clj and cljs when they definitely won't fit in a single int? I think about int-array but maybe there is a better approach.

p-himik17:06:33

My first step would be to consider very carefully whether I truly need a bit mask or whether some other approach would work, like a map with boolean values. If the conclusion is that a bit mask is the only approach, then I'd probably use js/BigInt with CLJS and BigInteger with CLJ.

Alex Miller (Clojure team)17:06:57

In Java, https://docs.oracle.com/javase/8/docs/api/java/util/BitSet.html is probably good to consider, not sure if there is a js equivalent

p-himik17:06:45

Ah, thanks. I kept thinking that there was a specific class for this but couldn't remember it. And seems like there are a few JS libraries to mimic that functionality.

johndoe17:06:57

Thank you guys! I want a single implementation for both languages, so it seems like int with fallback to int-array is the only option.

p-himik17:06:36

It'd still go with BigInt and BigInteger then because they both support bitwise operations. Ints are different between JS and Java - you can't just use them without writing at least some platform-specific code.

johndoe17:06:31

> writing at least some platform-specific code. Yeah, I know. Svelte is a reference implementation for my problem. Have checked and they are using arrays of *ints, not even bigints.

👍 1
johndoe17:06:01

Of course just with regarding int size (in js int is 32 bits, and they use 31 bits).