Proposal: Main.attach(node) to attach Elm to existing DOM?

181 views
Skip to first unread message

Rupert Smith

unread,
Jan 12, 2017, 12:02:36 PM1/12/17
to Elm Discuss
What do you think of this idea, to provide a 3rd way in which Elm can be set up in the DOM? 

We currently have .fullscreen() and .embed(node), a third way would be .attach(node). 'attach' would differ from embed, in that Elm would take over rendering from that node down, rather than insert its rendering output as the first child of the node as 'embed' does.

the reason for doing this would be so that the DOM being attached to, would have some additional attributes or possibly a checksum on it, that would enable the Elm virtual DOM code to re-use a section of the DOM that has already been rendered somewhere else. "Somewhere else" is likely to be a server rendered preview of the content so that the page loads and does its first render as quickly as possible. Such a page is likely to defer loading 3rd party content or initializing more interactive parts of the page until the Elm compiled javascript is loaded, which may take a while. Its a familiar technique from progressive or (dare I say it) isomorphic apps.

At the moment if I want to do a quick and approximate render then complete it on the client, I could delete the DOM and have the client completely re-render it. You will see the screen blink; not the end of the world, but somehow not a satisfactory user experience at the same time!

Server rendered virtual DOM is possible to do. For example, we know React can do it: https://facebook.github.io/react/docs/react-dom-server.html

I have yet to figure out how well this would work with Elms current vdom code. The basic idea seems to be to set a flag or a checksum on the nodes, and use that during the rendering to assesss whether or not a section of the DOM needs to be re-rendered. In the case where it does not, the rendering would still need to walk down the existing DOM and attach event handlers, if the client side rendering adds any.

Elm proudly advertises its fast vdom rendering: http://elm-lang.org/blog/blazing-fast-html-round-two

Perhaps this extra checksumming and comparison might slow it down? As the extra work would only need to be done when using 'attach' and not the existing 'embed' and 'fullscreen' modes, I anticipate that it should be possible to avoid slowing down existing code by using one vdom implementation or the other depending on the mode. If it is significantly enough slower, perhaps it might not be. I don't think the slow-down will be much, but I'd hate to be the one that bumps Elm down the leaderboard.

It also brings up the issue of server side Elm which is not officially supported. Adding this to Elm would kind of imply that it is supported, as that is driver behind adding this feature. Does that need to be considered?

I don't need this feature right now, but I may do soon (I'll tollerate the screen blink for now). If folks are generally supportive of this idea, I propose to continue investigating it and write up how to modify the Elm code to do it, also digging into the React code or other implementations.


Duane Johnson

unread,
Jan 12, 2017, 12:45:53 PM1/12/17
to elm-d...@googlegroups.com
I like this direction. One of the things I want in an app is near-instant load time. In addition, this leads nicely toward a server-side Elm "some day" which is another thing I hope for :)

Duane

--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rupert Smith

unread,
Jan 13, 2017, 7:28:06 AM1/13/17
to Elm Discuss
On Thursday, January 12, 2017 at 5:45:53 PM UTC, Duane Johnson wrote:
I like this direction. One of the things I want in an app is near-instant load time. In addition, this leads nicely toward a server-side Elm "some day" which is another thing I hope for :)

Yes, I think adding it would be completely transparent to client only applications.

I said that it might add some complexity or be a little slower but only in the case where 'attach' is being used. A further observation is that the extra complexity would only be needed on the first pass - after that, the client has full ownership of the vdom and could revert to the original algorithm for updating it. So it _might_ have some impact on the first pass when using 'attach', it might also work out that the impact is pretty negligable.

Duane Johnson

unread,
Jan 13, 2017, 11:22:29 AM1/13/17
to elm-d...@googlegroups.com

On Fri, Jan 13, 2017 at 5:28 AM, 'Rupert Smith' via Elm Discuss <elm-d...@googlegroups.com> wrote:
I said that it might add some complexity or be a little slower but only in the case where 'attach' is being used. A further observation is that the extra complexity would only be needed on the first pass - after that, the client has full ownership of the vdom and could revert to the original algorithm for updating it. So it _might_ have some impact on the first pass when using 'attach', it might also work out that the impact is pretty negligable.

Right, but the "impact" in slowness would be made up for in the initial (near instantaneous) client rendering of the server-shipped HTML--so it seems like a good trade-off to me (if the theoretical trade-off exists in the first place :).

Carlton Gibson

unread,
Jan 14, 2017, 2:09:29 AM1/14/17
to Elm Discuss
This is more than theoretical. First rendering delays are noticeable on even moderately highend mobile devices.

Attaching to an pre rendered DOM, optionally enhancing it, is a big win.

It's not just something done in React. (I first saw it in a Backbone application if that helps date it.)

On the performance side, the "time to attach" a price worth paying. You serve a usable interface, you enhance it without a re-render, the pecieved performance is much faster. (And if you JavaScript fails to load you're still in business.)


I'm a big +1 on this. I'm happy to help test, or whatever else I can offer.

Good one!

Carlton

Carlton Gibson

unread,
Jan 14, 2017, 3:04:55 AM1/14/17
to Elm Discuss
One more point here is that using a Program with Flags to pass the initial model state, it's good to parse the model state from the rendered DOM, rather than sending the data (again) as JSON. 

It's easy enough to extract the needed data in JavaScript before initialising Elm but it would be good to have a hook or extension point or... to enable this to be defined in Elm too.

(Rupert: if you're going to work on this, please hit me up for input/help!)

C.

Josh Adams

unread,
Jan 14, 2017, 4:31:17 AM1/14/17
to Elm Discuss
+1

Not much more to add, but figured it was worth mentioning since you're looking for feedback :) I have immediate uses for it but can live without it for a while.

art yerkes

unread,
Jan 14, 2017, 2:49:04 PM1/14/17
to Elm Discuss
+1

As an aside, you can use a dom mutation observer to avoid the blink, but it'd be better with proper support.

Rupert Smith

unread,
Jan 16, 2017, 8:56:21 AM1/16/17
to Elm Discuss
On Thursday, January 12, 2017 at 5:02:36 PM UTC, Rupert Smith wrote:
I propose to continue investigating it and write up how to modify the Elm code to do it.

Any ideas on how to go about working on code that is in elm-lang/virtual-dom ? Specifically, how do I create an alternate version of that, but have existing code that uses elm-lang/html call it?

The normal way I use elm-lang/virtual-dom is to import elm-lang/html in my elm-package.json, and it pulls in the vdom code as a dependency. I don't see a mechanism to exclude a dependency so that I can substitute another in its place. I would fork the vdom code to my own github account, work on it till its right, and then make a pull request in the usual manner.

It seems quite awkward to develop Elm native code that is pulled in through elm-package.
Reply all
Reply to author
Forward
0 new messages