I just wrote a blog post entitled Implementing VDOM in Elm. It’s meant as an example of some non-trivial Port usage as well as an example of how VDOM actually works without using very much JavaScript.
I’m interested to hear your comments: both on the actual code as well as on the presentation (which is mostly code with a bit of writing). I’m not sure how clear it is.
I think I’ve managed to simplify the article considerably by introducing the SafeHtml abstraction a section earlier. This allows me to omit a lot more decoders (as they are now trivial) and present extractListeners only once. It also makes the virtual section more focused on the diffing.
“If you want to build your own rendering engine in Elm, I’ve just shown you how. I hope this can encourage some experimentation with cool techniques. One of the popular ones these days is to not diff against a Virtual DOM, but against the real DOM. You can try that pretty easily.”
I would be tempted to try this out by diffing against a server side rendered DOM in the first instance. However, I think this feature is coming in 0.19 right?
I agree, doing rehydration with ports would be interesting, indeed. It would also be interesting to see how an approach like re:dom would perform in real world scenarios that uses the real DOM instead of a virtual DOM and can therefore skip the apply patches to the real DOM stage of VDOM libraries…
I wonder how the performance of this approach differs from the real implementation. It will certainly be worse, but by how much?
I’m starting to think this might be a better idea for real systems than I originally thought. Having control over the rendering means one can easily add more constructors to the Node type. Need a custom kind of element? Bam! Done. In pure elm with a small bit of ports code.
Seems a lot more flexible than trying to hook into the existing virtual dom or trying to use something like Custom Elements.
I’m having a play with your code because I want to try rehydration.
I think there is a small error in the type signature for diffChildren, which should be:
diffChildren : Int -> List SafeHtml -> List SafeHtml -> List Change
diffChildren index before after =
...
Isn’t the useful thing about custom elements that they are opaque to the Elm VDOM though? So you can embed native DOM manipulating code within an Elm application.
But you can do that with a custom node as well. Then the handling code in you port can do the custom dom manipulation based on instructions it gets from the Elm side.