Fork me on GitHub
#shadow-cljs
<
2020-08-24
>
bbss05:08:39

Okay, checking! 🙂

superstructor06:08:13

Thanks for the fix @thheller That release builds re-frame fine. Just to confirm does this change the table in the docs at https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages ?

thheller07:08:54

@superstructor it changes the table for import inside .js files on the classpath. CLJS remains the same.

superstructor09:08:25

Thanks for the clarification :thumbsup: @thheller

rickmoynihan10:08:39

What is the easiest way to require and instrument spec namespaces/functions in development mode?

rickmoynihan10:08:44

set the spec ns as a preload?

rickmoynihan10:08:36

then call (s/instrument) at the bottom of that ns/top-level?

thheller10:08:39

the trouble with instrument is that it is a macro and only instruments things that have been compiled by the type it is called

thheller10:08:02

so if you put it in a preload that ns also needs to require all namespaced its supposed to instrument

thheller10:08:10

but that works yes

rickmoynihan10:08:10

I think I can do that here… It does mean the specs won’t be in my app at all; but I’m keeping the namespaces separate right now, so they need to be included at the root.

thheller10:08:26

if you are on a recent version you can get fancy and do

(def ^:dev/after-load instrument-everything []
  (js/cljs-eval "(cljs.spec.alpha/instrument)"))

thheller10:08:43

since the eval happens after all compilation finishes it will see everything

thheller10:08:17

or maybe

(def ^:dev/after-load-async instrument-everything [done]
  (-> (js/cljs-eval "(cljs.spec.alpha/instrument)")
      (.then done)))

thheller10:08:04

I also added :build-options {:auto-require-suffixes #{"-spec"}} that will automatically add foo.bar-spec to the build if foo.bar is required

thheller10:08:43

but that doesn't solve the instrument issue needing to be called "late"

rickmoynihan11:08:55

Thanks… I seem to be getting an error: “Use of undeclared Var cljs.spec.alpha/instrument”. I have (:require [cljs.spec.alpha :as s :include-macros true]) in my ns definition

rickmoynihan11:08:19

currently calling (s/instrument) at the top level

thheller11:08:57

oh that might be in another namespace

thheller11:08:32

I think it might be cljs.spec.test.alpha. not actually sure.

thheller11:08:11

you can also do (js/cljs-eval "(require 'cljs.spec.test.alpha) (cljs.spec.test.alpha/instrument)") of course

rickmoynihan11:08:06

yeah you’re right — I thought it was wrong; but had seen something online listing it that way

rickmoynihan11:08:40

why cljs-eval it?

thheller11:08:43

eval what? the instrument or the require?

rickmoynihan11:08:11

why cljs-eval both like you have, rather than via preload?

rickmoynihan11:08:03

(If I only want them in dev mode)

thheller11:08:56

you can do the preload that is fine. if you setup your requires correctly that will work just fine

thheller11:08:09

BUT instrument is a macro so you need to realize what that means

thheller11:08:39

it will only do stuff it knows about at the time it is compiled. so it is easy to miss stuff if you don't list something or so.

thheller11:08:55

by using cljs-eval it is ensured that the macro is expanded at a time where all other compilation has finished

thheller11:08:06

you are guaranteed to get the "latest" version

thheller11:08:31

I do think that the :preloads variant is better and probably more reliable but it is more work and easy to mess up

rickmoynihan11:08:47

Yeah ok, that’s more or less what I was thinking… Essentially you’re saying the fdef’s all need to be explicitly required for them to be found, from the top of this ns, so any fdef’s required from the app’s top level would be missed.

thheller11:08:52

the fdefs need to be compiled before instrument is called yes, where from exactly doesn't really matter as long as its before

thheller11:08:33

<preload-ns> -> -> main.app-spec is fine but for example won't invalidate <preload-ns> when main.app-spec is changed and as such won't affect instrument

thheller11:08:47

unless you add :dev/always to the preload ns to always recompile

thheller11:08:59

I should really write this down somewhere. feel like I explained this before somewhere

thheller11:08:12

there are a whole lot of gotchas to watch out for but it can work fine

rickmoynihan11:08:22

what about where my.app.specs -> ?

thheller11:08:12

hmm? obvioulsy need to have my.app.specs required somewhere. if you do that in the preload that is fine, or the :auto-require-suffixes I mentioned

rickmoynihan11:08:08

yeah was thinking essentially it would just be required via the :preloads

thheller11:08:36

yes thats fine

rickmoynihan11:08:48

would I need any :dev/always or similar flags?

thheller11:08:08

if you have a instrument call in that namespace yes. otherwise while editing the code it will become "unstrumented". eg. watch compiles http://my.app and loads it so your fdef instrument is replaced

rickmoynihan11:08:39

hmm I might well switch to using :auto-require-suffixes stuff after all… will see :thinking_face:

thheller11:08:53

that doesn't solve the instrument problem though 😉

rickmoynihan13:08:34

yeah but including with ^:dev/after-load-async does right?

thheller13:08:21

it should in theory yes. never actually tried it 😛 frankly the instrument macro scares me 😛

Tuomas16:08:09

I’m recreating react material ui docs in workbooks to prove my colleagues it’s not impossibly hard. I got pretty far in one go, but ended up shutting down my computer before finishing. After I got back I was faced with a weird situation where on initial load the cards are empty but after live reload they work. The problem seems to be with my importing. I’m trying to recreate

import {
  MuiPickersUtilsProvider,
  KeyboardTimePicker,
  KeyboardDatePicker,
} from '@material-ui/pickers';
with
(ns app.mui-component (:require ["@material-ui/pickers" :refer [MuiPickersUtilsProvider KeyboardTimePicker KeyboardDatePicker]]))
having npm installed
"@material-ui/pickers": "^3.2.10",
but end up with
shadow-cljs - failed to load module$node_modules$$material_ui$pickers$dist$material_ui_pickers
  shadow.js.jsRequire @ js.js:74
  shadow.js.require @ js.js:113
  eval @ app.mui_components.js:10
  goog.globalEval @ main.js:577
  env.evalLoad @ main.js:1670
  (anonymous) @ main.js:2650
main.js:1672 An error occurred when loading app.mui_components.js
  env.evalLoad @ main.js:1672
  (anonymous) @ main.js:2650
main.js:1673 undefined
  env.evalLoad @ main.js:1673
  (anonymous) @ main.js:2650
Any tips on what to check/try/read?

Tuomas16:08:36

I’m not even sure if it’s shadow related or something completely different

thheller16:08:26

are there more errors? there should be. its just telling you what failed to load, the why you didn't paste?

thheller16:08:24

looks like you have to fix a bunch of other stuff?

👍 3
thheller16:08:06

I cannot tell what the actual error is either. my guess would be that maybe it expects a different react version?

Tuomas16:08:01

“buch of other stuff” you mean errors? If I comment out the

@material-ui/pickers
import and defs/cards/componests that end up relying on something undefined, I get no errors. When I remove the comments it’s like the whole namespace doesn’t load

thheller16:08:59

react-dom.development.js:89 Warning: componentWillReceiveProps has been renamed, and is not recommended for use. See  for details.
* Move data fetching code or side effects to componentDidUpdate.
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: 
* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.
Please update the following components: ReactGridLayout, ResponsiveReactGridLayout

thheller16:08:26

what are these? no clue if thats related to @material-ui/pickers or something else?

Tuomas16:08:23

I get that warning with and without pickers. I thought it was a Fulcro thing but I’ll try to make sure

Tuomas17:08:21

I’m sorry to let you know that it is working again, but I don’t know why. I’ll try to break it again for a while but will then move on. Thanks the replys!

3
bbss16:08:45

@thheller I'm still having trouble compiling the file:

[:main] Build failure:
Closure compilation failed with 2 errors
--- kr/models/ronde-tempel-compiled.js:7
Requested module does not have an export "createElement".
--- kr/models/ronde-tempel-compiled.js:7
Requested module does not have an export "useRef".

bbss16:08:14

With

import { useRef, createElement } from 'react'

thheller16:08:53

maybe import React, { useRef, createElement } from "react" works?

bbss16:08:00

nop, also tried

thheller16:08:08

otherwise only import React from "react" and React.useRef might work

bbss16:08:18

also tried that.. React is undefined

bbss16:08:27

shadow-cljs - server version: 2.10.13 running at 

bbss16:08:29

is that correct?

bbss16:08:59

I did install 2.11.0

thheller16:08:18

should be 2.11.0. remember to update in project.clj or deps.edn if you use either

bbss16:08:42

Checking again..

bbss16:08:12

Doh.. I thought might have been wrong version!

bbss16:08:13

Now watch build works again, but having minification issues I think, for release

cannot read property 'geometry' of undefined
;;probably for
createElement("mesh", {
    material: materials.red,

      receiveShadow: true,
      castShadow: true,
      geometry: nodes.temple_railing_top.geometry,
    name: "temple_railing_top",
    position: [0.82, 2.23, -2.03],
    rotation: [Math.PI, 0, Math.PI],
    scale: [2.61, 2.61, 2.61]
  })

bbss16:08:42

Is there a way to exclude files from minification?

bendlas16:08:34

say, I have two custom node libraries, depending on conflicting versions of d3. By default, shadow would try to resolve a single d3 version. :js-options :resolve doesn't help here either, because it just lets me choose the d3 version to resolve, correct? How to best deal with this? Should I use rollup to package the two libraries?

thheller16:08:04

@bbss if you use require and module.exports instead of import/export the file is treated as commonjs and as such does not go through :advanced

thheller16:08:18

JS code otherwise doesn't have externs inference so you could just add externs manually as well

thheller16:08:17

@bendlas shadow-cljs will not let you include 2 different versions of d3 no matter what so you have to use something different to get that yes

bbss16:08:27

awesome! working with release! thanks once again :)

👍 3
grounded_sage21:08:32

How do I run the browser tests once they are generated? I am having difficulties figuring this out from the documentation

lilactown21:08:15

the :browser-test build is meant to be opened in a browser. it should generate an html file as part of its output that you can open

grounded_sage21:08:50

How do you open it?

lilactown21:08:50

point chrome to where the file is being served by shadow-cljs web server

lilactown21:08:08

here’s an example of our config for it:

:test {:target :browser-test
                 :test-dir "resources/public/test"
                 :ns-regexp "-test$"
                 :compiler-options {:language-in :es6
                                    :output-feature-set :es6}
                 :devtools {:http-port 8021
                            :http-root "resources/public/test"}}

lilactown21:08:40

while the test watch is running

grounded_sage21:08:05

hmm. I get a bunch of errors when I do shadow-cljs watch test

grounded_sage21:08:05

Okay smaller library trying this out works. But I don’t see the results of the tests. Where are they printed?

lilactown21:08:45

in the browser

grounded_sage21:08:18

I have this in the console. env.cljs:187 error when calling lifecycle function shadow.test.browser/start Error: Assert failed: cljs-test-display: Element with id "test-root" does not exist.

lilactown21:08:25

try adding that html element to the index.html in test-dir

lilactown21:08:39

<div id="test-root" />

grounded_sage21:08:32

Okay that worked

grounded_sage21:08:48

Seems that this needs to be generated with the file.

thheller21:08:16

:browser-test should generate the index.html if it doesn't exist

thheller21:08:26

if you re-use a folder and it does exist it may not do the right thing

grounded_sage22:08:14

Yea I just tried on another project and it generated things properly. :man-shrugging:

grounded_sage22:08:51

I’ve literally been going down a rabbit hole trying to figure out why the test runner wasn’t working with Kaocha. Tracing problems in the code but it was actually the runner. shadow-cljs to the rescue again 🙇

bendlas22:08:08

I just ran into a problem, where I'm not sure if it's about shadow or the closure compiler: A node module, accessing process, hence triggering shadow's automatic require('process'), got moved by the closure compiler into a common base module, where it then failed to require process. But only in production mode.

bendlas22:08:40

Solution was to explicitly move the node module into the common sub module

thheller22:08:07

closure doesn't move JS requires. in fact it doesn't even see them?

bendlas22:08:28

yes, the js require had been rewritten to a shadow require at that point, but the module wasn't found. I suspect that, since the require('process') is added by shadow, it might have added the shadow$provide for process too late, because it didn't know about the require being cross-module moved, or something. If it's not obvious to you from the description, I can try to condense a test case ....

benny23:08:27

cross-posting this to see if there’s a way to do this with cljs

Pavel Klavík23:08:43

Hi, is this guide still up-to-date: https://code.thheller.com/blog/shadow-cljs/2019/03/03/code-splitting-clojurescript.html? If I want to split a large component in my Re-frame app into a separate module, I will add events, subscriptions and views namespaces into this module and load view by lazy-load as in the example? How do I load subscriptions and events namespaces? Should I add them to the main view namespace?