Svonix - Svelte & Phoenix > 1.6 - easily create and use Svelte components in Phoenix

Hello all,

I’ve been working on Svonix - a library for quickly integrating Svelte components into Phoenix views. It’s a much-needed successor to Sveltex given that it’s been more than two years since any updates have been rolled out (Phoenix 1.6 is not supported), and because I couldn’t find any other libraries for integrating Svelte components with Phoenix views in a pleasant manner.

So far it’s been a real pleasure to use, with minimal (if any) pain points. It even includes a mix task that runs most of the tedious setup.

This is my first real attempt at a library, and I would love any help from others interested in Svelte + Phoenix integrations. I’ve been building it as I work on another project, and have been pretty lax regarding testing given that I’m not sure how to even go about testing a lib for Phoenix.

Other than that, I hope people find it useful - so far I’ve loved the productivity boost of being able to quickly integrate Svelte whenever more interactivity is called for, while still being able to use Phoenix views for most of my static content.

Have a lovely day!

24 Likes

I’m not really familiar with the svelte ecosystem so forgive me if its a dumb question, but why not use the esbuild svelte plugin (esbuild - Plugins) instead of replacing esbuild?

1 Like

Not at all! This is actually the next step I’m hoping to take, it’s just that I’m way more familiar with Rollup than I am with ESBuild, so I went with the former for my current project.

2 Likes

Oh I see. That makes sense :smiley:

That’s a cool library. I wonder if there’s also something similar for VueJS.

2 Likes

@cpgo Just updated the lib to use ESBuild - thank you for the suggestion, recompilation is much snappier!

3 Likes

Whoa that was fast!
I may use this as an excuse to start learning svelte again.
It looks like your readme link still points to rollup

1 Like

@nikokozak I really like that Svelte minifies transfer by fetching only required code. I was interested in this topic for a longer time. However I do not understand one thing …

We have LiveView which gives us a low resources usage at client side and I see that in theory we can go fully into Svelte SPA to have the reverse case. However what’s the sense of using any JavaScript only partially?

Do you think it’s reasonable to have only API over Phoenix channels and then use Svelte for the SPA to minify server resources usage or maybe this approach is too extreme?

Do you plan to support or if there is nothing extra needed just write documentation how to setup Svelte SPA using your library?

2 Likes

I like the thought of a svelte SPA (possibly with node or deno on the server-side), but having a phoenix API as well as a svelte store implementation, which uses channels to sync data with the SPA similar to liveview, but as you said, kinda in reverse.

3 Likes

I am sorry if this is dumb, but

Can you give a real world scenario for this reverse Svelte implementation? Like where this sort of thing would be “necessary”?

1 Like

“There is no such thing as a dumb question”

Carl Sagan, The Demon-Haunted World: Science as a Candle in the Dark

:wink:

How about you want to render huge amount of data? I believe that in such case you may decide to stream data using Phoenix channel and render one entry or graph at a time, so the first (ordered or just most important) things would appear immediately. In some cases deliver content as soon as possible may be critical. Even on typical forums you have either pagination or render when needed strategies i.e. you never have rendering list of all topics.

@Eiji I’m going to be looking at providing support for SPA’s (haven’t looked at what that would entail, if anything - I almost think that you could get by with one “master” component that’s injected into one view as-is in terms of what the library supports now, but it might be more reasonable to define a separate build process in case an SPA is the goal), and hopefully building out some small JS helpers to help with websockets on the Svelte side. I think the approach you suggest is interesting, and definitely worth exploring.

In terms of why use JS only partially - the library came about because I was designing a few “games” that were far too complex to make work using only LiveView, and that had to be scattered throughout the site, and Svelte seemed like the perfect tool for the job. Nonetheless, the site still benefits from being SSR’d, given the nature of the domain. That being said - I’m sure most of what I’m doing could be replicated in LiveView with enough sweat and tears, I just found that the moment I made the conceptual shift to working with Svelte for these small components, I felt much more productive and “in control” (granted, I’m also sacrificing the simplicity of keeping it all in Elixir).

1 Like

@nikokozak Oh, I see … Obviously LiveView is not the answer for everything as simply thee is no rule without exceptions. :smiling_imp:

Also you are right that some things at least at start are not easy in LiveView. I’m not into the gaming, but I can imagine that uploading files in LiveView also was complicated. If we would go for gaming then we would need to have something like LiveCanvas or LiveGL which is definitely too much effort for a small project and introducing alternative “cheap” solution like this makes perfect sense.

Thanks for clarification. :+1:

1 Like

I am very interested in this project.

I’ll love to contribute.

1 Like

You might want to check this project out.

4 Likes

Looks really interesting, but this is for raw ws connection, so someone would need to modify or rewrite it to support Phoenix channels … Anyway it may be amazing starting point, many thanks!

Would this make it possible to utilize Svelte for SPA parts and use Live View along with it for server rendered html?

This way it would be possible to build a complete SPA/website that is snappy on client side but keeping things you want to on the server to remain there using Live View

1 Like

If I understand your question - I think in theory yes. For example, you could have a whole live-view based series of routes in your site (for example, your “index”, “about us”, etc. all of these using some form of dynamic data where LiveView makes sense), but also have a single “master” Svelte component rendered in your “authorized” routes (i.e. the actual “app” the user uses when logged in), which would act as an SPA.

That said - in my experience I haven’t really found integrating Svelte + LiveView to be particularly useful (unless you want to do websocket stuff, then LV makes a ton more sense), in that they’re both ways of targeting the same need, except that LiveView allows you to avoid writing JS.

1 Like

Hey @nikokozak I’m running into this issue where I’m getting the error:

  The plugin "svonix" was triggered by this import

    js/app.js:2:7:
      2 │ import 'svonix'
        ╵        ~~~~~~~~

1 error
[watch] build finished, watching for changes...
/Users/chrisking/Projects/myapp/assets/node_modules/esbuild/lib/main.js:1601
  let error = new Error(`${text}${summary}`);
              ^

Error: Build failed with 1 error:
build.js:100:91: ERROR: [plugin: svonix] path is not defined

My watchers are the following and I’ve done the import 'svonix'

watchers: [
    # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
    node: ["build.js", "--watch", cd: Path.expand("../assets", __DIR__)],
    esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
    npx: [
      "tailwindcss",
      "--input=css/app.css",
      "--output=../priv/static/assets/app.css",
      "--postcss",
      "--watch",
      cd: Path.expand("../assets", __DIR__)
    ]
  ]

Any idea what’s going on?

Thanks for making this :slight_smile:

1 Like

Hi @Morzaram! Hmmm… I tested your watcher setup on a similar project I have (tailwind, etc) and it didn’t throw an error.

Two things that pop into my mind:

  1. I don’t include the esbuild watcher in my watchers, given that build.js does that for me (specifically, watches any .svelte files we’re building). Nonetheless, as I tested it just now, it should work.
  2. The way the esbuild flow works, as declared in build.js, is that it looks for the import 'svonix' statement and replaces it with a whole block of code dictating how our compiled .svelte files are mounted into our site’s html. In other words, the fact that it’s throwing that error means that this replacement is not happening, and esbuild is actually looking for a svonix path in your node_modules. Granted, my diagnosis might be wrong, but I think there’s something either a) preventing build.js's esbuild rules from happening, or b) a secondary esbuild process is running after the one defined in build.js, encountering import 'svonix', and thinking it’s a node_module.

I hope this helps - I’ll take a more in-depth look this afternoon, thanks for bringing this up!

EDIT: Actually, nevermind - what’s causing the error is the inclusion of this line: esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}. I’ll take a look at what exactly this is doing for us, and whether we can get around the error whenever this is declared. As I mentioned before, watching .svelte files shouldn’t be an issue - is there any specific reason you’re including this line?

1 Like