Closed sumeetdas closed 2 years ago
Hi Sumeet,
Sutil works by reacting to events, and rebuilding DOM directly. Sutil defines a way of representing fragments of HTML that you mount
into a pre-defined element, and we call that a DSL. The DSL allows you to specify elements, attributes, event handlers, as you would in a plain .HTML file with JS, but additionally, it allows you to bind sub-DSLs to events. For example
let app() =
Html.div [
Attr.style [ Css.color "red" ]
text "Hello World"
]
mountElement (app()) "sutil-app" // May have this syntax/argument ordering slightly wrong
just builds a simple DIV that says "Hello World" in red, as you'd expect. However you can also do
let textSource = Store.make "Hello world"
let app() =
Html.div [
Attr.style [ Css.color "red" ]
Bind.element( textSource, fun s -> text s )
]
mountElement (app()) "sutil-app" // May have this syntax/argument ordering slightly wrong
We've now rewritten the static fragment as something that can now react to changes made via textSource
. Sutil handles the event listening and DOM reconstruction. It will rebuild the DOM directly into the page though, and not via a virtual DOM.
There really isn't a lot of magic to it! Does this help?
Adding to Dave's Explanation. Webpack is a dev time build dependency which can be swapped for other tools like vite/snowpack in case you know a little bit more of the node ecosystem.
but if we skip the node part (which we can), in simple terms it uses fable to compile down the F# code to javascript, in turn that javascript does what Dave just explained
Thank you Dave and Angel for the explanation. I still have one question - Svelte dropped virtual DOM and instead determines at build time how code will change and update DOM accordingly. Is that what Sutil does too using Store
as in the above code? Is Store being used to implement all build-time diff logic and not just for text input-related events?
Edit: I want to ask another question - if I create a new web component like custom-form
on top of Sutil, push it to NuGet as a library called 'Custom.Form' and import it into my project, then would Fable compile Custom.Form
into JS? I don't also have to build it into JS first, push it to npm registry and then use it as an npm dependency later, correct?
Sutil is indeed inspired by Svelte (and was initially called Sveltish). So, you are correct - though I'd rather say it as "Store is providing an observable stream of events that is used to make changes to the DOM at run-time".
Re: custom-form
Nice question. If you export your component as an F# (Sutil) component, then you just import as you would any other F# library, reference it from the DSL for your app and Fable handles it.
If however you make a Web Component
(https://developer.mozilla.org/en-US/docs/Web/Web_Components) from your component, in theory, you can just make this an NPM JS package. Fable is compiling the Sutil component into a Web Component
and you ship the generated .js
files. This is in theory! We did some work on Web Component
support but I'm not sure it's been proven in a real web site yet. The proofs-of-concept seemed to work well though.
Thank you Dave for your answers! F# (Sutil) component approach works for me, as I would like to minimize NPM dependencies as much as possible.
Hello @davedawkins! I just came across your project and what I really like about it is how it does not have any JS dependency to install (as per HelloWorld sample), except for webpack. The docs, however, does not explain it in detail as to how Sutil really works. Could you please explain it works? From what I've understood so far, Svelte compiles HTML + JS + CSS into JS and CSS. Does Sutil too compile F# code to JS? If yes, then how is it different from Fable compiler?
Sorry if the question is not very clear. I just want to understand how Sutil works. Thank you.