Looking for a guide to setup a pure esbuild and svelte for Phoenix API app

Hi, I wonder if currently it’s possible to have a pretty non standard setup.

Related topic:

In this case I’m thinking about:

  1. Phoenix-based API-only backend
  2. Svelte-based CSR, scoped style and script in svelte file and load on demand frontend SPA with a little help of something like routify
  3. autoprefixer and SASS/SCSS support for simplicity if possible
  4. also if possible I would like to avoid node and webpack if they are not necessary

I don’t need any Tailwind as well as any extra npm package. I’m considering a custom GUI using above setup

@greven Your response especially took my attention. Could please let me know if such build is possible and if so what I need to do to make it work? I’m not scared to work on custom tasks/hex package, so if it’s needed then could you please let me know what steps I need to follow (like download or compile something) in order to get final binary like the esbuild one in newly generated Phoenix project?

If something from above does not makes sense I would like to know why. I know that I’m new in this field who just heard some nice keywords about svelte and simply wants it to be a part of the app. Obviously I’m not asking for a sample project, but just for a step-by-step guide.

Hey.
In your description you say Phoenix based API, so a REST or GraphQL backend. With this you are decoupling the backend from the frontend, and therefore Phoenix doesnt care what you use for your assets, esbuild, SASS, etc. You will need to check SvelteKit docs on how to setup that (tho I think it comes with support for SASS out of the box as it uses Vite).

The routing would be done by Svelte so there isn’t any integration you would need to do between both frameworks. This assuming you want to use SvelteKit.

On the other hand if you just want to use plain Svelte, without SSR, check this: GitHub - woutdp/live_svelte: Svelte inside Phoenix LiveView with seamless end-to-end reactivity

1 Like

As in original post I want to fetch svelte files on demand and use CSR instead of SSR as the frontend is just supposed to use the API and render everything as SPA.

I have already tried running svelte standalone, but I really don’t understand why, when we have esbuild binary, we need to go for node, webpack and even extra server just to serve assets?. If remember correctly current Elixir hex packages for svelte are adding some kind of loader for svelte files in build.js.

I was trying to find if it’s possible and how to make an esbuild binary that simply can load svelte files just like it do for css and js ones.

Maybe in a bit different words … Here is what I would like to have:

  1. Browser send GET on some route
  2. The Phoenix is sending back simple HTML reply (either by small plug or simplest controller)
  3. The HTML in point 2 load the main.css (i.e. layout, variables etc.) and main.js or svelte file
  4. The main.js or svelte file (on client side) calls API to fetch a record and renders it in lazy loaded some (depending on routing) svelte file

So for example:

  1. GET /posts/:id
  2. 200 OK with content <!doctype html><html>…</html> (with head, body, style and script)
  3. XMLHttpRequest: GET /api/posts/:id.json
  4. Browser fetches for example /assets/svelte/pages/post_show.svelte and renders it using specific data from point 3
  5. Optionally svelte file then fetches on demand components files: /assets/svelte/components/header.svelte

It would be just perfect if I would be able to secure on Phoenix side /assets/svelte/admin/**/*.svelte with some custom plug that uses a user’s session token

So far the other solutions I’m aware of:

  1. standalone svelte app (working on other port)
  2. “old way” with esbuild and svelte dependencies from npm using a custom build.js file

Let me know if I have missed anything.

1 Like

Regarding the routing, if you are doing the routing on the Phoenix side, since you mention you want just CSR, you would need to fetch the .svelte file on each route, either manually (through a controller, since you would need to mount the svelte file on each route) or through writing a custom plug to do it for your (and integrate the user’s session too). I haven’t used that solution as since I have moved to Phoenix land, I’ve been using LiveView exclusively.

What you are describing is pretty close to what InertiaJS does.

Regarding making esbuild serve svelte files that is an issue with esbuild itself as it can only serve most common file types out of the box, other file types it needs the equivalent of a loader (like Webpack), in the case of esbuild a plugin. Since this is a custom plugin (there must exist one for sure?), if you don’t want to use node to fetch the deps with npm, simply put it in a vendors folder and manually include it in your custom esbuild build.js entry file.

1 Like

Adding to this, a combination of GitHub - EMH333/esbuild-svelte: An esbuild plugin to compile Svelte components building the components separately to priv/static/assets and then something like this from client side? Svelte Navigator - Lazy Loading • REPL • Svelte

1 Like

So you described pretty nice what I had in mind. I was thinking that I would need 2 plugs:

  1. One that works on “match all” which simply returns 200 OK with the base HTML code
  2. Optionally a second plug called before serving assets that’s checking request path and session token, so on any problem it redirects to let’s say /errors/unauthorized route that could later be handled by svelte component.

Close, yes. However it’s adding an extra unnecessary layer. Better or worse I would handle svelte side, but I was rather asking what’s the best way to configure it with esbuild.

Ah, so after all the build.js is required as there is no way for esbuild to be compiled and used (like in task install_and_run) with svelte loader support, right?

Simple npm install and other dev stuff are of course not a problem. I’m not asking to fetch all dependencies manually, but I’m searching for a guide that does not requires it in prod environment.

@03juan Ok, so this configuration does not require webpack. :+1:

One question … Does this configuration:

require a node in prod environment or it’s just used in build process before deploy the assets?

btw. The fs in buildscript.js is a part of node, right? Since I would work with it in Phoenix project I don’t need fs part, so the node is called here just to run esbuild and it’s loader, right? If so that would be a configuration I’m looking for since binary-only solution would not work.

Apologies for intervening in this discussion without having to contribute in the original question. I am wondering which may be the reasons/requirements for selecting Svelte over Liveview, if these can be shared in this forum.

2 Likes

I haven’t tried this, just ran across these links that I though would be relevant, but assume it would be tied in through implementing the Esbuild plugins example scripts in the Phoenix documentation.

1 Like

Depends on your workflow, you could built all the files in dev and digest them and don’t need node at all in prod or you might decided to build the assets in prod. Normally it’s part of your deployment process, now if you run that in a CI or in the prod VPS is up to you. :slight_smile:

2 Likes

No worries, simply you use:

  1. LiveView for simplicity (99% Elixir code + 1% Hooks)
  2. svelte SPA when you want to make your API as fast as possible

In 2nd point the server does not takes the resources for:

  1. Rendering
  2. Extra communication like click events (phx-click)
  3. DOM updates and especially the animations

In short we move most of work on server or client to provide lightweight apps (LiveView) or fast apps (svelte) as the communication between client and server is limited to data and currently the clients i.e. desktops and mobiles have enough power to not slow down page.

btw. This was already covered in some topic. :slight_smile:

2 Likes

Yes, exactly I had that in mind. Most probably I would deploy from Virtual Machine that have same distribution like prod server.

1 Like

Ok, so the solution is a summary of @greven and @03juan replies:

  1. We can’t use esbuild binary when we need to support extra file types (like svelte files), so that build.js is required.
  2. Depending on strategy the node can be used only on dev and right before deploying app to prod server.
  3. The dependencies can be limited to esbuild + loader (here svelte) + your custom dependencies - all of them can be install using npm install in dev

Many thanks!

4 Likes