Fork me on GitHub
#clojurescript
<
2021-06-15
>
tomrbowden00:06:50

Has anyone dealt with solving performance issues with Safari specifically for a web app written in ClojureScript? I am writing a feature involving drag and drop, using the Reagent wrapper around React, and the https://react-dnd.github.io/react-dnd/about library. The feature has some complexity to it, with calculations involving where the UI “blocks” can be dropped, including drag previews. I am able to get it to work quite smoothly on Chrome/Firefox/Edge, but the lagginess on Safari makes it unusable in that one browser… Does anyone have any advice/pointers? 🙏

p-himik10:06:36

No direct experience, but I would first check that it's indeed CLJS and not the DnD functionality itself. Then, if you can confirm it's CLJS, I would simply profile it, assuming Safari has a JS profiler.

tomrbowden11:06:41

How do I check it’s CLJS versus React DnD?

p-himik11:06:37

If you can create two implementations of a very simple DnD functionality where one is written in CLJS and the other is in JS, then you can compare them. If it's not that easy, you can start with profiling - chances are, it will answer that question as well.

tomrbowden11:06:33

Oh, the first part of that I have already done. With simple apps, there is no lag in Safari with either CLJS version of React-DnD, versus JS version of React DnD implementation. I only saw a big performance lag in Safari with the more complex feature, which I would rather not replicate in JS, due to time constraints. As said though, with other browsers the drag and drop works fine for the complex CLJS/ReactDnD…

p-himik11:06:28

So it's still unclear what the cause is then. Either the complex feature is written in a way that's slow on Safari, or it uses some browser JS API that's slow on Safari. The first case might be fixable by just rewriting the same feature in a different way. The second one might be fixable if there exists some alternative API that could be used instead.

p-himik11:06:07

Also, check out if you can find some relevant issues in the WebKit bug tracker.

tomrbowden11:06:34

Thanks for the feedback - I will check those avenues!

Evan Z01:06:15

what’s the right way to pull some CSS framework into a project like tachyon or bulma? I know that shadow-clj doesn’t really support sass/scss, though there’s ways to write CSS as clojure using garden

p-himik10:06:25

You can use build hooks or just start a separate process to compile anything to CSS, including sass/scss. Sometimes people write their own small wrappers for CSS frameworks/libraries. I know of two for Tailwind CSS.

magnars07:06:15

I switched to the newest devcards (0.2.7), which is now providing react via :npm-deps . This works fine. However, in combination with :install-deps true in my ClojureScript compiler options (for other reasons), two things happen: • the dependencies declared in npm-deps in devcards are added to my package.json (this is expected) • my app now fails with $jscomp is not defined and React is not defined (unexpected for me) There must be something about :install-deps that I don't understand. What am I missing? Thanks!

dnolen13:06:27

@magnars this is usually a :language-out problem if I recall - set it to :es6 or higher I think?

magnars14:06:19

Setting :language-out :es6 didn't do it, unfortunately. Do I have to make sure React is loaded into the page myself when using it like this?

magnars14:06:53

In short: React is provided via transitive :npm-deps in Devcards, until I add :install-deps true in my compiler opts. After that, I get ReferenceErrors.

dnolen14:06:04

@magnars $jscomp is probably closer to the real problem

dnolen14:06:38

Closure is generating some stuff that expects runtime support which is quite strange

dnolen14:06:24

@magnars oh ... but it sound like you are trying to push React through Closure? doesn't work - you haven't said anything about using the :bundle target

dnolen14:06:53

if that's true that the appearance of $jscomp and the other problems are not much of a surprise

dnolen14:06:11

if you want to use stuff from node_modules you need to use :bundle target

magnars15:06:59

That is indeed the case. We are not using the :bundle target. Thanks for the heads up, I'll follow up on that lead. 👍

West15:06:06

Is there an equivalent to clojure.data.json for clojurescript?

dpsutton15:06:37

the heart of that is reading and writing json which is handled pretty well natively by JSON/stringify and JSON/parse : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON

West15:06:42

Oh, so I can just call these by using something like js/json.stringify ?

dpsutton15:06:45

(.stringify js/JSON (clj->js {:a :b})) . i think you can get away with js/JSON.stringify though

West15:06:59

It works! Thanks a bunch!

West15:06:03

Looks like my script works fine when I run it in a repl, but it fails when I compile it to a js file and run with node. It will create a directory if it isn’t there, but it won’t generate any files.

thheller15:06:20

remember that map is lazy. so you want to use something that forces the lazy seq. eg.

(defn gen-all-posts
  [in-path out-path]
  (create-out-dir out-path)
  (let [input (rest (file-seq in-path))]
    (doseq [file input]
      (spit (str out-path (:id (:data (blog-post (slurp file)))) ".json")
        (js/JSON.stringify (clj->js (blog-post (slurp file))))))))

West15:06:24

Ok, I might have to read up on what laziness means, because this is the second time I came across a problem like this.

West15:06:10

Thank you again @thheller, and thank you doseq.

sergey.shvets23:06:30

Hi. Is it possible to get access to compile-time def inside clojurescript macro? Here is what I'm trying to achieve

;; cljs file
(ns my.cljs)

(def test-map {:foo :bar})

(mymacro test-map)

;; macrodef.clj
(defmacro mymacro
   [symb]
;; can I get the {:foo :bar:} here somehow? 
) 
Thanks in advance! I tried every option I could google, but no luck thus far.

p-himik23:06:30

It's possible if that def is inside a CLJC file.

sergey.shvets23:06:13

Do I get it using resolve and deref ?

sergey.shvets23:06:39

I'm able to get metadata of a def from cljs using cljs.analyzer, but can't figure how to get actual value.

p-himik23:06:36

Neither. You just use regular :refer.

p-himik23:06:15

Note that if you have some ns defined in a CLJC file, you cannot also have a CLJ or a CLJS file for that same namespace.

p-himik23:06:14

;; a.cljc
(ns a)

(def test-map {:foo :bar})

;; macro.clj
(ns macro
  (:require [a]))

(defmacro mymacro [symb]
  (do-something-to a/test-map))

sergey.shvets00:06:23

I see. I wasn't clear that I want to pass the def's symbol as one of the arguments to macro. I'm trying to write a macro that will build a query in compile time and trying to pass some meta information like names of collections, server, etc.

sergey.shvets00:06:37

Meta information is constant (doesn't change in runtime) and I'm trying to figure out if there is a way to access it from macro

p-himik00:06:09

Ah, then it's @(resolve symb). But the comment about it being in a CLJC (or regular CLJ) file still applies.

p-himik00:06:27

symb has to be a fully qualified symbol, of course.

sergey.shvets00:06:24

Thanks, it works with cljc file.

👍 3