Fork me on GitHub
#shadow-cljs
<
2018-03-07
>
pithyless06:03:39

Running 2.2.4, I’m seeing #shadow-hud-loading-container but not seeing #shadow-hud-container if I force a syntax error (just an error in the terminal). Was the HUD changed in some recent version? (I upgraded from a 2.0.x version)

thheller08:03:27

@pithyless didn't change the HUD in a while no (and its working as usual for me)

mhuebert09:03:31

random cljs repl question. Quite frequently for whatever reason I get a “REPL Timed out” error (maybe caused by a syntax error or something else). Is there something I should try other than restarting the whole shadow-cljs server to get it working again? refreshing the browser page usually doesn’t work, nor does re-opening a new nrepl connection

thheller09:03:09

restarting should never be required

thheller09:03:39

I recently added (shadow.cljs.devtools.api/reload!) to "restart" the server without restarting the JVM

thheller09:03:55

but I'd like to hear more details about the timeout

thheller09:03:24

probably a bug somewhere

thheller09:03:58

although one repl timeout shouldn't break the entire connection

mhuebert09:03:28

i’ll see if i can reproduce something easily

thheller10:03:17

REPL command timed out. is the error?

mhuebert10:03:50

that is common yes

mhuebert10:03:02

right now i am already in that state, and I am trying to evaluate :cljs/quit, i see

Error evaluating - class java.lang.InterruptedException: 
Error evaluating - class java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@2f73f4d6 rejected from java.util.concurrent.ThreadPoolExecutor@128bf5a3[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 4]

thheller10:03:38

hmm did you by any chance call shutdown-agents?

mhuebert10:03:13

i don’t think so no

mhuebert10:03:39

let me restart, i don’t know when i quit the node process

mhuebert10:03:55

so ignore this last bit

thheller10:03:13

rejected means that the pool was shutdown which shouldn't happen during normal eval

thheller10:03:31

only thing that would do that is shutdown-agents

mhuebert10:03:41

yeah I think while we were chatting I had already started going through the motions of restarting the thing and forgot

mhuebert10:03:12

so, if I get the timed out error, I should try to :cljs/quit and then (shadow.cljs.devtools.api/reload!)

thheller10:03:54

first I'd like to know the form that caused the timeout

thheller10:03:15

try to eval something simple like (+ 1 2)

thheller10:03:27

then quit/reload maybe

thheller10:03:54

is the timeout legit? do you do something that actually takes a long time?

mhuebert14:03:23

no, I think it usually happens when there is some kind of evaluation error

mhuebert14:03:29

i will play around and see how i can replicate

justinlee18:03:18

is there a flag to make the development server log requests, perhaps in one of the common log formats?

thheller18:03:03

not currently. why would you want that?

thheller18:03:31

it would be like hundreds of JS file requests. not very interesting?

justinlee18:03:00

debugging. sometimes static resources load funny, or i have some kind bug with the way i’m manipulating client-side html5 history. it is nice to know sometimes when my app is actually hitting the server and what it is requesting

thheller18:03:21

don't the chrome devtools tell you that?

justinlee18:03:39

allegedly they do.

justinlee18:03:57

i can’t figure out why i am apparently loading an image successfully but i get a broken link image

thheller18:03:33

are you sure the image is getting loaded? I mean with push state you get success for everything although it always the index.html

justinlee18:03:38

the other issue i have is when i’m not at the root level and I manually refresh, the development server doesn’t reserve the app like i would expect

thheller18:03:18

sounds like you are using <script src="some/relative/path.js"> maybe?

justinlee18:03:18

I guess I just wanted to sanity check what the hell was going on by checking the server logs. But you are right, there are other ways to debug this.

justinlee18:03:08

<script src="js/main.js"></script>

thheller18:03:56

use /js/main.js. otherwise it will attempt to load something/js/main.js when you are in /something/path

justinlee18:03:09

yup that fixed it. 🙂

justinlee18:03:25

the error that happens is truly inscrutable

thheller18:03:07

well yeah because you don't get 404s when using pushstate

thheller18:03:26

maybe I could 404 when .js files are requested

justinlee18:03:32

this is also the problem with my images not loading

thheller18:03:39

unlikely you are going to use that in html5 history paths

justinlee18:03:43

chrome devtools thinks the request was successful

thheller18:03:56

in chrome you can click open in new tab for the request

thheller18:03:19

or look at the response preview

thheller18:03:34

if its html its not an image

thheller18:03:49

but in general always use absolute paths to avoid such nightmares 😉

justinlee18:03:10

create-react-app handles this problem really well. i think they look at the headers. they also have a very convenient proxying feature so that development and deployment look similar when you server the bundle from the api server: https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#proxying-api-requests-in-development

justinlee18:03:13

i think it is related

thheller18:03:24

guess I could check the headers

justinlee18:03:07

i have dreams of building c-r-a on top of shadow

thheller18:03:24

hehe why? or which part?

justinlee18:03:54

because I think its the right way to get an opinionated set of tools going and get people interested in cljs development

thheller18:03:19

should I just make the push-state thingo the default? kinda feels like it might be the "usual" thing you want for a cljs app

justinlee18:03:23

templates are terrible and once you use one you can never keep up to date

thheller18:03:38

true but whats missing?

thheller18:03:01

I'm not buying the whole zero-conf argument. I think thats actually a bad idea

justinlee18:03:53

you just get so much functioning stuff for free with create-react-app. just look at the user manual.

justinlee18:03:22

development, production, testing, instructions on editor integration

justinlee18:03:49

zero-config really helps get you going and focusing on what matters

justinlee18:03:01

you can always eject and customize when you get sophisticated

justinlee18:03:45

in my experience, people overestimate the value of customization and underestimate the cognitive load needed to make decisions

justinlee18:03:54

it is great if you are an expert, but it sucks otherwise

justinlee18:03:21

so much of the cljs experience is still in the “use the source, luke” phase

justinlee18:03:58

you just won’t get anybody but hobbyists and top 1% programmers that way

justinlee19:03:06

even though I am a big fan of shadow-cljs and tell everyone to use it on slack, there is still something totally amazing about create-react-app. you npm install it, you create a new project, you say npm start, and BAM, you have a working hot reloading project. you can start editing right then and there. shadow is great, but you still have to go read the section on :devtools, pick a directory, make sure you’re setting it right, figure out how the :after-load handler works and install it somewhere, etc. etc. each of these things = friction.

justinlee19:03:06

if you want to do a little experiment in react, it’s super easy because you can just fire off a c-r-a, do some stuff on the main page, and then throw it away

justinlee19:03:58

also, shadow can’t really be opinionated about reagent vs. rum or what have you, whereas a create-reagent-app could

justinlee19:03:09

it could be opinionated about a testing framework

thheller19:03:54

I'm all for making things easier especially for beginners but I do think that some config is important

thheller19:03:12

I could certainly simplify the :browser target and introduce some convention around it

thheller19:03:18

or add something like :browser-simple

thheller19:03:54

ie. just set :app-ns my.app or so

thheller19:03:22

from that is infers my.app/start and my.app/stop as the :after-load and optional :before-load

thheller19:03:38

always creates an public/js/main.js

thheller19:03:42

so no :modules

thheller19:03:14

testing I have something in the works that makes it zero conf

justinlee19:03:44

zero config should be thought of more like “sensible defaults for generic things that most people will want”

justinlee19:03:20

even with c-r-a you can eject. the only reason they did it that way is that it allows them to update the toolchain from underneath you, which is totally rad.

thheller19:03:32

well thats the idea behind shadow-cljs in the first place

justinlee19:03:40

and i think you’ve largely succeeded. the thing is that c-r-a does that one level up on the stack. it picks react, a testing framework, a bundler, give some options for addons like less/sass, etc.

thheller19:03:07

well there could always be :target :reagent

thheller19:03:39

:browser is just generic browser stuff, could totally do framework specific stuff

thheller19:03:51

not inside shadow-cljs itself but add one dep you are good to go

justinlee19:03:51

one thing that create-react-app did which is quite clever is that they separated out create-react-app, which is a generic tool, from react-scripts

justinlee19:03:31

i wonder if shadow-cljs might be able to act as create-react-app and then you could write the react-scripts equivalent for, say, reagent.

justinlee19:03:19

some people just fork react-scripts if they want quasi configuration capabilities. and others have react-scripts variants available

thheller19:03:34

well the create-react-app part is just a template really.

thheller19:03:46

just most of the template is hidden in react-scripts rather than the template itself

justinlee19:03:16

right that’s what i mean.

thheller19:03:19

I absolutely hate templates as well

thheller19:03:33

for this very reason

thheller19:03:51

they just get out of sync and then you are F*

justinlee19:03:05

yea and you have no idea what’s going on

justinlee19:03:41

this is a big reason why i think lein ended up hurting the community. people made stuff that is complicated and undocumented but hid it behind a lein template

justinlee19:03:21

its almost too powerful

thheller19:03:32

{:source-paths
 ["src"]

 :dependencies
 [[reagent/shadow-cljs "1.0.0"]]

 :builds
 {:app {:target :reagent
        :app-ns my.app}}}

thheller19:03:39

this is totalyl doable today without me doing anything

justinlee19:03:36

so what would that script refer to? like, would it know to download something and then run it?

thheller19:03:09

the "script" just generates that config

thheller19:03:28

and creates the matching package.json

thheller19:03:41

then runs npm install and prints the usual help stuff

thheller19:03:56

and of course all the src files

justinlee19:03:56

i’m confused. i don’t see any documentation on a :reagent target in the guide. are you saying one can create custom targets?

thheller19:03:05

yep, custom targets

thheller19:03:56

not well documented but you can just delegate to the :browser target for everything in this case

thheller19:03:40

basically just generate the usual :browser config from that :target :reagent baseline and call the browser/process fn

thheller19:03:43

bascially what :reagent means is that shadow-cljs will try to load shadow.build.targets.reagent/process

justinlee19:03:21

this is great! i never really grokked this but shadow-cljs does really emulate c-r-a in structure

thheller19:03:32

all the default targets are built this way

justinlee19:03:48

i mean maybe you came first, but you know what i mean

thheller19:03:44

I might need to make a few adjustments to the devtools http stuff. this is not as flexible as I'd like it to be.

thheller19:03:57

but apart from that everything should work just fine

thheller19:03:40

@hlolli already created a basic chrome extension template this way. https://gist.github.com/hlolli/265b9183566a4c5829d7ee355e3d0998

thheller19:03:30

which is basically just :browser with one adjustment to only output a single file in development

justinlee19:03:38

to write cljs and target whatever chrome needs for its extensions?

thheller19:03:16

only the JS part the manifest you still have to write

thheller19:03:52

but you could also generate the manifest from the shadow-cljs config no problem

thheller19:03:02

I do want all these targets to exist, eg. :electron, :react-native, etc

thheller19:03:20

just have limited time to create/maintain them

thheller19:03:41

but they totally do not have to be part of shadow-cljs itself

justinlee19:03:46

would it work if you publish them to clojars and then add them as a dependency?

thheller19:03:29

{:source-paths
 ["src"]

 :dependencies
 [[reagent/shadow-cljs "1.0.0"]]

 :builds
 {:app {:target :reagent
        :app-ns my.app}}}

thheller19:03:35

thats the [reagent/shadow-cljs "1.0.0"]

thheller19:03:09

can't add it as a dependency to shadow-cljs itself since that would be circular

justinlee19:03:09

also it would make you a gatekeeper of sorts. much better this way so people can just do whatever

thheller19:03:32

exactly 🙂

justinlee19:03:06

i have read of companies forking react-scripts privately so that they can keep their configuration separate and shared internally among their own projects

thheller19:03:31

yeah you could totally do that with shadow-cljs and a custom :target

thheller19:03:52

maybe there are other ways to "extend" things I just didn't think of yet

thheller19:03:15

shadow-cljs clj-run reagent.quick-start

thheller19:03:34

some clojure ns that does all the bootstrapping and starts whatever you need

justinlee19:03:44

well i’ll play with this a bit later. i think its a neat idea

thheller19:03:00

a more focused :target could definitely set way more aggressive defaults than :browser can. and since its just clojure data you could just generate the more complex :browser config from the "easy" one.

thheller20:03:00

@lee.justin.m just pushed 2.2.5 which makes push-state the default and does the Accept header check to no longer serve images as html

justinlee20:03:08

very nice! thanks