hoplon

The :hoplon: ClojureScript Web Framework - http://hoplon.io/
rlander 2020-02-26T21:12:30.003600Z

So what's the idiomatic way of breaking a non-toy Hoplon app into namespaces? Most of the examples I found involved a single namespace.

rlander 2020-02-26T21:14:47.005500Z

I just ported the realworld app (https://github.com/gothinkster/realworld) to both learn how Hoplon works and to contribute back with a "reference". Anyone willing to take a look at the code?

2020-02-26T21:14:51.005700Z

i think usually there's an entrypoint element that's basically a tabset, and namespaces follow from how that top level element is structured

rlander 2020-02-26T21:15:19.006300Z

@alandipert so each "page" would be a separate ns?

2020-02-26T21:15:49.007200Z

it could be

2020-02-26T21:16:07.007800Z

this is one area where hoplon offers a lot of flexibility so i'm not sure there's one true approach

rlander 2020-02-26T21:16:11.008100Z

how about top level cells (state)? Should they live in a separate ns, like myapp.state or within the page ns?

2020-02-26T21:16:18.008300Z

since the linkages between cells are usually automatic, explicit structure isn't required

rlander 2020-02-26T21:16:59.009500Z

I ended up doing everything in one single file, the entire 900 lines. haha. Doesn't look as bad as it sounds.

2020-02-26T21:17:10.009700Z

there can be a top-level state, usually it contains the route and info related to the URI

2020-02-26T21:17:18.010Z

then usually instances of elements have a bunch of anonymous let-bound cells

2020-02-26T21:17:44.010900Z

i'm sure it's awesome, maybe one of the greatest things about hoplon compared to other frameworks is you can do it all in a single file

rlander 2020-02-26T21:17:54.011300Z

Yeah, I tried to used scoped cells as much as I could so that most elements could be re-usable.

flyboarder 2020-02-26T21:18:05.011600Z

I only use global state for things that should be global, ideally state is scoped to a page or element

flyboarder 2020-02-26T21:18:34.012100Z

with element state you have the option of a local let scoped cell or passing one in via an attribute

2020-02-26T21:18:54.012700Z

oh yeah, cell attributes, a key pattern

flyboarder 2020-02-26T21:18:57.012900Z

so often we use (:state attr (j/cell nil))

rlander 2020-02-26T21:19:11.013300Z

I'm still going to clean this up, but here it is: https://gist.github.com/rlander/e971880d86ad8ccb665ab69a0eb731aa

flyboarder 2020-02-26T21:19:44.014100Z

this pattern lets you have local default state while also accepting external state for reusability

rlander 2020-02-26T21:20:01.014500Z

Are you guys interested in adding this to the canonical realworld repo? It's fully working (based on shadow-cljs and retiit router though).

rlander 2020-02-26T21:21:37.015100Z

@flyboarder Yeah, I tried to keep global state only for shared cells.

rlander 2020-02-26T21:23:39.016300Z

I'm coming from many years of reagent and re-frame apps so maybe some of the code looks reagent-ish.

flyboarder 2020-02-26T21:24:09.016700Z

always open to more demos, feel free to open a PR for the demo repo

rlander 2020-02-26T21:25:15.017400Z

@flyboarder I was thinking of adding to this repo: https://github.com/gothinkster/realworld

1👍
2020-02-26T21:25:52.018Z

@rlander skimming the code, looks great. 42 bonus points awarded for dosync use

2020-02-26T21:26:50.019Z

makes me wonder about a helper for nested divs like (divs [["outer-class"] ["inner-class"]] ...inner-children) to compete for line count better :simple_smile:

rlander 2020-02-26T21:26:56.019100Z

Thanks! Should've used more dosynchad I added a loading cell.

2020-02-26T21:29:46.021Z

looking at the elm version... so many files 😱

rlander 2020-02-26T21:30:18.021300Z

@alandipert hmm yeah, I didn't even try to reduce repetition and it's already besting the re-frame implementation by ~150 lines. But yeah, that kind of helper would be useful!

2020-02-26T21:30:49.021800Z

well, maybe it would hehe. it also obfuscates

rlander 2020-02-26T21:32:52.022600Z

I'm also a little worried about the bundle size. The last build got to ~700kb.

2020-02-26T21:33:44.023200Z

oof, thats with advanced and stuff?

rlander 2020-02-26T21:33:52.023400Z

BTW, using shadow-cljs & Hoplon together was a blast.

rlander 2020-02-26T21:34:30.024700Z

Yesm with advanced on. Shadow-cljs has a report command that shows all dependencies by size.

2020-02-26T21:34:37.024800Z

not to suggest hoplon PR work for you 😉 , but i don't think anyone's ever written an experience report about that combo

2020-02-26T21:34:53.025Z

anyway i would upvote it

rlander 2020-02-26T21:35:41.025200Z

something like this: https://gist.github.com/rlander/3081f3703ea9cfed3129e8afcc94bedb

rlander 2020-02-26T21:37:56.027200Z

@alandipert I was going to write about the experience anyways, no worries 🙂

rlander 2020-02-26T21:38:26.027900Z

They go really well together since through shadow-cljs I am free to use any JS lib that's in npm.

rlander 2020-02-26T21:38:38.028200Z

BTW, I only used shadow-cljs because I could not find recently updated boot template.

rlander 2020-02-26T21:39:56.029400Z

It's nice to know that it is flexible enough to work well with a build tool that didn't even exist when Hoplon was created, though.

rlander 2020-02-26T21:41:27.030400Z

As someone who's coming from years of React/Redux/reagent/re-frame, I really enjoyed working with Hoplon.

rlander 2020-02-26T21:44:48.030900Z

So, do I keep it a one-file project?

rlander 2020-02-26T21:48:28.031Z

That's a very useful idiom, thanks.

2020-02-26T21:57:49.031400Z

one-man project = one-file project imo 😆

1😁
2020-02-26T21:57:56.031600Z

i love keeping huge things to one file if i can

2020-02-26T21:58:04.031800Z

other programmers tend to object

2020-02-26T21:58:37.032200Z

modern editors can split files into conceptually separate files with window-splitting technology

micha 2020-02-26T21:59:11.032500Z

what is this sorcery

micha 2020-02-26T21:59:30.032800Z

i have separate files on separate computers in separate buildings

micha 2020-02-26T21:59:41.033100Z

now you say i can do some craziness in my editor?

2020-02-26T22:01:14.033300Z

C-w v ®️

1😀
rlander 2020-02-26T22:04:08.034500Z

My concern is publishing something not idiomatic as a Hoplon reference.

2020-02-26T22:04:50.035400Z

no concerns here. if it works for you, then it's idiomatic as far as we're concerned

2020-02-26T22:05:04.035800Z

and if it didn't work for you, you woudl use something different 😄

rlander 2020-02-26T22:05:50.037Z

Awesome. I'll clean it up, add a repo, add to the demos and post the link here.

2020-02-26T22:06:00.037300Z

i feel like this is maybe why people were always a little weary of hoplon, we never described (or prescribed...) any particular high level architecture in concrete terms

2020-02-26T22:06:17.037600Z

but that was supposed to be a feature, that the implementor would have full control there still

micha 2020-02-26T22:07:53.038100Z

yeah it's just a clojure program at the end of the day, right?

micha 2020-02-26T22:08:28.038800Z

you can organize any clojure program in different ways by factoring it into namespaces

micha 2020-02-26T22:08:43.039100Z

probably isn't any one best way to do that

rlander 2020-02-26T22:10:06.039600Z

For someone just getting started this can definitely be a problem

rlander 2020-02-26T22:12:33.041100Z

Most people think hoplon is this monolith thing that can only be used with .hl files, boot and castra and it's actually the opposite.