Fork me on GitHub
#shadow-cljs
<
2021-09-14
>
caleb.macdonaldblack00:09:03

Do preloads work in ~/.shadow-cljs/config.edn?

thheller04:09:43

no, build configs are not supported there. what kind of preload do you have in mind?

caleb.macdonaldblack23:09:34

A coworker is using reframe 10x but I dislike it because my app-db output in the chrome console is no longer sorted. A solution I’ve thought of is two seperate builds.

thheller05:09:22

one option would be shadow-cljs watch app --config-merge '{:devtools {:preloads [foo.bar]}}' or using the clojure API to start things

thheller05:09:33

then you can modify everything to your liking

ingesol07:09:47

@thheller Sorry for the confusion, turns out I was calling my build with the wrong alias, reloading on :local/root works great

West09:09:23

How do I interpret this error?

Execution error (TypeError) at (<cljs repl>:1). shadow.js.shim.module$unified.unified is not a function
Here’s a sample of the source.
(ns app.org-parser
  (:require ["unified" :as unified]
            ["rehype-stringify" :as html]
            ["uniorg-parse" :as uniorg]
            ["uniorg-rehype" :as rehype]
            ["rehype-raw" :as raw]
            ["uniorg-extract-keywords" :refer [extractKeywords]]
            shadow.resource))

(def ^:private processor
  (.. (unified)
      (use uniorg)
      (use extractKeywords)
      (use rehype)
      (use raw)
      (use html)))
Is there something wrong with unified such that I can’t import it? I also tried using js/require but that didn’t work either.
require() of ES Module /Users/main/Code/clojure/mysite/node_modules/unified/index.js from /Users/main/Code/clojure/mysite/[stdin] not supported.
Instead change the require of index.js in /Users/main/Code/clojure/mysite/[stdin] to a dynamic import() which is available in all CommonJS modules.

borkdude09:09:40

@c.westrom If you want to use ES modules in your project, it might be best to compile your project itself as an ES module.

borkdude09:09:07

Note that you will likely also have to change your import to "unified$default" :as unified after switching

borkdude09:09:49

@c.westrom There are currently no docs for the :esm target, but you can read about it here: https://clojureverse.org/t/generating-es-modules-browser-deno/6116

West09:09:22

@borkdude Ok, I'll try and see if it still works in the browser.

borkdude09:09:29

@gnhuy91 also recently used it, perhaps he also has some pointers

huygn09:09:12

yea it works on the browser if you use script type="module"

huygn09:09:36

which is cool, then you can fully dance with the whole esm/deno ecosystem, downside is old browsers compat, but who cares 🤷 we had that curse for a decade already, time to get moving

borkdude09:09:07

I hope Github also moves to Node 14 or 16 for their action runners, then I can finally use nbb (ESM) for that

clojure-spin 2
huygn09:09:20

ooh so esm is from node 14? I thought node 16

borkdude09:09:44

12 already supports it but their action runner doesn't use the appropriate --experimental flag

borkdude09:09:45

$ nbb -e 'js/process.version'

"v12.22.6"

awesome 2
borkdude09:09:31

so I'm actually not sure what the problem is with the Github action runner: I think they're using an even older 12 version

West09:09:01

Well, it seems like :target :esm as an option works in the browser just fine, I’m still getting the same errors when trying to use unified though.

borkdude09:09:28

@c.westrom what error are you getting. Did you use script type="module" as well?

borkdude09:09:47

Also "unified$default" :as unified

West09:09:44

Ah, forgot about $default again, but after adding I get this now.

------ REPL Error while processing ---------------------------------------------
(cljs.core/load-file "/Users/main/Code/clojure/mysite/src/app/org_parser.cljs")
------ REPL Error while processing ---------------------------------------------
(ns app.org-parser
  (:require ["unified$default" :as unified]
            ["rehype-stringify" :as html]
            ["uniorg-parse" :as uniorg]
            ["uniorg-rehype" :as rehype]
            ["rehype-raw" :as raw]
            ["uniorg-extract-keywords" :refer [extractKeywords]]
            shadow.resource))
In :require [shadow.js.shim.module$unified$default :refer (unified)] already used by [shadow.js.shim.module$unified :refer (unified)]

West09:09:21

I did update my index.html with type="module" in the script tag.

borkdude09:09:42

ok, I think you're on the right track

borkdude09:09:10

perhaps just start with only that require

borkdude09:09:16

and then gradually add more

borkdude09:09:48

you might have some stale cache or so

borkdude09:09:59

restart your shadow process, clean .shadow-cljs

borkdude09:09:46

@c.westrom I think you will also need to add $default to the other requires btw

West09:09:51

Ok, heavily stripped it down

(ns app.org-parser
  (:require ["unified$default" :as unified]
            #_["uniorg-parse$default" :as uniorg]
            #_["uniorg-rehype$default" :as rehype]
            #_["rehype-stringify$default" :as html]
            #_["rehype-raw$default" :as raw]
            #_["uniorg-extract-keywords" :refer [extractKeywords]]
            ;;shadow.resource
            ))
Here’s the result.
Execution error (TypeError) at (<cljs repl>:1).
shadow.js.shim.module$unified$default is not a function
Looking at the source for unified, it isn’t labeled as a default export, just an export.
export const unified = base().freeze()

borkdude09:09:44

Can you try "unified$unified" ?

West09:09:25

------ REPL Error while processing ---------------------------------------------
(cljs.core/load-file "/Users/main/Code/clojure/mysite/src/app/org_parser.cljs")
------ REPL Error while processing ---------------------------------------------
(ns app.org-parser
  (:require ["unified$unified" :as unified]
            #_["uniorg-parse$default" :as uniorg]
            #_["uniorg-rehype$default" :as rehype]
            #_["rehype-stringify$default" :as html]
            #_["rehype-raw$default" :as raw]
            #_["uniorg-extract-keywords" :refer [extractKeywords]]
            #_shadow.resource
            ))
In :require [shadow.js.shim.module$unified$unified :refer (unified)] already used by [shadow.js.shim.module$unified$default :refer (unified)]

borkdude09:09:35

this is a REPL error I think

borkdude09:09:41

just re-start the process

West09:09:58

restarting…

borkdude09:09:55

I'll also try unified from nbb

West09:09:47

cljs.user> (ns app.org-parser
             (:require ["unified$unified" :as unified]
                       #_["uniorg-parse$default" :as uniorg]
                       #_["uniorg-rehype$default" :as rehype]
                       #_["rehype-stringify$default" :as html]
                       #_["rehype-raw$default" :as raw]
                       #_["uniorg-extract-keywords" :refer [extractKeywords]]
                       #_shadow.resource
                       ))
nil
Execution error (TypeError) at (<cljs repl>:1).
shadow.js.shim.module$unified$unified is not a function
again

borkdude09:09:09

$ nbb -e '(ns foo (:require ["unified$unified" :as u])) (.log js/console u)'
[Function: processor] {
  data: [Function: data],
  Parser: undefined,
  Compiler: undefined,
  freeze: [Function: freeze],
  attachers: [],
  use: [Function: use],
  parse: [Function: parse],
  stringify: [Function: stringify],
  run: [Function: run],
  runSync: [Function: runSync],
  process: [Function: process],
  processSync: [Function: processSync]
}

borkdude09:09:21

did you npm install unified?

West09:09:32

yarn add but I think that’s effectively the same

borkdude09:09:15

is this really all the source you have or are you using unified somewhere?

West09:09:29

the workaround I had to do before, was compile a separate program as a node script and then import the compiled script for my site

borkdude09:09:49

that workaround shouldn't be necessary for :esm

borkdude09:09:53

@c.westrom Perhaps you can make a tiny repository on Github with this code

borkdude09:09:59

for us to try locally

West09:09:20

https://github.com/wildwestrom/mysite/tree/develop I was just thinking of that. I’ll make a minimal one though.

West10:09:27

Execution error (TypeError) at (<cljs repl>:1).
shadow.js.shim.module$unified$unified is not a function
Ok, minimal project here: https://github.com/wildwestrom/minimal-unified-troubleshooting

borkdude10:09:34

@c.westrom I am seeing: > Holy fuckeroni, is this working? I guess it is if you can see it.

borkdude10:09:02

after: > npx shadow-cljs compile app and then serving the HTML in a local server

West10:09:13

yep, but in the repl is where I encounter problems

borkdude10:09:20

how do you start the REPL?

West10:09:51

cider-connect-cljs in emacs. I don’t know what the equivalent is in your editor.

West10:09:17

So yarn start then cider-connect-cljs.

borkdude10:09:43

Ah screw the cljs-repl, I'm just using npx shadow-cljs watch app

borkdude10:09:03

The CLJS REPL is such a pain that I've stopped using it ages ago

borkdude10:09:20

unless I'm in node, then I use a very minimal (require 'foo :reload) workflow

borkdude10:09:39

but at this point, we've demonstrated that your ES module works. The rest is a tooling problem, either downstream or in shadow itself.

borkdude10:09:53

So at this point, I would say: take it up with @thheller or otherwise

West10:09:13

Alright, imma update the example. Also, here’s the separate script I made as a workaround: https://github.com/wildwestrom/uniorg-util

borkdude10:09:33

@c.westrom is this just for command line invocation?

West10:09:13

It’s probably way more trouble than I needed to go through.

borkdude10:09:41

cool. I think it would be a nice challenge to make this project work with #nbb as that is kind of the niche of what it's for: making scripts/CLIs with interop for node

borkdude10:09:16

I'll make an issue for that and see how far I'll get with that

West10:09:57

awesome! :thumbsup: and thanks for all the help so far @borkdude

roman01la11:09:37

👋 is it technically possible to reduce code splitting setup to Webpack’s Dynamic Imports experience (https://webpack.js.org/guides/code-splitting/#dynamic-imports) i.e. import("./file.js")? Basically removing configuration step in build config. I was thinking about something like a macro that would inject modules configuration into shadow’s build state, not sure if it makes sense. cc @dazld

clojure-spin 2
huygn11:09:56

maybe unrelated but I've recently tried import(..) within script type="module" to lazy-load a shadow-cljs module. (context is to load new react page component then render after url change) Currently hitting an issue where such import will download a shared module again, so if home & about module both depends on shared module then both imports will trigger shared module download. Which leads to duplicated cljs namespace error or even React error due to different React/ReactDOM instance kind of thing.

huygn12:09:49

for your idea, I'd love see it happens 🙏 having to explicitly specify split modules is quite verbose imo, (although I think it can somehow achievable with a script that pass merge option to shadow-clja cli)

roman01la12:09:40

I think that effortless code splitting has an important side effect in developer engagement and reduced maintenance cost. If the tool encourages code splitting then it’s more likely that engineers would develop features in a way that defers code to later. An example would be not only splitting by route/page, but by particular component or feature that it not immediately accessible

borkdude12:09:14

@U0FR82FU1 FWIW I've also adopted this approach in #nbb: I lazily load code-splitted modules on demand, e.g. when someone requires reagent.core I lazily load the reagent module using js/import. I don't understand what you need from shadow since this is already supported?

huygn13:09:16

I think he means to perform code split without having to declare modules in shadow-cljs edn confile file

thheller14:09:22

this is mostly a problem since the closure-compiler doesn't support it (yet)

thheller14:09:59

in theory this can work but I believe the result is always worse than properly setting up your modules manually

thheller14:09:17

its not that complicated and it won't just magically make an app work that isn't designed for it

thheller14:09:13

there are limits to automatic splitting and you can often end up with many tiny modules which actually load slower due to the cascasding requests requiring to load them (a loads b loads c loads d etc)

thheller14:09:18

also :advanced can do so much more with static information

thheller14:09:32

FWIW if you start with https://clojureverse.org/t/shadow-lazy-convenience-wrapper-for-shadow-loader-cljs-loader/3841 you can write your code as-if you had this magic import thing and then at a later point worry about organizing your modules and tweaking them until happy

clojure-spin 2
thheller14:09:59

since that helper hides the actual module names and lets you focus on namespaces instead

thheller14:09:23

totally fine to start with one module and go from there (and adjust later)

rosado12:09:42

I have a react-native app and I'm trying to introduce dynamic module loading, but keep hitting "shadow.loader API was called before shadow.loader.init!" error. I tried calling init, but it didn't change anything. Is there a particular place the init should happen?

thheller14:09:59

@rosado you cannot use the shadow.loader with react-native at all. metro needs to handle the loading

thheller14:09:16

so you use js/require to load modules

thheller14:09:03

shadow.loader only works in a browser environment, not react-native

thheller14:09:30

I don't have a clue whether the js/require is actually dynamic though. I don't use react-native and don't know what the situation there is

Chase19:09:05

I want to have my public folder in a resources directory but whenever I make that switch my backend messes up. It says that foo is not defined in foo.core.main() portion of the js script in my index.html. What I changed in my shadow-cljs.edn file was the :output-dir to "resources/public/js" instead of "public/js" , the :asset-path to "/public/js" instead of "/js" and the :http-root to "resources/public" instead of "public" .

Chase19:09:23

shadow-cljs watch app still works as expected with those changes

thheller19:09:49

your asset path needs to be "/js" since that is the path to access the actual files over http

Fredrik Andersson19:09:30

I'm trying to understand how I would :require npm package firebase: 9.0.1 in my code. I have tried multiple versions of "firebase/app" with :as :default and :refer. Compiler say [BABEL] Note: The code generator has deoptimised the styling of "node_modules/@firebase/firestore/dist/index.esm2017.js" as it exceeds the max of "500KB". And I get error in chrome saying shadow-cljs - failed to load module$node_modules$$firebase$app$dist$index_esm2017

thheller19:09:42

@fredrik245 impossible to answer without more info

Fredrik Andersson19:09:56

what info do you need?

thheller19:09:56

like what other errors do you get in the browser console?

thheller19:09:09

what is your build setup? why do you get a babel error?

Fredrik Andersson19:09:51

:client {:target :browser :output-dir "dist/client/js" :asset-path "js" :modules {:main {:entries [percap.client.core]}} :devtools {:before-load percap.client.core/stop :after-load percap.client.core/start :http-root "dist/client" :http-port 8022}}

thheller19:09:54

upgrade shadow-cljs to fix that one

thheller19:09:33

just for future reference the important errors here were the red actual errors. the yellow one is just a warning and useful for diagnosis but not the actual error 😛

👍 2
Fredrik Andersson21:09:56

however the red errors didn't tell me much other then there is an error

Fredrik Andersson21:09:21

but it works now. So I am happy 😃