Those who don't like JavaScript and are sitting on the fence about using a reactive framework, I took the bullet and tried Svelte for a Go Web Application. Here are some findings which can save you some frustration and help you decide better.
Svelte, Because it seems like the sanest JavaScript framework of all.
Svelte's original developer Rich_Harris seems like a kind of person who can write a 3D renderer from scratch in JavaScript in a weekend but would choose not to.
The developer matters here because, One of the main reason why I didn't get behind 'React' bandwagon was because Facebook's problems are not my problem. My applications wouldn't need to show hearts, emoji animations immediately when clicked, Track user mouse movements, Scrolling in real-time and send it to the server. Minimal JS is one of the ways I protect my customers privacy.
Even Wikimedia chose Vue.js over React for Wikipedia as they didn't want anything to do with Facebook/Meta even though its open-source. I had used Vue once because of that for my Purchasing Parity Calculator That was my only time with a reactive app.
My goal with Svelte now is to create a dynamic form whose elements are based on nested array values, Update those values in real time from user action and plot a chart dynamically. All these are to be done at the client and no data is sent to the server in real time(Cookie).
Svelte has a good tutorial with REPL, I went through that quickly for what I'd be needing until it got bit tedious; Not particularly a fault on the tutorial, Likely my impatience to start building.
I looked up couple of blogs on Go web application using Svelte front-end & Almost all of them start with changing the rollup.config.js
to add customElement:true
. This was needed to embed the svelte code as web component
into Go template, Since Go has excellent template support most users would be using it and that's exactly what I wanted too.
It felt bit weird that I didn't come across this during the Svelte tutorial, Then again I didn't go through the entire documentation either. In order to bind inputs from a nested each (for loop in Svelte) I had to use separate .svelte files and nest them.
The child components complained that it didn't have tag
(correlating with Go's html template) even though the parent .svelte had one, So I added a dummy tag. The styles are encapsulated in Svelte so I had to duplicate the styles for the form in my parent .svelte from my app CSS. But the inputs from the child .svelte didn't get those styles after rendering.
I tried duplicating the styles (for 3rd time) in the child .svelte but it didn't work. I knew that there's a way we can use a Global CSS in svelte, So I decided to look at it later after I get the logic working.
Getting the dynamic form logic done was a breeze, Thanks to earlier official tutorial and the state management using Stores
feature. Changing the form input values changes the stored variable data automatically, Deleting the form input renders new form reactively, Just what I wanted to do.
I added a generic charting library to render a chart based on those form values dynamically; There were no hassle at Svelte end. The CSP in my application blocked inline-styles
(as one should) and it was complaining about it.
But I had set in the rollup.config to generate a CSS file separately, It seems it wasn't working. Allowing inline-styles rendered styles from parent svelte component, So the CSS seems to be rendered via JS.
I had to look up the Svelte documentation to get clues on why the CSS wasn't generating as a separate file and why nested svelte style were not working. I came across the official Custom Element API doc - https://svelte.dev/docs#run-time-custom-element-api and it mentions several shortcomings when using Custom Element, incl. those I face now.
Namely,
At this point, I noticed that when I remove a form element dynamically the first input field (type=number) of the form shows the validation tool-tip to enter a valid number since the values are in decimals.
I must have ignored this from the start as I knew this was a simple fix of adding step=any
and setting min & max
for the fields. But alas, When I set the step the page reloads when I remove the form element! I tried to debug this in vain and decided to set the step to expected decimal values i.e. 0.1, 0.001 and this brought back the input validation tool-tip again even though the values were perfect. This would confuse my users and is not acceptable. At this point I found the issue titled - 'The Svelte "customElement" feature is not production ready yet !' - https://github.com/sveltejs/svelte/issues/6481.
Sad trumpet noises. The issue particularly lists about several other 'Custom Element' issues incl. 'Nested child components lose their CSS when the parent is used as a custom element'. I went through the discussions and found a particularly alarming statement from a Svelte Member: "Nobody on the core maintainers team is particularly fond of Web Components, and thus there is limited desire to prioritize the issues which set out to provide support further than what currently exists."
I went into the rabbit hole to find why and found this blog from Rich Harris himself - https://dev.to/richharris/why-i-don-t-use-web-components-2cia . Technical opinion aside, All this while I was using something which the developers themselves don't like to use? Why the support for it then?
I deleted the Svelte code and implemented my dynamic form routine in the Go template with fewer lines of code. Yeah, Reactivity is good to have but not at the expense of security and usability.
Would I use Svelte again? Sure; Without Custom Element
like embedding the generated html files directly in Go if the need ever arises. Also perhaps with the Svelte Kit (back-end/SSR framework) if it offers any significant advantage over my Go framework for some problem.
I strive to write low frequency, High quality content on Health, Product Development, Programming, Software Engineering, DIY, Security, Philosophy and other interests. If you would like to receive them in your email inbox then please consider subscribing to my Newsletter.