Fork me on GitHub
#shadow-cljs
<
2020-01-29
>
genekim04:01:41

Wow. shadow-cljs is amazing! I’m amazed at how wonderful the CLJS REPL is, and how fast the code loads in the browser! Thank you for all your wonderful work, @thheller!

genekim05:01:45

I have a question that I’m hoping someone with more npm experience can easily answer… . I was using the linkify npm module via cljsjs in a figwheel project. I’m trying to convert it over to shadow-cljs and for the life of me, I can’t figure out how to get the syntax of the require correct. In the GitHub repo, the instructions are: https://github.com/SoapBox/linkifyjs/

var linkify = require('linkifyjs');
require('linkifyjs/plugins/hashtag')(linkify); // optional
var linkifyHtml = require('linkifyjs/html');
So, following the instructions, I tried this:
(:require    
    ["linkifyjs" :as l]
    ["linkifyjs/hmtl" :s lh])
But I keep getting errors like:
The required JS dependency "linkifyjs/hmtl" is not available, it was required by "trello_workflow/io.cljs".

Search in:
	/Users/genekim/src.local/trello-workflow/node_modules
You probably need to run:
  npm install linkifyjs/hmtl

See: 
How does one get access to the linkifyHtml function? Many thanks in advance! And keep up all the great work, @thheller!!!

genekim05:01:55

PS: In my desperation to get things running again, I even tried switching to the goog.string.linkify library in Google Closure, but wow, their SafeHtml classes are way too effective — I couldn’t replicate all my dangerous hacks I was using! 🙂

sogaiu05:01:45

@genekim it's not a matter of "linkifyjs/hmtl" -> "linkifyjs/html", right?

genekim05:01:38

OMG. You’re right @sogaiu — I had a typo! (I’ve been banging my head on this for 90m. I think I had it right in an earlier iteration…) Wait, more typos… oh, hey!

lh
=> #object[Function]
(lh "")
=> "<a href=\"\" class=\"linkified\" target=\"_blank\"></a>"
Thank you so much!!! 🎉 🎉 🎉 🎉

sogaiu05:01:06

:thumbsup:

genekim05:01:32

PPS: @thheller Your documentation is superb. For the first time in three years, I finally have some reasonable understanding of what a classpath is! (Your description of the source-paths was a huge lightbulb moment for me.)

🙂 8
👍 12
💯 4
sogaiu05:01:00

also very much appreciate the docs :thumbsup: on a side note, i found the following seancorfield article to be very informative wrt classpaths and some clojure-related tooling: https://corfield.org/blog/2018/04/18/all-the-paths/

genekim14:01:49

Thank you!! Superb article!!! Thx to you and @U04V70XH6 !!!

Mathieu Pasquet07:01:17

Hey, sorry didn't realize there are other channels! I posted in #clojurescript but maybe this is more appropriate. Here's a link to what I posted : https://clojurians.slack.com/archives/C03S1L9DN/p1580280756468800

J08:01:30

Hi 🙂. I’m wonder if there is a trick to have code splitting with expo and react-native for the web target?

thheller08:01:41

@jean.boudet11 I did some prep work for that and it works in theory but I have no idea how to make react-native actually lazy load the code. it requires messing with some rather weird react-native/metro internals that I don't know how to get working. https://facebook.github.io/react-native/docs/performance#ram-bundles--inline-requires

J08:01:33

Ok thanks! In fact, expo can use react-native-web to target the web but in shadow-cljs the build target react-native . I try to use a target web for react-native-web without expo but not work for the moment because of ui-kitten.

thheller08:01:43

yeah no clue about any of that sorry.

J08:01:37

No problems 🙂 ! Thanks for your time and shadow-cljs

thheller08:01:36

dunno if thats even possible with expo

p-himik08:01:43

About replacing the <latest> placeholder with "LATEST". It seems that in Maven 3, both "RELEASE" and "LATEST" are missing: https://cwiki.apache.org/confluence/display/MAVEN/Maven+3.x+Compatibility+Notes#Maven3.xCompatibilityNotes-PluginMetaversionResolution The maven-resolver-api that's used by tools.deps still seems to support "RELEASE" though, but I cannot find any specific information about it.

thheller08:01:43

hmm yeah might be "RELEASE", not exactly sure. I saw something used in a project that wasn't an actual version and was surprised to learn it worked 😛

p-himik09:01:50

Well, the code of tools.deps does have a special clause for handling "RELEASE" and "LATEST" specifically. But I can't find any proper mention of these aliases in the tools.deps documentation as well. So maybe it's just legacy stuff left in there because Maven 2 used to support it, no idea.

thheller09:01:32

yeah I'm always wary of "magic" version numbers but having to look up the latest version isn't great either

p-himik09:01:51

Hmm. Now I think that for a build tool, using such an alias is not really appropriate though. It will lead to situations where I develop with one shadow-cljs version, test with another one, deploy with the third one. And just to avoid going to the homepage of every single library I use, I find https://github.com/Olical/depot quite sufficient. :)

thheller09:01:11

thats for finding newer versions. you still need to know at least one version to use it 😛

thheller09:01:39

thats one thing npm install thing actually got right

thheller09:01:16

I may add something like shadow-cljs find-versions reagent or something like that some day

thheller09:01:30

but given that I already have a billion other features planned that'll probably take a while 😛

p-himik09:01:27

Right, that makes sense. Maybe even shadow-cljs add-dep reagent or something like that. :) But that asks for a different project. Or maybe a PR for depot.

thheller09:01:34

I thought about add-dep a lot but its just not gonna work. programmatically editing shadow-cljs.edn (or deps.edn) destroys all the formatting and comments the user may have done

thheller09:01:18

and I'm very sensitive to my config file structure. it changing "randomly" is not something I would accept

thheller09:01:49

thats one thing EDN isn't great for

thheller09:01:14

might be doable with something like rewrite-clj but that is also rather difficult to use 😛

thheller09:01:54

I have some ideas on how to do it but who has the time to do it ...

p-himik09:01:12

Oh, right. Well, it should be possible to always add the requested dependency right at the end of the :deps map. Although it may require hooking into the EDN parser or even writing your own to know exactly where that } is (never tried or even read about rewrite-clj, no idea here). I'd argue that it would be enough for the vast majority of cases. And for the rest, the user can always fix the file manually, especially when using any VCS. The heavy lifting of getting the version and putting the coordinates into the file has already been done. But even just printing out the coordinates is much better than nothing, that's for sure.

thheller09:01:25

yeah and printing should be easy

thheller09:01:15

at some point I also wanted to generate build configs and such from templates but never could figure it out. I don't like templates that have even on incorrectly indented output :P

royalaid10:01:07

Hey @thheller just wanted to pop in and say I have started to refactor based on your recommendations. It is SO MUCH BETTER 🙌 ty again for the advice

👍 4
royalaid12:01:48

Final total for that commit: 34 files changed, 185 insertions(+), 1965 deletions(-)

Hi12:01:22

deletions are good 😁

thheller13:01:10

looks good 🙂

jeeq13:01:54

I seem to be having trouble requiring js files into shadow-cljs (react native project). Am I importing it in wrong? My Error:

[:app] Build failure:
------ ERROR -------------------------------------------------------------------
 File: /Users/jeeq/Documents/rnproj/src/js/rnproj/home.js:6:5
--------------------------------------------------------------------------------
   3 | 
   4 | function Home(props) {
   5 |   return (
   6 |     <Svg width={16} height={16} viewBox="0 0 16 16" fill="none" {...props}>
-----------^--------------------------------------------------------------------
primary expression expected
--------------------------------------------------------------------------------
   7 |       <G clipPath="url(#prefix__clip0)">
   8 |         <Path
   9 |           d="M11 16h2c.6 0 1-.4 1-1V8h1c.3 0 .6-.1.8-.3.4-.4.3-1-.1-1.4l-7-6C8.3 0 7.8 0 7.4.3l-7 6c-.4.4-.5 1-.1 1.4.1.2.4.3.7.3h1v7c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-3h4v3c0 .6.4 1 1 1z"
  10 |           fill="#546BFB"
--------------------------------------------------------------------------------
It seems to be able to find the js file but not parsing it correctly. I have a line in my :require, [“./home” :as svghome :refer (Home)] home.js is svg converted to “appropriate” format by tool linked by react-native-svg (https://svgr.now.sh/)
import React from "react";
import Svg, { G, Path, Defs, ClipPath } from "react-native-svg";

function Home(props) {
  return (
    <Svg width={16} height={16} viewBox="0 0 16 16" fill="none" {...props}>
      <G clipPath="url(#prefix__clip0)">
        <Path
          d="M11 16h2c.6 0 1-.4 1-1V8h1c.3 0 .6-.1.8-.3.4-.4.3-1-.1-1.4l-7-6C8.3 0 7.8 0 7.4.3l-7 6c-.4.4-.5 1-.1 1.4.1.2.4.3.7.3h1v7c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-3h4v3c0 .6.4 1 1 1z"
          fill="#546BFB"
        />
      </G>
      <Defs>
        <ClipPath id="prefix__clip0">
          <Path fill="#fff" d="M0 0h16v16H0z" />
        </ClipPath>
      </Defs>
    </Svg>
  );
}

export default Home;

thheller13:01:31

that is not a javascript file. that is a JSX file and JSX is not supported by shadow-cljs

dima13:01:09

Hello! I’m configuring running tests in browser. Is there a way to know what ns is going to be reloaded in start fn call in runner-ns? Currently start would run whole test suite, but i’d like to run tests from recompiled ns only. I tried using build-hooks for that which is getting build-state object. Idea was to store recompiled ns somewhere in global var and then use it in runner-ns start fn.

thheller13:01:28

that isn't currently supported no but I could make that data accessible

dima13:01:24

that would be awesome, thanks!

thheller13:01:02

please open an issue on github so I don't forget. have to finish up some other stuff first but its a relatively easy add so should be quick once I'm done with this.

dima13:01:19

ok, will do

jeeq13:01:51

@thheller doh! Of course. Guess my mind was elsewhere. Thank you. I’ll try using babel to convert as suggested in the doc

robert-stuttaford15:01:33

how might i go about diagnosing the root cause of this?

------ ERROR -------------------------------------------------------------------
 File: jar:file:/Users/robert/.m2/repository/org/clojure/clojurescript/1.10.597/clojurescript-1.10.597.jar!/cljs/core.cljs:999:14
--------------------------------------------------------------------------------
 996 |     (if (js/isFinite o)
 997 |       (js-mod (Math/floor o) 2147483647)
 998 |       (case o
 999 |         ##Inf
--------------------^-----------------------------------------------------------
No reader function for tag Inf

--------------------------------------------------------------------------------
1000 |         2146435072
1001 |         ##-Inf
1002 |         -1048576
1003 |         2146959360))
--------------------------------------------------------------------------------

robert-stuttaford15:01:04

https://stackoverflow.com/questions/48039878/cljs-core-cljs-line-988-col-14-no-reader-function-for-tag-inf says i need org.clojure/tools.reader 1.1.0` at least, but i've checked, i have org.clojure/tools.reader 1.3.2 on the classpath (according to clj -Stree )

thheller15:01:49

hmm yes that is normally cause by having a CLJS version that doesn't match its required tools.reader version

thheller15:01:32

are you sure you checked your -Stree with all the aliases active you'd have active for cljs?

robert-stuttaford15:01:22

yes, with all aliases on, org.clojure/clojurescript 1.10.597 and org.clojure/tools.reader 1.3.2

robert-stuttaford15:01:54

bit of a head-scratcher

thheller15:01:46

try running clj (with the aliases) and then ( "clojure/tools/reader.clj") (require first)

robert-stuttaford15:01:58

looks correct

user=> ( "clojure/tools/reader.clj")
#object[.URL 0x1c7fd41f "jar:file:/Users/robert/.m2/repository/org/clojure/tools.reader/1.3.2/tools.reader-1.3.2.jar!/clojure/tools/reader.clj"]

Drew Verlee15:01:03

I have version 2.8.83 of shadow cljs and my shadow-cljs.edn file looks like so: {:app {:devtools {:preloads [shadow.remote.runtime.cljs.browser When i run shadow-cljs watch app it tells me the shadow.remote.runtime.cljs.browser ns isn't available. I'm not sure what else to try.

thheller15:01:35

are you sure you have 2.8.83? it is a common mistake for people using deps.edn/project.clj to update the the npm install but not the clj side

Drew Verlee15:01:14

facepalm yes. thats the problem

thheller16:01:40

@robert-stuttaford don't even know if the shadow-cljs version is relevant here but which one do you have?

robert-stuttaford16:01:00

would a discrepancy between package.json and deps.edn mess with that? package.json "^2.8.83" deps.edn "2.8.48"

thheller16:01:25

no, that doesn't matter

thheller16:01:24

only guess I have is that you have some AOT compiled version of the old tools.reader on the classpath

thheller16:01:56

check ( "clojure/tools/reader__init.class")

robert-stuttaford16:01:56

mf! #object[.URL 0x49872d67 "jar:file:/Users/robert/.m2/repository/com/datomic/datomic-pro/0.9.6021/datomic-pro-0.9.6021.jar!/clojure/tools/reader__init.class"]

thheller16:01:14

boom! dunno if its possible to figure out what version thats actually from but thats likely the problem

robert-stuttaford16:01:14

i'll try to exclude tools.reader on the datomic dep

thheller16:01:29

that does nothing. it is packaged in that .jar

thheller16:01:19

(btw I do recommend keeping CLJS dependencies separate because of stuff like that)

thheller16:01:43

there is no reason to have datomic on the classpath when compiling CLJS

thheller16:01:22

is it possible to remove deps when a profile is activated? something like :override-deps {datomic false} or so?

robert-stuttaford16:01:33

totally hear you. i'll move to a cljs alias

Drew Verlee16:01:43

now its telling me the build failed because clojure.datafy is not available. maybe I have clojure version 1.10.1 maybe that needs to be bumped?

robert-stuttaford16:01:52

great question, i'll check

thheller16:01:14

datafy should be in 1.10?

thheller16:01:30

@drewverlee your CLJS build failed? maybe you also have a bad CLJS version?

Drew Verlee16:01:42

well specifically it says:

The required namespace "clojure.datafy" is not available, it was required by "shadow/remote/runtime/shared.cljc".
"clojure/datafy.clj" was found on the classpath. Should this be a .cljs file?
Sorry. Ill just come back to this later. Im probably missing something obvious

thheller16:01:38

yes, that is a CLJS error. so you very likely have an old CLJS version

thheller16:01:18

should be 1.10.597

thheller16:01:00

I should write a blog post "yes, you might have a dependency conflict. no, that wouldn't happen if you put your CLJS dependencies in shadow-cljs.edn as recommended" 😛

robert-stuttaford16:01:03

we switched our biggest codebase to shadow this week. knocked 40% off our build time.

😎 12
dpsutton16:01:44

i'm still dragging ours over. i ran into some timing issues. i'm assuming we have some races in navigation now but they are working correctly. get errors on nav at the moment

thheller17:01:43

benchmarking JS is extremely tedious ... anyone know of tools to automate this better?

thheller17:01:27

I'm trying to setup a system that runs various shadow-cljs+CLJS combinations through a benchmark suite and collect the results

thheller17:01:58

so I can compare and track runtime perf and maybe compile perf over time

thheller17:01:40

I've made one rather big change and I want to test if thats actually worth performance wise

thheller17:01:45

;;; fn invoke
{:standardDeviation 0.023446214753117665, :bindings "[val (rand)]", :maximum 1, :total 11, :expr "(simple-fn val)", :median 0, :minimum 0, :count 20000, :average 0.00055}
{:standardDeviation 0.027376540573065246, :bindings "[val (rand)]", :maximum 1, :total 15, :expr "(simple-fn-indirect simple-fn val)", :median 0, :minimum 0, :count 20000, :average 0.00075}
{:standardDeviation 0.029143094653764887, :bindings "[val (rand)]", :maximum 1, :total 17, :expr "(simple-fn-indirect-hinted simple-fn val)", :median 0, :minimum 0, :count 20000, :average 0.00085}

thheller17:01:35

can't even get precise timing on node it seems

jeeq18:01:59

Sorry to keep bothering about something that may or may not be supported in shadow-cljs right now but I’m now trying to get the example in the docs (https://shadow-cljs.github.io/docs/UsersGuide.html#_javascript_dialects) to work in my project (expo/react-native not sure if this is the issue). example jsx I’m trying to get working:

import React from "react";

function myComponent() {
  return <h1>JSX!</h1>;
}

export { myComponent };
when I conver this jsx to js with babel as in the docs I get error message about shadow.js.shim… not being provided:
Module not provided: shadow.js.shim.module$$babel$runtime$helpers$interopRequireDefault

construct
    [native code]:0
_construct
    construct.js:30:26
Wrapper
    wrapNativeSuper.js:26:23
SyntheticError
    index.bundle?platform=ios&dev=true&minify=false&hot=false:31652:111
handleException
    ExceptionsManager.js:111:31
handleError
    setUpErrorHandling.js:23:40
ErrorUtils.setGlobalHandler$argument_0
    ErrorRecovery.fx.js:8:32
tryCatch
    runtime.js:45:44
invoke
    runtime.js:271:30
tryCatch
    runtime.js:45:44
invoke
    runtime.js:135:28
Promise.resolve.then$argument_0
    runtime.js:145:19
tryCallOne
    core.js:37:14
setImmediate$argument_0
    core.js:123:25
_callTimer
    JSTimers.js:146:14
_callImmediatesPass
    JSTimers.js:194:17
callImmediates
    JSTimers.js:458:30
callImmediates
    [native code]:0
flushedQueue
    [native code]:0
invokeCallbackAndReturnFlushedQueue
    [native code]:0
Without the import line and if I just set to return a simple number (i.e. return 2;) I’m able to use the exported module. It just seems to be confused when trying to import any modules. Any pointers?

thheller18:01:55

what did you use to convert the JSX? that is likely incorrect

thheller18:01:52

but you are using react-native anyways so you should figure out a way to let react-native compile the js files and not shadow-cljs

thheller18:01:58

then you can skip the entire babel stuff

jeeq18:01:43

just used the example on the doc but with option for transform inlined

babel --plugins @babel/plugin-transform-react-jsx src/js --out-dir src/gen

thheller18:01:50

likely that means not requiring the file via ns and instead do (def thing (js/require "../path/to/home.js"))

thheller18:01:28

and what does the generated output file look like? it looks like it rewrote ESM import to require which it should not do

jeeq18:01:10

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", { value: true });
exports.myComponent = myComponent;
var _react = _interopRequireDefault(require("react"));
function myComponent() {
  return 8;
}
This is the output from babel

thheller18:01:26

yeah it shouldn't do all the other stuff, only jsx

thheller18:01:29

I did a setup several years ago. maybe that still works? https://github.com/shadow-cljs/examples/tree/master/babel

jeeq18:01:34

I’ll try to figure out if I can turn that off and also will try requiring with js/require

jeeq18:01:09

Cool. I’ll take a look at that as well. Thank you so much!

Wilson Velez19:01:26

Hi, I have a re-frame app from which I wanted to extract some functionality, and I want to share that funcitonality with other components I have done in the past

Wilson Velez20:01:40

I’ve read that I can use lein to generate a jar, so I can do that locally, and then how can I include that generated jar in my component using shadow?

thheller20:01:50

@wvelezva I can tell how it works if your library is public/open source. otherwise you are probably better off using deps.edn and putting the files in a git repo or local folder

Wilson Velez20:01:35

@thheller ok, so I think I better use deps.edn

Wilson Velez20:01:26

but in general what I should create? a normal cljs component? I have to generate the js? or something like a jar, npm?

Wilson Velez20:01:31

or can use lein to manage my dependencies and install the component like a jar?

thheller20:01:31

you don't have to compile anything. the easiest way to share components is to just put them in their own namespace

thheller20:01:44

take the file and put them somewhere "shared"

thheller20:01:25

and then either add the path to that into your :source-paths or use lein install and add the dependency

thheller20:01:32

I'd recommend just files

thheller20:01:27

eg. you have /code/project-a/src and /code/the-library/src

thheller20:01:52

in project-a/shadow.cljs.edn you put :source-paths ["src", "../the-library/src"]

Wilson Velez20:01:36

oh, I didn’t know that was possible

Wilson Velez20:01:48

I will give it a try

thheller20:01:20

things get a bit more complicated if you want to declare dependencies in the library, at which point you should likely go with deps.edn

knubie20:01:26

Is there a recommended way of rendering images in react native? I’m using the method described in this example https://github.com/PEZ/rn-rf-shadow/blob/master/src/main/example/app.cljs#L16

thheller20:01:40

what else would there be?

knubie20:01:10

I dunno but the Metro Bundler is giving an error, so I thought there might be a different way

thheller20:01:38

I don't know but I doubt it. whats the error?

knubie21:01:11

ReferenceError: SHA-1 for file …/assets/logo.png (…/assets/logo.png) is not computed

knubie21:01:43

I think it might be that the “image is outside of my project”

thheller21:01:40

no clue. the path used must be relative to the :output-dir used in the build config

knubie21:01:01

that was it

knubie21:01:13

the image was in a directory above the react native project path