Can you hook up a LiveView to a prerendered static page?

My thinking is to do something JAMstack-like with Phoenix LiveView at some point. If you have generated an HTML page before-hand and it loads the relevant JavaScript, maybe somewhat custom for this. Could that successfully take the static view and turn it “live”?

I seem to recall that when a LiveView is loaded it will provide the static markup as a first step and then establish the Channel over WebSockets and everything to liven it up. Are there any CSRF, session or similar concerns to doing this from an originally entirely static page? The idea being that this would be a form of progressive enhancement.

1 Like

I’ve had the same questions as you but sadly zero direct helpful answers.

When I find a job and get some free time after the onboarding I’ll definitely try Next.JS and/or Eleventy for that. They allow you to build a website from scratch without getting in the way.

So you could, theoretically, duplicate what a normal Phoenix LiveView project is doing by injecting the very small LiveView JS file into your static site, and take it from there.

Although to be fair, what you’re describing sounds like a much better fit for Vue.JS which has been used successfully, many times, to selectively add dynamism to otherwise mostly static pages/sites.

1 Like

Yeah, this would be part of something that would use a Phoenix API from static pages anyway and if I could do some of it with LiveView it might be magical.

Mostly a theoretical thing for now.

I appreciate the tips, I’m looking around the static generator world quite a bit right now. But I really don’t want to build heavily on Node and JS. JS for the browser is one thing. I feel like Node doesn’t really give me much of what I want and it comes with a world of things I’d rather skip.

Currently Hugo is my top contender for an SSG. Wide feature set, performance focused, single binary. Seems like a good use-case for Go.

Sorry, entirely missed responding to the best part. Yes, this would be what I’d want. And U think that should be feasible. Slightly surprised it hasn’t been done.
Guess I have a concept to prove and a blog post to write…

I’ve been thinking a bit about this recently as well. No real info to share, but I’d be happy to join in any efforts to dig into this.

Do you have any thoughts yet on how to handle injecting the initial LiveView-managed DOM into your static page?

1 Like

Last time I heard the first render of a LiveView isn’t stateful. So that’s a straight render and then when the live part mounts that part is replaced. But I might have a simplified idea. Haven’t looked yet :slight_smile:

Oh definitely. Just thinking about how best to get it from Phoenix into your static site generator… maybe a Phoenix SSG plus LiveView would be the killer app… :thinking:

1 Like

Yeah, that’s one way to do it. Just render the template with the initial state. Or you make a static page that is mostly replaced if turned live. Depends on the use-case. I’d have to look into it.

I don’t think I’d build an SSG with Elixir+Phoenix mostly because I think there are perfectly good options already. But I wiuld consider integrating with one :slight_smile:

1 Like

Hugo is working well and is fast. Trouble is, if you don’t like all aspects of the theme you picked, there is a steep learning curve to customise it.

Hugo is mostly good if you want to just pile up several add-ons and call it a day. If you want to truly make the site in your style however, you’ll suffer a bit. Which is okay but I’d still prefer something like Eleventy instead.

3 Likes

I do think this is workable (although it is going against the grain of LiveView), but by default you do need to pass a CSRF token that is read from the rendered page:

import {Socket} from "phoenix"
import LiveSocket from "phoenix_live_view"
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content");
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}});
liveSocket.connect()

So you’d need to pass the CSRF token separately or disable it for this approach.

3 Likes

Cool. Yeah, I figured I’d run into the CSRF token. If the idea is primarily to display the static page if there is no JS and then get the LiveView up and running it might also be fine to load the LiveView and get the CSRF token set up as normal whenever JS is active. Bit of a slow-down, something to think about.

1 Like

What part of theming did you find steep? I took a look at some themes and found it fairly clear. The syntax of the dynamic portions is odd to me but overall I found it fairly approachable (example: https://github.com/wayjam/hugo-theme-mixedpaper/blob/master/layouts/_default/list.html). Curious if you found any stumbling blocks. If I’m setting up a site for less technical frontend designers I don’t want to traumatize them : )

For my plans and needs currently I think Hugo will fit nicely. But really appreciate getting some perspectives on it as I haven’t used it for an actual site.

Mostly its custom DSL. My Go is quite rusty and the DSL isn’t very close to Go itself either.

1 Like

You can run liveview without CSRF protection. Just be sure to not allow it to manipulate things, which would be worth protecting. See e.g. this commit.

4 Likes

I think in the case of something that allows manipulation of anything sensitive it would require some kind of auth and then I don’t see any real problem establishing a session and CSRF-tokens and whatnot. I’d have to double-check some of the details since its all security-related and there’s a bunch of nuance to not get wrong if I want to do this. But I think LiveView could be very neat as both part of Progressive Enhancement and JAMStack-style interactivity.

1 Like

I assume by static you mean “externally / CDN hosted”?

I’ve been wondering about this, if you had a task to build and publish the first pass of the live view to a static cache, then had a bit of JS to run a “session creation” request that returned the CSRF token I think it should work.

2 Likes

That was roughly my thinking :slight_smile:

Did you ever pursue this further?

Not yet

1 Like

Any idea how one would do this (if even possible with current implementation of liveview)? My use-case to cache everything in a cdn (including HTML) on a site so that first load is super fast and then switch to liveview running on a subdomain. See implementation: https://test.budgetera.nu (which is 100% cached by a CDN) and it calls liveview on live.budgetera.nu (which is same phoenix app running on fly.io). Btw, if you read it in the future chances are something else will be on that domain.

It kinda works with the solution mentioned by @LostKobrakai but only for sites that don’t really need a session etc. My dream scenario would be if I was able to cache everything on test.budgetera.nu and when it’s loaded it makes a new request to live.budgetera.nu that creates the csfr-token that can then be used for the liveview session (or some other kind of flow that makes more sense. I don’t have the skills to figure out how everything needs to work).