Fork me on GitHub
#shadow-cljs
<
2018-03-15
>
p-himik13:03:09

I'm trying to migrate to shadow-cljs, but I keep getting this error:

module.js:478
    throw err;
    ^

Error: Cannot find module '@cljs-oss/module-deps'
    at Function.Module._resolveFilename (module.js:476:15)
    at Function.Module._load (module.js:424:25)
    at Module.require (module.js:504:17)
    at require (internal/module.js:20:19)
    at [eval]:3:13
    at ContextifyScript.Script.runInThisContext (vm.js:25:33)
    at Object.runInThisContext (vm.js:97:38)
    at Object.<anonymous> ([eval]-wrapper:6:22)
    at Module._compile (module.js:577:32)
    at evalScript (bootstrap_node.js:351:27)
Does anyone have any idea on what may be causing it? My package.json:
{
  "devDependencies": {
    "shadow-cljs": "^2.2.9"
  },
  "dependencies": {
    "create-react-class": "^15.6.2",
    "react": "^15.6.2",
    "react-dom": "^15.6.2"
  }
}

hlolli13:03:30

ok I can't write, lol my slack client is really screwing with me

p-himik13:03:57

Oh wow. 🙂 Yes, I've those steps.

p-himik13:03:26

BTW, I'm using it with :lein true.

hlolli13:03:11

shouldn't matter, I get the same errors when a module is not in node_modules dir, is this module there at all?

p-himik13:03:51

There're shadow-cljs and shadow-cljs-jar dirs.

hlolli13:03:45

ok this is not a shadow-cljs dependency https://github.com/thheller/shadow-cljs/blob/master/packages/shadow-cljs/package.json#L30-L38 so you'll have to add this yourself, maybe you have cljsjs dependency that needs cljs-oss/module-deps.

hlolli14:03:08

unrelated question, does it say on the bottom hlolli is typing?

hlolli14:03:44

I forward this to thheller, I have a working shadow-cljs project and the folder (at)cljs-oss is not in my node_modules, so sounds strange.

p-himik14:03:59

Do you use :lein true?

hlolli14:03:10

ah ok, this may be related since this is dependency module

p-himik14:03:39

Interesting. I just used re-frame-template and modified the generated project to use shadow-cljs. The shadow-cljs.edn files do not differ between two projects. But the build for my main project starts with

Compiling ClojureScript...
Compiling ["frontend/static/js/main.js"] from ["frontend/cljs"]...
Options passed to ClojureScript compiler: {... A large map of options...}
[... the aforementioned error ...]
whereas the build for the generated project starts with
shadow-cljs - server running at 
shadow-cljs - watching build :dev
[:dev] Configuring build.
[:dev] Compiling ...

hlolli14:03:29

I guess you'd only want to start leiningen for clojure (backend) stuff and leave the rest to shadow-cljs, icludeing removeing the cljsbuild from the leiningen plugins

p-himik14:03:25

Actually, I don't even use Clojure, I use Python. 🙂 I just wanted to try to migrate my project to shadow-cljs with the smallest cost possible.

hlolli14:03:53

ok, then use python to serve the output directories, you'll still get the hot-reload from shadow-cljs, if there's no clojure code involved, you don't really need leiningen anywhere.

p-himik14:03:42

Hmm, in the main project I have these lines:

;; to clean JS files generated during the build
  :hooks [leiningen.cljsbuild]
Removing the last one also removes the error, which of course surfaces a whole bunch of other errors. But they should be fixable.

p-himik14:03:26

Yeah, I'm thinking about dropping lein altogether.

hlolli14:03:07

Yes, shadow-cljs alone is capable of doing all the cljs tooling you would need.

thheller15:03:11

@p-himik yeah I'd advice dropping lein if you don't need clojure. the @cljs-oss/module-deps is not from shadow-cljs and must be coming from something in lein-cljsbuild

p-himik15:03:27

@thheller Yeah, I plan to give it a go today or tomorrow. Thanks.

mhuebert15:03:57

@thheller re: circleci, do you know if the issue with :jvm-opts being passed down is a shadow issue or a deps issue?

thheller15:03:38

@mhuebert shadow-cljs only. I can add that now.

mhuebert15:03:00

cool, not a big rush, memory usage for my builds must be borderline because it works ~50% of the time. or maybe it depends on whether I’m sharing the instance with a crypto miner 💀

mhuebert15:03:16

i don’t know if they eat memory or just cpu

thheller15:03:17

well. I'm not sure if you can specify those via deps.edn

thheller15:03:39

depends on the miner I think. some are memory bound some are cpu bound.

mhuebert15:03:38

it looks like i can put jvm opts under an :aliases key

thheller15:03:17

right I was looking for that

mhuebert15:03:26

would i need to also put that in shadow-cljs.edn, or does shadow run itself ‘under’ clojure

thheller15:03:55

if you use :deps it will run via clojure

thheller15:03:20

probably a good idea to create a :ci profile for that option

thheller15:03:58

I should be able to easily pass :jvm-opts along from shadow-cljs.edn though

thheller15:03:03

just forgot about it

mhuebert15:03:59

hm I got a memory error again, after adding :aliases {:jvm-opts ["-Xmx2G"]}

mhuebert15:03:24

this is what i run to start the thing:

npx shadow-cljs clj-run maria.build/release;
shadow-cljs - config: /home/circleci/project/editor/shadow-cljs.edn version: 2.2.9
shadow-cljs - starting via "clojure"

thheller15:03:31

you need to create an alias and activate it

thheller15:03:51

:aliases {:ci {:jvm-opts ["-Xmx2G"]}} and shadow-cljs -A:ci

thheller15:03:21

hang on I just added the fix so jvm-opts get passed along from shadow-cljs.edn

mhuebert15:03:51

great, just had a maria build succeed w/ that option

p-himik15:03:16

Suppose one project (say, reagent) depends on something from cljsjs (say, react). It has some particular version specified there. Is there any way to automatically update this version in package.json when the project updates its dependencies?

thheller16:03:02

@p-himik cljsjs is not supported in shadow-cljs. npm is always used but no it is not synced until reagent starts declaring its react dependency via deps.cljs :npm-deps. I believe it started doing that in the latest alphas.

p-himik16:03:53

I see, thanks.

p-himik17:03:02

It's working! But I see some errors like Use of undeclared Var re-frame.cofx/kind. The mentioned vars vary, but they all exist when I check. What could cause these warnings? We don't need to (:require [some.thing]) in order to write some.thing/foo, do we?

thheller17:03:55

you do need to unless you like fun and undefined behaviour

thheller17:03:40

the :require ensures that things get compiled in the correct order. without the require a namespace might be compiled before its dependency leading to those kinds of warnings

p-himik17:03:30

Interesting. I can't find any documentation on mentions without requiring, but I've seen a ton of examples from which I've learned.

thheller17:03:36

shadow-cljs is a bit stricter for those things because of the more aggressive caching and parallel compilation by default

thheller17:03:01

references without require are always a bad idea and should never be done

thheller17:03:26

should never be done in files. its fine for the REPL.

p-himik17:03:14

> parallel compilation by default So one doesn't have to specify :parallel-build true? Or is it something different?

thheller17:03:45

no setting necessary. enabled by default.

thheller17:03:16

in fact you probably don't need ANY of the usual CLJS configuration

p-himik17:03:57

:external-config and :closure-defines are still probably needed.

thheller17:03:01

:external-config is dangerous with caching. handle with care. :closure-defines not needed if all you set is goog.DEBUG but otherwise yes

p-himik17:03:53

I use only :devtools/config and :dirac.runtime/config in :external-config. Should be fine, right?

thheller17:03:35

to be safe keep it in :dev {:external-config ...} so it doesn't apply to release builds

p-himik17:03:59

I think it should be :dev {:compiler-options {:external-config ...}}.

thheller17:03:21

ah right. yes.

p-himik18:03:56

I think the final bit in my project is to make dirac work. In project.clj I have :repl-options {:init (do (require 'dirac.agent) (dirac.agent/boot!))}. Is it possible to have something like that with shadow-cljs? I found this in the documentation: "When enabled the watch will also hot-reload your code and provide a REPL." However, the link on "enabled" just goes to "Development Options" section that doesn't say anything about REPL.

p-himik18:03:34

OK, now I'm starting to think that I will still have to use Leiningen. Because otherwise: 1. Apparently I won't be able to have some code being run automatically on nREPL connection 2. Cursive won't fetch any dependencies (or I'll have to generate pom.xml each time shadow-cljs.edn is changed) 3. I won't be able to use Leiningen plugins (e.g. lein-environ) and tools (e.g. lein ancient)

p-himik18:03:03

Also, attempting to use dirac prints out something interesting:

[3:0]~shadow.user=> (dirac.agent/boot!)
#object[clojure.core$future_call$reify__8097 0x79c9b171 {:status :pending, :val nil}]
[3:0]~shadow.user=> -----------------------------------------------------------------------------------------------------------
[3:0]~shadow.user=> WARNING!
We detected unexpected middleware setup in your nREPL server at !
The difference (clojure.data/diff expected-ops reported-ops) is:
[nil
 [nil nil nil nil nil nil nil nil nil nil :cljs/select]
 [:clone
  :close
  :describe
  :dirac-devtools-request
  :eval
  :identify-dirac-nrepl-middleware
  :interrupt
  :load-file
  :ls-sessions
  :stdin]]

For reference, the reported versions by the nREPL server are:
{:clojure "1.9.0", :java "1.8.0_151", :nrepl "0.2.13"}

This usually happens when some extra middleware gets injected into your nREPL server behind your back.
e.g. * Didn't you include a middleware via ~/.lein/profiles.clj or BOOT_HOME/boot.properties?
     * Or maybe using Cider's nREPL stuff?
     * Or maybe using some combination of ancient Clojure/Java versions?
     * Or some bleeding-edge alpha versions?
     * Or a rogue tools.nrepl dependency in your project or its dependencies?

Please follow Dirac installation instructions: .
-----------------------------------------------------------------------------------------------------------
I guess shadow-cljs injects :cljs/select, right?

darwin19:03:23

@p-himik should be harmless, you should be able to suppress that warning by passing a config overrides into boot!: (dirac.agent/boot! {:skip-dirac-nrepl-middleware-check true}) or something like that

colindresj20:03:41

How would one fully qualify a JS dependency when writing a macro?

thheller20:03:15

@colindresj I have been thinking about that but the best solution right now is to create a helper fn in your cljs ns that calls the JS code and call that from the macro

colindresj20:03:27

Ok, that’s what I thought

thheller20:03:11

problem is that the JS namespace can change if filenames change or :browser vs :node-script

colindresj20:03:04

Yeah, I was look at the compiled source and the references didn’t seem reliable

colindresj20:03:20

Don’t think a helper is the end of the world

thheller20:03:29

you can get to it via the compiler env but I cannot guarantee that that won't change over time. so better stick with the helper fn for now

thheller20:03:15

@darwin how come you are checking the nrepl middleware?

darwin20:03:30

@thheller that is just a sanity check, people had weird issues when running some other middleware alongside dirac’s, just a warning

darwin20:03:03

I might relax that check and check only against white-listed middleware which is known to be “compatible”

kenny20:03:22

Just updated to shadow-cljs 2.2.10 and after first run I am receiving this error: https://pastebin.com/r0wteDyJ. Feels like a dependency issue but unsure. I am using ClojureScript 1.9.946.

thheller20:03:26

@kenny use [org.clojure/clojurescript "1.10.145"] thats the version now used by shadow-cljs. if you want to continue using 946 you must downgrade the closure compiler

kenny20:03:51

Gotcha. Is there a compatibility table that has this info? Also, do you know if that is a stable release? The CLJS github doesn't have any visible info on that version.

thheller20:03:01

technically you shouldnt worry about which cljs version you are using and just depend on the one shadow-cljs "ships"

thheller20:03:47

what we are using is stable yes

thheller20:03:02

there wasn't an official release yet since lots of the new stuff they were working on is not stable

thheller20:03:08

but we are not using that so it doesn't matter

thheller20:03:56

got impatient with the upgrade since I wanted to finally sort out the java9 issues

thheller20:03:12

upgraded to the pre-release pretty much for that reason

kenny20:03:33

While I'm here, ever since switching to shadow-cljs I receive this warning in the console:

Warning: It looks like you're using a minified copy of the development build of React. When deploying React apps to production, make sure to use the production build which skips development warnings and is faster. See  for more details.
How do you include React in your builds? Right now it's just in my package.json under dependencies.

kenny20:03:48

... for dev.

thheller20:03:28

yeah ignore that warning. everything is fine. react is just being annoying.

thheller20:03:49

it goes away when doing a release build

kenny20:03:55

It makes it sound like I should not be using a minified dev build of React when developing.

thheller20:03:16

no the warning is there to protect users from using the dev version in production

kenny20:03:45

And the best solution is to always send a warning during development? 🙂

thheller20:03:40

nah their detection is just flawed

thheller20:03:02

been meaning to bug them about that

thheller20:03:26

unfortunately due to their annoying packaging there is no way to get rid of the warning if you want to use the dev version

thheller20:03:36

if you always want to use the production version there is a way

thheller20:03:51

but some of there debug messages are pretty helpful so I'd rather keep them

kenny20:03:53

Unrelated note: Is there a way to get shadow-cljs to spit out the nrepl port into the same file leiningen uses so Cursive can work with the REPL? Right now I have to statically set the REPL port.

kenny20:03:14

I haven't found a way in Cursive to set the nrepl port file to something other than the default -- .nrepl-port at the root directory.

thheller20:03:44

yeah I have been hesitant to write to that file since it belongs to lein and I don't want to get in its way

thheller20:03:08

guess I could just write it if it doesn't exist

kenny20:03:01

Makes sense. Perhaps a config option to specify the REPL port file?

thheller20:03:34

well as you said there is no way to configure cursive to use a different file

kenny20:03:16

I mean in shadow-cljs. I'd think that If I explicitly specify shadow-cljs to write to .nrepl-port then it becomes my problem if that interferes with lein.

thheller20:03:16

maybe I can talk Colin into looking at other files now that shadow-cljs is gaining popularity

mhuebert21:03:38

hmm

[2018-03-15 22:55:34 - SEVERE] spark/util/mongoose-types/lib/plugins/useTimestamps.js:1: ERROR - Invalid module path "goog:shadow.js.shim.module$mongoose" for resolution mode "BROWSER"
var mongoose = require('goog:shadow.js.shim.module$mongoose')
this is supposed to be a :node-script, but this error says ‘resolution mode “BROWSER”’

thheller22:03:06

BROWSER is the resolution mode for the closure compiler, we always use that since the others are just flat out broken

thheller22:03:43

are you compiling .js files with shadow-cljs?

thheller22:03:40

I mean outside node_modules?

mhuebert22:03:42

that was a cljs file attempting to require via a module via a relative path, which itself requires stuff from node_modules

thheller22:03:24

yeah that is currently only works for ES6 files

thheller22:03:33

commonjs is busted because of the closure compiler

mhuebert22:03:47

ie. in my-namespace ["./util/mongoose-types" :as mongoose-types], and then in ./util/mongoose-types/ it requires other stuff

thheller22:03:10

the file has var mongoose = require('mongoose') which shadow-cljs replaces with the goog:shadow.js.shim.module$mongoose

thheller22:03:35

which the closure compiler in turn just replaces with var mongoose = shadow.js.shim.module$mongoose so all is good in the world

thheller22:03:03

for ES6 that is .. for commonjs it doesn't process the goog: part

thheller22:03:15

I have not figured out how to solve this without everything breaking

thheller22:03:38

import mongoose from "mongoose" should work just fine

mhuebert22:03:15

I can use ordinary nodejs/require, using js/__dirname and relative paths

mhuebert22:03:54

well let’s see

thheller22:03:38

unfortunately not

thheller22:03:15

well if you manually copy the .js files into the :output-to folder

thheller22:03:40

with js/require they won't get copied from the source paths

thheller22:03:10

hmm just thought of something. might be able to trick GCC