Fork me on GitHub
#clojurescript
<
2020-01-09
>
quoll01:01:55

Sorry to come in with such a newbie question, but would anyone please know why I would have references to window and document when I generate .js files with the compiler option set to :nodejs?

lilactown01:01:34

if the CLJS code includes references to window or document, they will not be removed

lilactown01:01:41

the :nodejs target for shadow-cljs simply does some extra work for you to optimize it correctly for Node.js. It won’t remove code that won’t work in Node.js

quoll01:01:23

Anything else?

quoll01:01:25

This is code that was in separate .clj and .cljs files. I already bring the code in as a library. But it needed an update, so in the process I decided to merge them into a .cljc file (The two original files were almost the same anyway). But now I can’t run the test, because when I try it tells me that I have references to document and window 

potetm01:01:13

You can maybe compile with :optimizations :none, :pretty-print true and then grep the output for references to window or document.

potetm01:01:52

I’ve usually found it straightforward to translate from js to cljs with those settings.

potetm01:01:53

@quoll actually, did you by chance change the optimization level for your code? IIRC some of the optimizations will attempt to write a script tag to the dom.

quoll01:01:28

I’m not sure what you mean by “translate from JS to cljs”. Do you mean, so that I can find the code that generated the reference?

potetm01:01:48

yes, exactly

quoll01:01:05

OK… I was AFK for a bit (and responding via my phone), but I’m back now

quoll01:01:40

:optimizations :none is a bit difficult:

Assert failed: :nodejs target with :none optimizations requires a :main entry
(not (and (= target :nodejs) (= optimizations :none) (not (contains? opts :main))))

quoll01:01:35

This is the code that’s reported (reformated by hand):

goog.testing.TestCase.prototype.getName = function() { return this.name_ };
goog.testing.TestCase.maxRunTime = 200;
goog.testing.TestCase.protectedSetTimeout_ = goog.global.setTimeout;
goog.testing.TestCase.protectedClearTimeout_ = goog.global.clearTimeout;
goog.testing.TestCase.protectedDate_ = Date;
goog.testing.TestCase.protectedPerformance_ = window.performance && window.performance.now ? performance : null;
goog.testing.TestCase.currentTestName = null;
It’s that protectedPerformance_ value that causes the error

potetm01:01:34

hmm… :thinking_face:

potetm01:01:46

well I got nothing for that :feelsbad:

quoll01:01:51

OK… I’m seeing what has happened.

quoll01:01:54

I think 🙂

quoll01:01:40

The original code was all .clj. To make it compatible with ClojureScript, he copied the file to .cljs and modified it. (so far, so good)

quoll01:01:13

But then he wrote a complete different set of tests for it.

quoll01:01:55

In my process of merging the .clj and .cljs files, into a single .cljc I had also hoped to merge the tests.

quoll01:01:17

But I thought I would check that my .cljc file would work with the existing test first

quoll01:01:30

That’s what I’m trying to do, and that’s what fails for me

quoll01:01:17

I just looked at this .cljs test file, and I see that he has incorporated: (:import [goog.testing TestRunner TestCase])

quoll01:01:39

The code then creates these objects:

(def tr (TestRunner.))
(def test (TestCase. "The Project"))

(defn test-always []
  (parser-result? 5 (p/always 5) "")
  (parser-result? 5 (p/always 5) "abc"))

(.add test (TestCase.Test. "test-always" test-always))

(defn test-nxt []
  (parser-result? 5 (p/nxt (p/always 3)
                           (p/always 5)) ""))

(.add test (TestCase.Test. "test-nxt" test-nxt))

potetm01:01:44

ah ok, yeah I was thinking, “surely cljs doesn’t depend on something that can’t be ported to node”

quoll01:01:25

So it looks like the reliance on TestCase is bringing in these references

potetm01:01:49

right, can that be ported to vanilla cljs.test?

quoll01:01:12

i.e. I’m going to throw away the .cljs test file and port the .clj file into .cljc

quoll01:01:45

there are already vanilla tests that use clj.test so it should be OK

quoll01:01:45

I just caused myself grief by trying to make it work along the way. (I’m thinking that if I check the library out clean, then the ClojureScript tests still don’t work. I forgot to check them clean)

JAtkins03:01:41

Can defs be marked for running by the compiler? e.g. statically run this

(def v1 {:key :val})
(def v2 {:key2 :val2})

(def v3 (merge v1 v2))
so that the program startup doesn't get hung up with some small calculations?

JAtkins03:01:43

I'd like to have the compiler replace the merge with {:key :val :key2 :val2} by running the code during compilation. I have a large cljs app that's beginning to slow down from some more complex code in defs like this

kenny03:01:54

You could inline the calculations with a macro.

JAtkins03:01:27

Can it reach the other defs from a macro?

kenny03:01:17

Everything would need to be done at compile time.

JAtkins03:01:12

Huh. Sounds like it would get messy quickly.

kenny03:01:43

What are you doing that takes so much time?

JAtkins03:01:59

Some static config stuff is all being generated. It's not a ton of time, maybe <50ms right now, but I'd like to have a solution before it gets bigger.

Ivan Koz03:01:46

static means compile time why is it a problem then?

JAtkins03:01:46

e.g. some complicated custom merge logic to deduplicate a vector of config maps.

JAtkins03:01:13

Right now it's running every page load

Ivan Koz03:01:37

so to use a macro to setup your defs

kenny03:01:21

Everything can be done at compile time. It's just like writing clojure @U5P29DSUS.

Ivan Koz03:01:31

it will run on cljs to js translation

Ivan Koz03:01:42

so you js sources will have all the data already present

kenny03:01:15

Right. The tradeoff is payload size. It's typically trivial though.

Ivan Koz03:01:14

unlike on JVM where compiler runs at runtime, so there is no difference from that point of view

JAtkins03:01:33

That's the best solution I guess. I was hoping for a cleaner solution because I have some chains that are longer. That would require maybe everything being passed to a macro and the macro evaling to a map with the results being put in individual defs

Ivan Koz03:01:18

well maybe you have an architectural\\design problem

JAtkins03:01:07

Perhaps, but I don't think so for this.

Ivan Koz03:01:34

will help you to improve configuration performance

Ivan Koz03:01:36

specter is usually faster for manipulating nested data structures

JAtkins03:01:34

Thanks! Cool projects, but not applicable to my issue here. https://clojurians.slack.com/archives/C03S1KBA2/p1578541758132000

Aaron Addleman04:01:07

Anyone have suggestions on what to read and where to start for deploying CLJS to AWS Lambda?

valtteri06:01:34

What kind of tooling are you planning to use? I mean are you planning to use Serverless Framework, SAM, or setup the infra yourself? Depending on your preferences there are some existing tools and examples. In the past I’ve used https://github.com/nervous-systems/serverless-cljs-plugin with success but at the moment my go-to-choice is using shadow-cljs to compile CLJS -> JS and then upload the code and infrastructure with Serverless Framework. I have a small example project here https://github.com/vharmain/serverless-healthcheck There’s some discusssion in https://clojureverse.org/t/cljs-aws-lambda/2183 and also a bit inactive #aws-lambda

👍 4
Aaron Addleman16:01:21

@U6N4HSMFW thank you so much for all this great info! Very helpful

valtteri17:01:44

No problem! Let me know if you have any further questions. 🙂

Lokanadham07:01:24

How can i write serialized java objects into a file and read them back into java objects in clojure? any serialization library for this?

alexmiller12:01:32

you can just use Java serialization via Java interop

alexmiller12:01:34

that doesn't handle the file part, but that's just a matter of layering in a FileInputStream / FileOutputStream in the chain

dnolen14:01:14

@cmcfarlen right, maybe there's a way to exclude those nses, but I don't know how to do that - none of the various things I tried work. AOT compilation in Clojure basically transitively compiles everything you need. Far as I know you can't link together independently AOTed things - or it's just outside of my experience how to accomplish that.

dnolen14:01:38

your other option is to just avoid the AOTed ClojureScript dep, this means a longer startup time - but if your workflow is heavily REPL driven then maybe that doesn't matter for you

dnolen14:01:02

we provide a sources dep

kenny15:01:29

Just received this warning from the cljs compiler: "cljs.core//, all arguments must be numbers, got [cljs.core/LazySeq number] instead". I instantly knew what was wrong. So freaking cool. Thank you guys for the awesome type inference work!!

cljs 4
cmcfarlen16:01:48

@dnolen Thanks for the info. I was not aware of the source cljs dep. We'll look at using that or adjusting our workflow to separate out the cljs dep.