Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use prerender in the ob init example app #320

Closed
mightybyte opened this issue Nov 24, 2018 · 13 comments · Fixed by #617
Closed

Use prerender in the ob init example app #320

mightybyte opened this issue Nov 24, 2018 · 13 comments · Fixed by #617

Comments

@mightybyte
Copy link
Collaborator

The example app generated by ob init doesn't use the prerender function. This makes it not obvious how to go from DomBuilder which is needed by _frontend_body to MonadWidget which you end up wanting for most of your app. Using something like this would make that more obvious:

  , _frontend_body = prerender (text "Loading...") app
@kitlangton
Copy link

Some examples would help as well. Are there any open source obelisk apps/examples out there?

@hSloan
Copy link
Contributor

hSloan commented Nov 26, 2018

Going to create a ticket that will make a better error message than the one experienced here.

I'm going to reference this issue #241 because examples and documentation using prerender are desperately needed.

@mightybyte
Copy link
Collaborator Author

@hSloan I don't think an error message would help much in this case. The default skeleton app works fine. It's just that it's not easy to figure out how to change the type from DomBuilder to MonadWidget. I was thinking something simple like this would demonstrate the concept pretty clearly.

#322

@ryantrinkle
Copy link
Member

@mightybyte FWIW, I'm hoping to deprecate MonadWidget once we sort out how to make the alternatives more ergonomic.

@mightybyte
Copy link
Collaborator Author

@ryantrinkle I tend to think that's likely to be the wrong decision, but I'll reserve judgement until I can see the alternative. It seems like this is the age-old constraints-vs-liberties tension. It's really nice to never have to think about what constraint you're using when you're building an app and just use the thing that you know will always give you all the power you might need in the future. I suspect we'll want this as long as the constraints can't be inferred. And even if the constraints can be inferred, we're probably still want something like MonadWidget since writing type signatures is the widespread best practice in Haskell.

@marcotoniut
Copy link

I'm seeing myself deprecating MonadWidget more and more in favor of my own (contained) App/Module/Widget Constraint type synonyms. Aside from making it easier for me to reason about the inner workings of Reflex and Reflex Dom, this practice has also been helpful when abstracting the smaller more reusable reflex components.

@ali-abrar
Copy link
Member

Perhaps a subroute that uses prerender would be a good compromise. That way there's a documented prerender example, but the default route still takes full advantage of server-side rendering and DOM rehydration.

@ryantrinkle
Copy link
Member

@ali-abrar Yeah; it could also be just some widget on the page that uses JS; whether or not it's a subroute, it will need some prerender.

@cgibbard
Copy link
Contributor

cgibbard commented Apr 21, 2019

My recommendation on this would be to have an example of using either XHR or websockets in the skeleton, which would then involve putting a prerender just around that bit. The correct impression to give is that prerender is best used around parts of the page which actually render no DOM whatsoever.

Of course, we might also want to push the use of prerender into the definitions of those things, at which point, the examples of usage would be harder to come by.

@mightybyte
Copy link
Collaborator Author

I like @cgibbard's suggestion. It also lines up quite nicely with something I was just thinking today which is that obelisk should provide a convenience function that opens a websocket using the obelisk-configured route in config/common/route. I was just setting this up and there are several details that you have to get right that aren't obvious. Here's what I ended up with:

appWebsocket = do
    route <- liftIO getAppRoute
    let (_,rest) = T.breakOn "://" route
    webSocket ("ws" <> rest <> "/ws") cfg

And then in Common.Route I have:

getAppRoute :: IO Text
getAppRoute = do
    mroute <- ObConfig.get "config/common/route"
    case mroute of
      Nothing -> fail "Error getAppRoute: config/common/route not defined"
      Just r -> return $ T.dropWhileEnd (== '/') $ T.strip r

You can work out the details differently of course, but the important parts that weren't obvious to me at first are the need to use config/common/route and the need for the ws:// prefix on the argument passed to the webSocket function. Ideally obelisk should provide this out of the box in the project skeleton or at least supply some library functions that reduce the potential for getting these details wrong.

I suppose this merits a separate ticket, but I thought I'd see if you're open to the idea before I create the ticket.

@eskimor
Copy link
Collaborator

eskimor commented May 6, 2019

For https, you would need wss instead of ws.

@mightybyte
Copy link
Collaborator Author

Ahh yes. All the more reason to solve this problem for people with code!

@ryantrinkle
Copy link
Member

Also: we should provide in the FAQ that when someone sees an error like Couldn't match type 'DomBuilderSpace m' with 'GhcjsDomSpace'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet