Fork me on GitHub
#shadow-cljs
<
2019-09-02
>
dazld06:09:09

hey! I can see that shadow puts the nrepl port into a file called .shadow-cljs/nrepl.port - is there anyway to get cursive to pick this up automatically?

dazld06:09:28

https://github.com/dazld/frontend-playground < I’ve put together some boilerplate and wanted to update the readme

David Pham16:09:22

Is there a guide to integrate Dirac to shadow-cljs?

darwin16:09:22

@neo2551 no, AFAIK, I’d like to look into it

darwin16:09:15

I guess, we will need something like this: https://github.com/binaryage/dirac/blob/master/examples/figwheel-main/src/repl/dirac_figmain/repl.clj, run shadow-cljs nREPL server, start there Dirac Agent and teach dirac middleware to understand shadow-cljs internals

👍 12
joshkh17:09:53

i'm attempting to use react-bootstrap with shadow-cljs and i'm seeing a weird behaviour. loading the compiled js in the browser throws an exception [1] only on the first load and nothing is rendered, and then any subsequent hot-reload renders the button just fine. can anyone seem what i'm doing wrong? 🙂

(ns myproject.views
  (:require
    [reagent.core :as r]
    ["react-bootstrap" :refer [Button]]))

(defn home-panel []
  (fn []
    [(r/adapt-react-class Button) {:variant "primary"} "Test 1"]))
[1]
Uncaught TypeError: (0 , _uncontrollable.default) is not a function
    at Object.shadow$provide.module$node_modules$react_overlays$Dropdown (Dropdown.js:306)
    at shadow.js.jsRequire (js.js:63)
    at Object.shadow$provide.module$node_modules$react_bootstrap$Dropdown (Dropdown.js:19)
    at shadow.js.jsRequire (js.js:63)
    at Object.shadow$provide.module$node_modules$react_bootstrap$index (index.js:84)
    at Object.shadow.js.jsRequire (js.js:63)
    at Object.shadow.js.require (js.js:97)
    at myproject.views.js:6

thheller18:09:28

@joshkh I suspect that you have a dependency conflict somewhere

thheller18:09:40

check if the node_modules/react-bootstrap/node_modules folder exists

thheller18:09:45

and if so which dependencies are in it

joshkh18:09:11

looking at the node_modules/react-bootstrap/node_modules/package.json i do see some potential conflicts, mainly react and react-dom which i have in my own root package.json. how might i go about resolving dependency conflicts? in figwheel land i would use a combination of :excludes and top level dependencies.

thheller18:09:37

uhm that isn't what I asked

thheller18:09:53

node_modules/react-bootstrap/node_modules/package.json this shouldn't even exist?

thheller18:09:10

did you mean node_modules/react-bootstrap/package.json ?

joshkh18:09:30

ah sorry, long day at work. there is no node_modules directory in node_modules/react-bootstrap.

thheller18:09:43

when npm installs a package with a dependency conflict it installs conflicts in a nested node_modules directory

thheller18:09:05

so that package didn't have any conflicts, its deps may still have though

thheller18:09:17

I forgot what the npm command for this was

thheller18:09:11

npm list or something

joshkh18:09:23

okie dokie, i'll dig into it. thanks for the help!

thheller18:09:50

(0 , _uncontrollable.default) this looks very suspiciuous though so might be something else

joshkh18:09:19

yeah. and all subsequent hot-reloads work just fine.

thheller18:09:54

yeah found the problem

thheller18:09:23

react-bootstrap requires react-overlays which wants "uncontrollable": "^6.0.0"

thheller18:09:38

but react-bootstrap installs "uncontrollable": "^7.0.0"

thheller18:09:59

react-overlays has the nested install (so node_modules/react-overlays/node_modules/uncontrollable/...)

joshkh19:09:51

ah, gotcha! thanks for digging into it. i'm only just reacquainting myself with npm after spending a long time (happily) avoiding it.

joshkh19:09:25

is there an idiomatic way to resolve it?

David Pham19:09:43

Referring to this chapter from the documentation (https://shadow-cljs.github.io/docs/UsersGuide.html#_requiring_js), I am trying to mix javascript and clojurescript. I converted my JSX files with Babel, however the following line import React, { Component } from 'react'; leads me to the error Requested module does not have an export "Component". when I import the file. Does anyone have an idea how to solve this issue?

thheller19:09:03

@neo2551 yeah that is not supported and wouldn't work in webpack5 either

thheller19:09:18

they just currently have this compatibility mode that still allows this, just won't in the future

thheller19:09:31

import React from "react"; and React.Component should do it

David Pham19:09:39

ok! Thanks a lot!

thheller19:09:22

@joshkh not sure that can actually be resolved. in webpack it'll happily use 2 versions of the same library but that isn't supported in shadow-cljs because I think that is nonsense

joshkh19:09:45

webpack craziness is what drove me to shadow-cljs. 😉 i understand

David Pham19:09:59

@thheller Are there anyway to get something else than the default export?

thheller19:09:12

what do you mean?

David Pham19:09:27

In the example you provided me for importing react

David Pham19:09:43

is there a way to get React is the default export

thheller19:09:48

they should all be properties of the React export

thheller19:09:00

but no direct :refer

David Pham19:09:12

I understand, I am trying to explain my problem with the example of react

David Pham19:09:23

and apply it to other libraries

thheller19:09:43

react itself is packaged as commonjs, shadow-cljs and closure-compiler only support strict-style commonjs -> ESM interop (as will webpack5)

David Pham19:09:16

guess, I will have to study JS(hit) a bit

thheller19:09:31

and with strict interop the ESM can only use a default export from commonjs

thheller19:09:07

it depends on how the package is packaged. if is it actual ESM code or commonjs (ie. compiled by babel)

thheller19:09:40

the situation is a bit icky currently as many packages are switching from the compatible style to the strict style

thheller19:09:07

thus breaking those that still expect the compatible style

thheller19:09:15

it is a complete mess 😛

David Pham19:09:37

Sorry for the newbee questions xD

thheller19:09:57

if you have specific examples I can make suggestions but it is a pretty broad topic

David Pham19:09:27

I am trying to improt this type of dependencies

thheller19:09:39

the webpack folks have been talking about this for a while now https://www.youtube.com/watch?v=p-MhcctQBlY

thheller19:09:55

but it still isn't out yet so we'll see how that goes

David Pham20:09:27

Thanks, I am totally new to JS, I started UI on the web with shadow-cljs, so have been totally protected from all that. xD

thheller20:09:46

well not totally protected since you are exposed to all npm packages 😉

thheller20:09:04

might actually be smoother in webpack for now given that it still supports the old stuff

David Pham20:09:08

Yes, I accept a bit of impurity (Clojure is meant to be practical xD)

thheller20:09:15

what is the actual problem though?

thheller20:09:47

I hope you are not trying to put react-chart-editor on the classpath and import directly?

David Pham20:09:48

I would like to use this statement in a custom jsx file import PanelMenuWrapper from 'react-chart-editor';

David Pham20:09:08

nope, I am trying to build custom js file, export them through babel

thheller20:09:09

that doesn't look right?

thheller20:09:36

import RCE from "react-chart-editor"; and then RCE.PanelMenuWrapper?

David Pham20:09:38

nope, because PanelMenuWrapper becomes the default exort

David Pham20:09:57

and the default export is not one that embeeds all of them

thheller20:09:00

no, there is only one default export

David Pham20:09:13

PlotlyEditor is the default export

thheller20:09:17

with the name that you give it. the name is completely up to you.

thheller20:09:34

just like clojure (:require [some.thing :as whatever-you-want])

thheller20:09:40

the alias has no relation to the actual name

David Pham20:09:29

thanks for the precision! The issue is the default export is a (extremely restricted) subset of the exposed variable in the index.js file

David Pham20:09:11

import PlotlyEditor from './PlotlyEditor';
import DefaultEditor from './DefaultEditor';
import EditorControls from './EditorControls';
import {EDITOR_ACTIONS} from './lib/constants';

export {DefaultEditor, EditorControls, EDITOR_ACTIONS};

export * from './lib';
export * from './components';
export * from './default_panels';

export default PlotlyEditor;

thheller20:09:59

don't ever look at the source code

thheller20:09:05

it is lying to you more often than not

David Pham20:09:20

haha, the best advice ever xD

thheller20:09:05

the easiest way I find to inspect what is going on is doing

thheller20:09:09

shadow-cljs browser-repl

thheller20:09:18

(require '["react-chart-editor" :as x])

thheller20:09:25

(js/console.dir x) then look at the object in the browser-repl browser console

thheller20:09:16

one thing you can also do is just use commonjs

thheller20:09:37

so in your .js files just use const RCE = require("react-chart-editor");

thheller20:09:49

that isn't subject to the commonjs->ESM interop stuff

David Pham20:09:58

ohhhh this seems cool

thheller20:09:00

so RCE might have the full set of properties

David Pham20:09:48

the funny stuff is

David Pham20:09:02

the cljs version works, I get full access to everything.

David Pham20:09:06

but not the jsx

thheller20:09:18

try the commonjs style (ie. use require not import)

David Pham20:09:00

nope, still gives me PlotlyEditor

David Pham20:09:48

Althgough Babel translate it to

David Pham20:09:48

const RCE = require('/node_modules/react-chart-editor/lib/index.js');

thheller20:09:42

I think you mean shadow-cljs did that part?

thheller20:09:33

babel should leave it as require("react-chart-editor")?

David Pham20:09:26

the shadow-cljs part works totaly fine

thheller20:09:44

yes but please be clear in which files you are talking about

David Pham20:09:53

The workflow is: custom JSX -> babel -> cljs

thheller20:09:59

you have JSX. that is transformed by babel, that is then transformed by shadow-cljs

David Pham20:09:04

I am editing the custom JSX file

thheller20:09:27

so check the babel output what that does

thheller20:09:58

I hope you are not putting node_modules on the classpath?

David Pham20:09:08

nope 🙂

David Pham20:09:18

const RCE = require('react-chart-editor');is the output babel

thheller20:09:26

good 🙂

thheller20:09:54

shadow-cljs adjusts the paths so you know which files were actually used

thheller20:09:25

(and to work around a problem in the Closure Compiler)

David Pham20:09:35

shadow-cljs is great 🙂

thheller20:09:37

but yeah RCE should have all the stuff you want?

David Pham20:09:29

nope, when I enter console.log(RCE.Button); I get undefined

thheller20:09:35

hmm actually it might not have

David Pham20:09:38

funnily enough on shadow-cljs I get something xD

thheller20:09:44

but then shadow-cljs should have either?

David Pham20:09:09

yes shadow-cljs have either. This is what kills me xD. I can write better js in cljs than in js

thheller20:09:59

so if you console.log(RCE) in the JS you get different output then (:require ["react-chart-editor" :as x]) and (js/console.log x)?

thheller20:09:04

that should match?

David Pham20:09:58

JS -> undefined, cljs -> {default f} and when you open it you get the whole shebang of objects.

thheller20:09:25

with console.log(require("react-chart-editor"))?

thheller20:09:00

that shouldn't be undefined?

thheller20:09:27

oh or does it throw an error in the browser console while loading?

thheller20:09:41

that isn't handled well currently

David Pham20:09:43

I get f PlotlyEditor(props) for js, against the expected {default: f, ...}

thheller20:09:32

hmm thats weird

thheller20:09:55

but we are talking about require here yes? definitely not import?

David Pham20:09:12

definitively require

David Pham20:09:16

I copy past your code

thheller20:09:21

so there is no import in the file at all anymore I mean?

David Pham20:09:45

let me try again

David Pham20:09:48

with a minimal example

David Pham20:09:41

ok, with minimal example, it still output the default export from index.js

David Pham20:09:08

const RCE = require('react-chart-editor');

console.log(RCE.PanelMenuWrapper);
console.log(require('react-chart-editor'));
const CustomEditor = function (props, context) {
  return React.createElement("div", null);
};

export default CustomEditor;

David Pham20:09:03

got undefined, and PlotlyEditor as output in the browser

thheller20:09:31

try console.dir(RCE)

thheller20:09:51

and don't mix module styles

David Pham20:09:00

ƒ PlotlyEditor(props)

thheller20:09:02

module.exports.default = CustomEditor

thheller20:09:45

geez how gigantic is this react-chart-editor package

thheller20:09:54

seems like it is downloading the entire internet right now

David Pham20:09:12

you remember when I asked you how to load npm packages in the browser and you said to me to use the "eval" option somehwere in the config?

David Pham20:09:15

this was because of that XD

thheller20:09:18

yeah. are the no smaller alternatives? 😛

David Pham20:09:11

I wish. 🙂 My rationale was that it would require me a lot of work to rewrite the stuff in re-frame.

David Pham20:09:35

They have a two way communication between the editor and plot, and plotly have a gigantic amount of options.

David Pham20:09:57

(obviously I could start small), but I doubt my employer would accept me saying: I can't use JS, so I reimplemented the wheel xD

David Pham20:09:07

but if it does not work, I will just go with the slow way, it is just annoying. I tried to reimplent some part directly in CLJS, but the I don't understand how they bind this in their subcomponent.

David Pham20:09:01

Well thanks, I need to go to sleep but it was really nice and enjoyable to talk to you @thheller

thheller20:09:43

hope you find a way to sort it out 😛

David Pham20:09:54

Reinventing the wheel

David Pham20:09:58

Works all the time

thheller21:09:29

it is completely possible that you are just running into an edge case in the shadow-cljs JS support

thheller21:09:39

not many people use it and it definitely can have issues 😛