I’ve spent the last month building the backend of my project (Transportation Management System+CRM) in Go, while changing my mind daily on what to use for a frontend. I advocate for anything that emphasizes simplicity, and I know that is why I should use HTMX, but it does come with design limitations down the road. My JavaScript/Typescript experience is minimal, I consider it a necessary evil. Just by comparing the syntax of React vs. Vue vs. Svelte, it seems like a simple solution that Svelte is my answer.
I know some of you will hate hearing this, but I do chat with LLMs to get ideas and to learn (always verify, hence this post). When I asked what the tech-stack & file structure would look like when using Svelte with Go, it recommended SvelteKit over Svelte, with the reasoning being Server-Side Rendering. Forgive my ignorance (I coded in VB 6.0 & C++ from 1995-2002, then picked up Apex & Python in 2023), but it is my understanding that the purpose of using Go on the backend is to keep JavaScript on the client; as far away from the server as possible where I believe it should have stayed (thanks Ryan Dahl).
Can anyone spare a few minutes educating me on this topic?
Hi Anthony,
Chatting with LLMs is fine. They give you good ideas. But they tend to be upper average.
(But not really experts)
First of all, frontends are difficult. Not really from a technical perspective, even though you CAN actually mess something up if you do not plan it properly and then you have a BIG technical debt.
The problem is the user and that you have to “explain” intuitively what your app does. Users are lazy, dumb, nice, evil, and super smart at the same time. Today you cannot expect them to read a manual.
What to choose depends really on what you need to build. Will this be public? I mean do you need SEO for dynamic content? If No, I highly recommend CSR. (Even if the LLM says SSR)
Personal opinion:
My stack is React Vite and I am really happy with this. (But no experience with Svelte)
I cannot recommend HTMX. I posted about this. I think this is just a hype.
SSR is often just still in the heads for legacy reasons. I see the frontend as an actual app as every browser has awesome features and every device is actually a supercomputer. The backend is an API.
In the backend, Go is perfect, I am so happy every time I am allowed to use it. You will be fine.
Everyone I ever talked to was happy once they seriously tried Go
Hope I could help.
Well, it depends entirely on how you use Go. You can generate 100% of your site server-side in Go (using templates, etc.) and never use a front-end framework or JavaScript at all if you want. You can also use a hybrid approach where you generate HTML using Go but then use JS/front-end frameworks to do differential loads. You can also use a traditional SPA framework like React where you ship JavaScript to the client which then manipulates the DOM.
I am not super familiar with Sveltekit and how they handle SSR. But - for a client library to handle SSR you have to have some sort of runtime on the server. It looks like they have the concept of “adapters” for specific targets:
It looks like most people combining svelte and go are using “static” adapter and then just serving that content up with Go. I don’t know how that would be able to prerender something with dynamic data from a RESTful API (you would need a server-side runtime for that). But maybe give the static adapter a try and see if it works for you.
I love the concept of everything being SSR, but for this project (which is completely internal, there is no need for SEO), I believe I’m adding a layer of complexity (by my standards/skill set) by asking Svelte to SSR, in addition to Go.
@Dean_Davidson – regarding your post, could I keep my Go + Supabase backend, and simply write the frontend in Svelte as CSR? It’s my understanding that Svelte is a compiler, and will turn the code directly into JavaScript; circumventing the concept of a Virtual DOM.
Yes. Probably the easiest way you could do this is: build your app using Svelte (which will leave you with JS/HTML), then serve that static content from your Go executable. I do a similar approach all the time. When doing deploys, have your front-end framework compile to ./public or something similar, then serve that static content like this:
The only other “gotcha” to CSR is: they can land on any page in your app and/or hit refresh button so you need to either have a fallback that serves index.html on “not found” or keep track of routes and serve index when a user lands on a route like yourapp.com/users/1:
// For all SPA routes we will also serve up /index.
// Register any front-end routes here
spaRoutes := []string{
"/home",
"/faq",
"/login",
"/users/{id}"}
for _, route := range spaRoutes {
http.HandleFunc(fmt.Sprintf("GET %v", route), indexHandler)
}
Where indexHandler just serves up index:
func indexHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./public/index.html")
}
There are other ways of accomplishing this as well but this is probably the simplest.
In terms of your API and how it interacts with your web app: you would just create routes that return JSON and your Svelte app would update the UI based on your RESTful API. Again - I’m not a Svelte dev but something like this:
// main.go where you are setting up routes
http.HandleFunc("POST /api/items", getItemsHandler)
//...
func getItemsHandler(w http.ResponseWriter, r *http.Request) {
// Fetch items from wherever
items := getItems()
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(items)
}
Create a load function in svelte (or something similar):
<script lang="ts">
import type { PageProps } from './$types';
let { data }: PageProps = $props();
</script>
<h1>Items</h1>
<ul>
{#each data.items as item}
<li>{item}</li>
{/each}
</ul>
I don’t know about the virtual DOM in the svelte world. Frameworks use virtual DOMs because DOM manipulation is expensive. By keeping track of changes you can only update the DOM when you need to. So, I’m not 100% sure how svelte manages its’ DOM manipulation but I wouldn’t worry about that too much.
There is no reason why your Svelte App needs to be SPA. I have been coding with Go Backend and Svelte Frontend for years - and I usually go with a multi-page approach. Just serve multiple HTML files if you need multiple pages, if you need some persistent state on the client it can easily be shared in session-storage between pages.
How are you returning that server-side rendered as HTML with the title and content filled in? Or are you using what I would call a hybrid approach where you are just returning a blank title/content and the client uses the fetch API and sets title/content? This is the only part that confuses me about Svelte because in order to truly render things server-side you need some kind of runtime on the server.
But often the data will be reloaded on demand and dynamically with different queries (e.g. paging table data), so JavaScript does the loading and svelte dynamically updates frontend tables.
What I did occasionally to improve first page load performance for internal pages is to insert the data server side with go using the go template engine. But I insert the data as json directly into JavaScript and let svelte do the rendering into frontend components.
// go inserts data into this string literal:
const serverData=`{{data}}`
...
//Svelte passes the data down to components to safely render complex structured data
<Table data={data.rows}>
And for most public sites I use Atro as a build tool for svelte, which uses static rendering at build time and hydration, this gives perfect SEO performance without any server side requirements, since only user specific dynamic content is loaded via fetch API, giving a nice combination of fast caching for static data and fast rendering due to hydration.