tonydang

tonydang

Setting Up Phoenix with Inertia.js and Svelte :)

I recently got inertia-phoenix (an Inertia.js adapter for Phoenix) working with Svelte. Setting up the server-side rendering (SSR) with Svelte and esbuild was a little tricky so I made a repo with a detailed guide and example project so that I would remember all the steps for future projects.

Thought I’d share it here in case anyone else is trying to get the same setup going. :wink:

In addition to setting up Phoenix with Inertia and Svelte, the guide also includes a section for setting up several other JS tooling you may want when using Svelte, such as TypeScript, Prettier, ESLint, etc.

I’m definitely not an expert with esbuild setups, so please lmk if you see any mistakes or possible improvements! :pray:

Most Liked

tonydang

tonydang

I think the answer depends on a lot of things. :sweat_smile:

First, do you have a complex frontend where using a framework like React, Vue, or Svelte would be helpful? If so, you’ll need to decide whether to keep your backend and frontend separate (e.g., Phoenix + Next.js/Nuxt/SvelteKit/Astro) or use a monolithic Phoenix setup.

If you’re sticking with a Phoenix monolith and still want to use a frontend framework, the current options that support SSR (server-side rendering of JS components) that I know of are LiveSvelte, LiveVue, and Inertia.js.

Now, for choosing between LiveSvelte/Vue and Inertia.js: I haven’t used LiveVue, so I can only speak about LiveSvelte and Inertia.js. LiveSvelte is specific to Svelte, while Inertia.js is framework agnostic and can be used with React, Vue, or Svelte. LiveSvelte integrates closely with LiveView, which means it includes all of LiveView’s features, like automatic socket connections and rendering based on socket state changes.

In contrast, Inertia.js doesn’t integrate with LiveView. Instead, it hands off the entire frontend to your chosen frontend framework. It provides SPA-like routing similar to LiveView’s live navigation but without using a socket. For real-time features, you would need to set up your own socket and channels.

I find LiveSvelte offers tighter integration, making the developer experience simpler overall. However, there are some known SSR performance issues and specific challenges (related to making LiveView work in an offline app) that led me to try Inertia.js.

The Elixir Inertia.js adapter has experimental SSR support, and while it sometimes crashes in development, it falls back to non-SSR if it fails. I haven’t encountered SSR issues in non-dev environments. Not integrating with LiveView also avoids some of the offline-related problems I faced.

Both have their pros and cons. I really like LiveSvelte, but Inertia.js solves the specific problems I have better at the moment. That said, I don’t think the issues I have with LiveView and offline functionality are unsolvable—I just haven’t dug into them further since I wanted to try out Inertia.js. Inertia.js isn’t perfect either, but so far, everything seems to just work where it needs to in my current project.

Sorry for the long-winded response! I hope this helps answer your question!

11
Post #7
tonydang

tonydang

Hi @jam — I actually just hacked together a hackathon app this week using SvelteKit + Phoenix Channels, and I think I like it more than using LiveSvelte for PWAs that need to work offline. Specifically, I used SvelteKit in SPA mode. During development, I set up a Vite proxy to talk to Phoenix. In production, the SPA is compiled into Phoenix’s static folder, so I only need to run the Phoenix server — no separate SvelteKit server required.

There are some tradeoffs with this approach, though. Mainly, there’s no SSR unless you prerender pages. But for a PWA with a service worker caching files for offline use, that’s not a big deal — and having the SvelteKit router is great.

You can make LiveSvelte work as an offline PWA, but there are a couple of downsides:

  1. Lack of client-side routing: Liveview has live navigation, but that only works when you’re online. If you want offline routing without page reload, you’ll need to build your own or use a third-party library, neither of which will likely be as full-featured as SvelteKit’s.
  2. CSRF token issues: For offline apps, you’ll need to cache your HTML, which ends up caching the CSRF token used for the LiveView socket connection. This makes reconnecting after being offline for a while tricky with LiveSvelte. I had a very hacky workaround in a previous app, but I wouldn’t recommend it.

In summary, I wouldn’t recommend LiveSvelte for PWAs that need offline capabilities. It’s possible, but right now I don’t think it’s as clean as just using channels.

cblavier

cblavier

Naive question: why would I pick inertia over liveview?
what would be the rationale?

Wojciech

Wojciech

Inertia.js allows for integration between client-side frameworks (React, Vue, Svelte) and server-focused ones (LiveView) so if you have somewhat complex client-side logic you may want to consider using it. I prefer LiveSvelte though.

If you’re using Svelte within your Phoenix LiveView app you can also call LiveView events as LiveView has really convenient JS interoperability.

cblavier

cblavier

Thank you for your comprehensive answer!

Where Next?

Popular in Guides/Tuts Top

kuon
I have a page with a large state that is loaded from DB, let’s call that “data”. I have a root live view that load “data” on mount and r...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
hauleth
Some time ago someone suggested me to write article about how I have configured my Vim to work with Elixir, now there it is: https://med...
New
kokolegorille
Hello dear alchemists, There was this question some days ago here about the deployment to a VPS. As I was in the process of deploying t...
New
OvermindDL1
Ran across this recently, it's a set of cheatsheet inforgraphic things of the OTP behaviours on the BEAM:
New
njwest
In the process of developing a Phx-based multiplayer experience, I found myself with so many browser tabs open with Elixir gaming resourc...
New
berts-4865
Here is a quick guide to uploading a file from the browser to DO spaces. It is crude, but will hopefully save sometime time and frustrat...
New
jswny
Hello everyone, I recently redesigned my entire deployment process for Phoenix apps based on Docker. I really like the strategy that I ca...
New
fmcgeough
pipe into case? I use that fairly frequently…unless I’m misunderstanding what you’re wanting…could be… its still very early… str = "Hell...
New
tonydang
I recently got inertia-phoenix (an Inertia.js adapter for Phoenix) working with Svelte. Setting up the server-side rendering (SSR) with S...
New

Other popular topics Top

Tee
can someone please explain to me how Enum.reduce works with maps
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement