pedestal

bobcalco 2018-12-17T02:07:48.062300Z

@mtnygard Let me try first more simply to describe what I want: A static "landing" page at "/", an api root of /api/* which is handled server side, and an admin console at /admin that itself has many logical sub-"routes" using bidi with re-frame. The static page at "/" has different style completely from the admin console at "/admin" (which is a SPA). Currently I'm slurping up two different starter index.html files, but I'd rather make the entire page rendering dynamic (looking at rum for that). I have not changed the code much from what you find at https://github.com/pdlug/re-frame-starter. Anyway.... the abstract question is, how to get pedestal routes to play nice with bidi routes in the case where the SPA is not being created off root "/" but rather off "/admin" (for example). I am refactoring things a bit right now so code posts aren't practical at this precise moment. I'm trying to think differently about my problem and see if I can't find a solution that doesn't fight the frameworks expected behavior. For example: I'd be happy putting every page in the SPA if I could render entirely different CSS styling/JS for logged in vs not logged in scenarios. This is why I separated them in the first place - the need to have different stuff in the <head> and different JS at the bottom.

mtnygard 2018-12-17T03:25:31.065400Z

@bob592 I see. I just took a look at bidi’s code. They don’t directly support Pedestal, but I think you could make a very simple interceptor to glue a Pedestal route to the bidi router. That would be the sole interceptor on ‘/admin’. Then that interceptor would call the bidi router directly and pass it the request map from the context.

bobcalco 2018-12-17T12:19:10.072Z

@mtnygard Thing is, I don't want the admin console SPA reloaded every time Pedestal detects a route that "belongs" to it, as it would be harder (if not impossible or in any case highly non-performant) to maintain application state. Might as well do MVC post-backs (ahem). The request shouldn't even be making it to the server if bidi has it "covered," no? Maybe I should just use a different routing engine. The more interesting problem is, how do I support more than one CSS theme/design? I'm coming to the conclusion that I should just run two separate instances of pedestal - one HTTP and the other (once in production) HTTPS. Usually routing could split those hairs with interceptors but I don't know a way to generate the CSS I need in the <head> on the fly, as reagent is mounting the "app" div in the <body>, although I can probably do it by generating my own <link> tags since hiccups doesn't. A flask of Rum is sounding good perhaps for this. Alas, frameworks are as much a source of incidental complexity as language syntax...

mtnygard 2018-12-17T18:06:41.072700Z

@bob592 I'm lost. How does bidi affect your SPA state at all? I thought it was a back end routing framework.

bobcalco 2018-12-17T18:21:36.077100Z

@mtnygard It's a front-end routing library AFAIK, and on the #re-frame channel I'm getting some help that seems to be on point by @mateus.pimentel.w... he recommends I combine bidi with pushy on the client. Apparently it can prevent the call to the server for subroutes but I'm still not entirely clear myself how it is supposed to play nice with pedestal's server-side routing. The link the the article he pointed me to talks only about compojure. However, if it does require server side cooperation, your original idea about an interceptor for /admin may be the key after all. I still feel like I need more fundamentally to rethink what I'm trying to do. The motivation for all of this is simply to have different styling for a not-logged-in landing page, and a separate styling for the logged-in admin SPA.

2018-12-17T18:33:14.079900Z

Bidi is portable between clj/cljs and only cares about translating string paths to/from data structures.

2018-12-17T18:34:30.082700Z

Both using it on the backend with pedestal and on the frontend with pushy make sense, but are different things.

2018-12-17T18:35:26.084300Z

Hi @bob592! I think it’s best to distinguish between front-end and service api here. There will be some endpoints provided by your service api to satisfy app needs. How you coordinate that interaction is an orthogonal issue.

☝️ 1
bobcalco 2018-12-17T18:36:27.085200Z

@ddeaguiar Yes, I'm trying to think that through. As usual, starter projects and templates create more headaches than starting from first principles.

2018-12-17T18:37:06.086100Z

yeah, we don’t have starter projects which dive into this area

bobcalco 2018-12-17T18:37:10.086300Z

they only save you time if your app requirements are of the "hello, world" variety.

2018-12-17T18:37:49.087300Z

I recommend two different projects for front-end and service api

2018-12-17T18:38:02.087900Z

they can be in the same repo if you want but I think the separation is useful

2018-12-17T18:38:33.088700Z

I’d also consider implementing a mechanism to stub out service api interactions in the front-end code

Whiskas 2018-12-17T18:44:59.093700Z

@bob592 My provisory solution is to return index.html for everything but resources/files and let pushy to change the route for me with the help of bidi

Whiskas 2018-12-17T18:45:32.094400Z

but the ideal solution would be to use the same routes you set on client, on the server, returning index for them

Whiskas 2018-12-17T18:46:19.095700Z

since you are doing full stack clojure i think this should not be hard since the route definition can be done in a shared file and transformed into the appropriate format for the server

Whiskas 2018-12-17T18:46:25.096100Z

i’m not a specialist in this subject tho

bobcalco 2018-12-17T18:48:13.097400Z

@mateus.pimentel.w What i want to avoid in that case is constantly re-initializing application state each time the server posts back an index. I need some way to get the client and server to cooperate with whole-page rendering, not just the "app" div. At least, that's what I think I need. Separating the two seems like a good idea until you need to debug the round trip for API calls.

2018-12-17T18:50:43.099200Z

One thing to keep in mind is that it’s quite nice to separate front-end index.html from the backend service. Completely decouple them. For example, serve the front-end from s3 or something

2018-12-17T18:52:30.101100Z

front-end just makes service calls for data it needs. How you do this is up to you. Here’s where folks stumble on too coarse-grained or fine-grained service apis and what implementations like graphQL try to solve.

2018-12-17T18:52:57.101700Z

I don’t think there’s one good answer because it’s context-specific

bobcalco 2018-12-17T19:02:01.107700Z

@ddeaguiar In concept I agree of course. But development and deployment are two different worlds with their own exigencies and "incidental compexities"... Alas, the language can't really help us with those as much as we might like, especially once we start having to live with various design decisions and their sometimes unforeseeable consequences. I won't even mention the incidental complexities of development on a platform like the JVM with diverse tooling options and related ceremonies, and the seemingly infinite smorgasbord of library choices with varying interdependencies and version complexities... never a dull moment. 🙂

Whiskas 2018-12-17T19:08:48.108200Z

@bob592 are you developing a non-spa ?

Whiskas 2018-12-17T19:09:00.108500Z

here i just switch views using re-frame/dispatch

Whiskas 2018-12-17T19:09:06.108700Z

and the url is synced

Whiskas 2018-12-17T19:09:23.109Z

the url is synced in case you want to copy paste the url for that specific url

Whiskas 2018-12-17T19:09:39.109300Z

if you want to use the cached index i think you will have to add # to the url