All liveviews in a single session for a more SPA-like experience

I would like to create a webapp with all my liveviews into the same session to create a more SPA-like experience.

First question: Does it seem to be an ok practice?

Second one: live_session functions are used in router.ex to add on_mount on a group of liveviews (e.g. authentication checks). However, I would like to keep my on_mounts blocks without creating separate sessions to avoid full page reloads. Do we have a solution for this case?

1 Like

I applied the simplest workaround to avoid full page reloads: all liveviews in a single live_session in my router.ex, and on_mount functions moved into liveviews. I suppose having authentication hooks in liveviews is not better or worst than in the router finally.

E.g. from:

# in router.ex:

live_session :no_authentication,
  on_mount {MyApp.Hooks.LiveAuthentication, :logged_in_user_unwanted} do
  live "/register", Live.Authentication, :register
  live "/log-in", Live.Authentication, :log_in
  # [...]
end

live_session :authentication_optional,
  on_mount {MyApp.Hooks.LiveAuthentication, :logged_in_user_optional} do
  live "/", Live.Home
  # [...]
end

live_session :authentication_required,
  on_mount {MyApp.Hooks.LiveAuthentication, :logged_in_user_required} do
  live "/settings", Live.Settings
  # [...]
end

To:

# in router.ex:

live_session :global do
  live "/register", Live.Authentication, :register
  live "/sign-in", Live.Authentication, :sign_in
  live "/", Live.Home
  live "/settings", Live.Settings
  # [...]
end

# in all liveviews:

on_mount {MyApp.Hooks.LiveAuthentication, :logged_in_user_unwanted}
# or
on_mount {MyApp.Hooks.LiveAuthentication, :logged_in_user_optional}
# or
on_mount {MyApp.Hooks.LiveAuthentication, :logged_in_user_required} 

Are you aware of the push_navigate and push_patch functions?
https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#push_navigate/2

These are built in ways to prevent full page reloads.

With my previous code, full page reloads were applied when I navigate (via <.link navigate={~p"/path"}>) from a liveview from a live_session to another liveview from another live_session. I did not have the problem with liveviews from the same live_session.

Putting all liveviews in a single live_session solved my problem.

2 Likes

Seems you worked it all out, but I guess re the original questions:

First question: Does it seem to be an ok practice?

IMO the live_session idea exists to make boundaries really clear and “easier to not muck up”, but forgoing them is ok as long as your careful.

Second one: live_session functions are used in router.ex to add on_mount on a group of liveviews (e.g. authentication checks). However, I would like to keep my on_mounts blocks without creating separate sessions to avoid full page reloads. Do we have a solution for this case?

You answered this yourself, but you may want to alter your MyAppWeb __using__ macro to support different arguments, so instead of use MyAppWeb, :live_view, you’d have use MyAppWeb, :public_live_view, use MyAppWeb, :authenticated_live_view. These specific flavours can include your on_mount calls, which might make missing them or using the wrong one a bit less likely.

2 Likes