<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="101311" data-post-id="101311">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>And more importantly, can I render the initial<br>
HTML using vampyre/phoenix/whatever (using Elixir) and then use the VDOM implementation from TEA to mutate the DOM using a vdom fragment sent by the server?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101311" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/102">Post #101</a>
	                </div>
	            </div>
              <div id="likers-container-101311" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101311"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #101"></div>
  </section>
</div>
    <div class="postbit" id="101317" data-post-id="101317">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The attraction of using morphodom is that it patches simple HTML strings into the DOM with no further intervention…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101317" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/103">Post #102</a>
	                </div>
	            </div>
              <div id="likers-container-101317" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101317"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #102"></div>
  </section>
</div>
    <div class="postbit" id="101328" data-post-id="101328">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Sorry for spamming my own thread, but if you don’t like the incoherent stream-of-consciousness style, then you have likely stopped reading weeks ago…</p>
<p>I’ve been thinking about <a class="mention" href="/u/overminddl1" rel="nofollow">@OvermindDL1</a>’s suggestions and something’s not right… There are two phylosophical positions:</p>
<ol>
<li>
<p><strong>Templates should generate valid (X)HTML which is easy to analyze statically.</strong> The poor user is weak of spiritand cannot be trusted to generated valid (X)HTML unaided. Also, HTML5 is a freak show and should be erradicated from the face of the earth, not to taint it with its basphemy. This way, you can easily diff and optimize templates in a semantically meaningful way.</p>
</li>
<li>
<p><strong>Templates should generate whatever binary the user feeds into it.</strong> Because the use knows best, the template engine has no type safety whatsoever (Types? What types? The only relevant type for web development is the byte and the iolist!). The template engine better generate exactly what the user asks for! Which will be absolutely valid HTML5 (by pure coincidence, it could be a JPEG file or something like that). This allows things like these: <code>&lt;&lt;%= tag_name %&gt; &lt;%= attr_key_and_val %&gt;&gt;</code> (Closing tag? do I need a closing tag? is this the 00’s?). Semantically, that’s a very dangerous template fragment. It assumes the variables will be strings/iolists that make sense in the context of the rest of the template. And it’s impossible to analyze statically…</p>
</li>
</ol>
<p>So, I’m working firmly in option number 2, while <a class="mention" href="/u/overminddl1" rel="nofollow">@OvermindDL1</a> wants to push me towards option number 1. <a class="mention" href="/u/dgmcguire" rel="nofollow">@dgmcguire</a> is working firmly in option 1. Clearly, both extremes (1 and 2) have merit. Option one holds the key to optimizations both on the server and client. Option 2, well, is compatible with the way Phoenix renders templates and has given me a 12x performance improvement. Which is something…</p>
<p>Is there any merit in an attempt o reconcile both options? Clearly option 1 could benefit from the performance of Vampyre for serverside rendering. But to send the actual minimal diffs, a format which is easy to analyze statically is very important. The VusJS web framework has string templates, but those templates have many restrictions. For example, tag names need to be literals (not variables). IIRC attribute names (not keys!) need to be literals too. In my option, those options <em>make sense</em>… But if there is such thing as a Phoenix way, I think they go against it. The Phoenix user expects to be able to send whatever they want to the browser. They want the freedom of string-based templates. My approach gives us that. As does Chris’ in <code>Phoenix.LiveView</code>.</p>
<p>You generate whatever binary you want, and let the browser make sense of it on the other side. The only difference is that no the browser needs the <code>morphdom</code> javscript library to make sense of what you’re sending. This is very powerful model (even if a little inefficient on the client), and I’m having a hard time letting go of it. On the other hand, I do see the beauty in a system that enforces valid (X)HTML by default…</p>
<p>So, my conclusion is that both extremes (1 and 2) are valid, while the intermediate solutions look like a big mess. Not that one can’t successfully navigate the messy parts, but it’s not going to be easy.</p>
<p>I need to decide whether to commit to option 2 or try an intermediate approach in which everything must compile to a rigid structure that respects option 1. Why is this important? Because if I want to follow option 2, I must reimplement all widgets in Phoenix.HTML as self-optimizing macros. Which is <em>a lot</em> of work. If I decide to implement restrictions that put me firmly in option 1, then I can spare most of that work, because things are much simpler to optimize.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101328" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/104">Post #103</a>
	                </div>
	            </div>
              <div id="likers-container-101328" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101328"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #103"></div>
  </section>
</div>
    <div class="postbit" id="101395" data-post-id="101395">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tmbb" data-post="100" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Ok, I take it on faith that bucklescript-tea (just TEA from here on) is wicked fast.</p>
</blockquote>
</aside>
<p>I hooked it into an existing benchmark that tested a lot of other things like Elm, Vue.js, React, Angular2/3, etc…  It was consistently at least on par with Elm or faster, with nothing else being close.  <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="tmbb" data-post="100" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Bur how do I capitalize on that? TEA seems to be diffing a custom stripped-down VDOM. Is it still fast when it comes doen to patch it ino the real DOM?</p>
</blockquote>
</aside>
<p>Just make your own patcher based on whatever format you encode it in, tea doesn’t seem appropriate for this (although you ‘could’, it would very much want to ‘own’ the DOM and not work with any third-party things, where something like Drab does).  And that benchmarking was patching into a real DOM.  <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="tmbb" data-post="101" data-topic="16533" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Or are you just talking about reimplementing TEA on the server? If TEA is so fast I should youse it to handle the diffs on the client, right?</p>
</blockquote>
</aside>
<p>I’m talking about not using that style at all, that would imply complete ownership and requires more iterating of the DOM than is entirely necessary since you can pre-bake known information at compile-time, something like a JS client that owns its part of the DOM can’t really assume that easily.</p>
<aside class="quote no-group" data-username="tmbb" data-post="103" data-topic="16533" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>The attraction of using morphodom is that it patches simple HTML strings into the DOM with no further intervention…</p>
</blockquote>
</aside>
<p>That still involves iterating the DOM, there’s no point of that, not even Drab iterates the DOM, it literally uses the element ID’s to acquire the element that it directly needs to modify, significantly faster, and if you bake in the known ID’s in the template and into specialized javascript code for each of those elements then it becomes even faster still.</p>
<aside class="quote no-group" data-username="tmbb" data-post="104" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Sorry for spamming my own thread, but if you don’t like the incoherent stream-of-consciousness style, then you have likely stopped reading weeks ago…</p>
</blockquote>
</aside>
<p>Lol, I enjoy it, similar to how my mind works.  ^.^;</p>
<aside class="quote no-group" data-username="tmbb" data-post="104" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<ol>
<li><strong>Templates should generate valid (X)HTML which is easy to analyze statically.</strong> The poor user is weak of spiritand cannot be trusted to generated valid (X)HTML unaided. Also, HTML5 is a freak show and should be erradicated from the face of the earth, not to taint it with its basphemy. This way, you can easily diff and optimize templates in a semantically meaningful way.</li>
</ol>
</blockquote>
</aside>
<p>When you are dealing with javascript and all such, HTML5 should be used and enforced, it <em>is</em> the current web standard and will be for the long forseeable future.</p>
<aside class="quote no-group" data-username="tmbb" data-post="104" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Templates should generate whatever binary the user feeds into it.</p>
</blockquote>
</aside>
<p>This should not be assumed since the whole concept of patching via javascript and all falls flat with it.</p>
<aside class="quote no-group" data-username="tmbb" data-post="104" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>So, I’m working firmly in option number 2, while <a class="mention" href="/u/overminddl1" rel="nofollow">@OvermindDL1</a> wants to push me towards option number 1. <a class="mention" href="/u/dgmcguire" rel="nofollow">@dgmcguire</a> is working firmly in option 1. Clearly, both extremes (1 and 2) have merit.</p>
</blockquote>
</aside>
<p>I personally don’t see option 2 having merit personally, you are throwing out the known domain that this thing will only work in, it won’t work in any other so making it generic outside of the only domain it will work in seems to be losing capability for no reason whatsoever?</p>
<aside class="quote no-group" data-username="tmbb" data-post="104" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Option 2, well, is compatible with the way Phoenix renders templates and has given me a 12x performance improvement.</p>
</blockquote>
</aside>
<p>Option 2 is perfectly sufficient for non-HTML templating, and it should become the standard EEX engine style, but for being able to peel apart element and hotpatching on the fly a remote client canvas then specific knowledge is far superior.  This is going to require 2 implementations of course though, but a lot of shared code between them regardless.</p>
<aside class="quote no-group" data-username="tmbb" data-post="104" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Is there any merit in an attempt o reconcile both options?</p>
</blockquote>
</aside>
<p>I’d personally see it being 1 library with 2 engines (maybe more if you start supporting hot-CSS patching or whatever) with a shared common set of code but specialty implementations where the, for example, HTML5 version spits out not only the bindings and template on each return (like the generic) but also a listing of updateable ID keys and mappings and so forth.</p>
<p>Plus with knowledge of the problem domain then having something like Phoenix.HTML’s <code>tag</code> could literally return some specialized HTML5 tuple object or something (for easy compile-time processing), being significantly easier to make.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101395" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/105">Post #104</a>
	                </div>
	            </div>
              <div id="likers-container-101395" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101395"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #104"></div>
  </section>
</div>
    <div class="postbit" id="101401" data-post-id="101401">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="OvermindDL1" data-post="105" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>That still involves iterating the DOM, there’s no point of that, not even Drab iterates the DOM, it literally uses the element ID’s to acquire the element that it directly needs to modify, significantly faster, and if you bake in the known ID’s in the template and into specialized javascript code for each of those elements then it becomes even faster still.</p>
</blockquote>
</aside>
<p>If you have a sensible representation for HTML (i.e. 3-tuples or something like that), then yea, it is trivial. And I can certainly do it. I even have a number of strategies to parse an EEx template into HTML at compile-time very efficiently.</p>
<aside class="quote no-group" data-username="OvermindDL1" data-post="105" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>This should not be assumed since the whole concept of patching via javascript and all falls flat with it.</p>
</blockquote>
</aside>
<p>You do get that this is the whole point of using morphdom, right? Morphdom takes up a string representing HTML and patches it into the DOM.</p>
<p>And as I said above, this is the “Phoenix way”. Phoenix templates are things that compile into arbitrary iolists with no “type safety” whatsoever. Contrast that with a haskell web framework like <a href="https://www.yesodweb.com/" rel="noopener nofollow ugc">Yesod</a>, which enforces valid HTML at compile time with a mixture of macros and the type system. I would like to work with templates that can be proved to be valid (within reason, of course, no need to go full Applicative-Monad-Functor-Endomorphism + dependent types or whatever is in vogue nowadays). But I’m working within Elixir (and Phoenix!), and trying to validate things at compile time would go against the spirit of both.</p>
<p>Currently, I can just tell someone who wants faster templates to replace <code>use Phoenix.HTML</code> by <code>use Vampyre.HTML</code>. If I start to require type safety and removing flexibility when writing templates then I’ll be creating my own little type-safe world incompatible with everything else, which will be used by a total of 3 people, including both of us <img src="https://forum.elixirforum.com/images/emoji/apple/smile.png?v=15" title=":smile:" class="emoji" alt=":smile:" loading="lazy" width="20" height="20"> By working within the conventions of the Phoenix ecosystem (even if I don’t necessarily agree with them), I make the benefits of Vampyre templates available to the wider community.</p>
<aside class="quote no-group" data-username="OvermindDL1" data-post="105" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>I personally don’t see option 2 having merit personally, you are throwing out the known domain that this thing will only work in, it won’t work in any other so making it generic outside of the only domain it will work in seems to be losing capability for no reason whatsoever?</p>
</blockquote>
</aside>
<p>I think the merit of option 2 is explained above. Again, option 2 is not something I like philosophically, but it’s certainly pragmatic, given the constraints of the Phoenix ecosystem.</p>
<aside class="quote no-group" data-username="OvermindDL1" data-post="105" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>Option 2 is perfectly sufficient for non-HTML templating, and it should become the standard EEX engine style</p>
</blockquote>
</aside>
<p>Option 2 is more or less the way non-HTML templating works. What I don’t think you are appreciating is that what makes option 2 fast in Vampyre is not only the template compiler itself, but also the library of macros for HTML templating. Option 2 is fast <em>precisely</em> because I’m replacing HTML widgets previously implemented as functions (AKA things that do work at runtime) by widgets implemented as macros (AKA things that do work at compile-time)</p>
<aside class="quote no-group" data-username="OvermindDL1" data-post="105" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>Plus with knowledge of the problem domain then having something like Phoenix.HTML’s <code>tag</code> could literally return some specialized HTML5 tuple object or something (for easy compile-time processing), being significantly easier to make.</p>
</blockquote>
</aside>
<p>My <code>Vampyre.HTML.Tag.tag</code> macro already returns a specialized structure for use with Vampyre templates, namely a <code>Segment.container()</code>, which contains a list of static and dynamic segments. Unlike the default <code>Phoenix.HTML.Tag.tag</code> function, which builds an iolist at compile-time. Vampyre’s specialized structures make it probably the fastest possible template implementation for EEx (without messing with the elixir compiler)</p>
<p>I’m perfectly aware of how much simpler my life would be if I implemented the <code>tag</code> widget as you say… In fact, I could probably implement something like Texas in about a week (with proper compile-time optimizations) with the experience I have now, but I’ve deliberately decided to work with binaries alone and leave the hard work of rebuilding/iterating the DOM to <code>morphdom</code> (as <a class="mention" href="/u/chrismccord" rel="nofollow">@chrismccord</a> has done, BTW).</p>
<p>But in the aggregate you’re obviously right. I’ve built a suboptimal solution out of laziness alone. The <em>correct</em> thing to do would be to team up with <a class="mention" href="/u/dgmcguire" rel="nofollow">@dgmcguire</a> and work on a proper VDOM implementation on the server, as you suggest. It would have a number of advantages:</p>
<ol>
<li>
<p>It would be as fast on the initial render as Vampyre is, because I can always compile HTML into super-fast iolists using Vampyre’s optimizing compiler.</p>
</li>
<li>
<p>It would be faster to diff than anything that uses morphdom (I’m taking it on faith because you’re saying it and it’s intuitively <em>obvious</em>, and I won’t become a javascript pro just to benchmark both options…)</p>
</li>
<li>
<p>I can trade higher CPU usage for better diffs pretty transparently (or not, if I decide I want to spend CPU cycles on the client instead of on the server). I’m thinking concretely of diffing lists on the server to send smarter diffs like “replace 3rd child of element with id <code>128736182</code>”, instead of sending the full child list and leaving it up for the client to fix things.</p>
</li>
<li>
<p>Having a VDOM on the server is certainly good from a marketing perspective. After all, everyone and their mother know (or think they know) what a VDOM is, while saying “it’s the fastest iolist renderer around” just makes people say “WTH is an iolist?”</p>
</li>
</ol>
<aside class="quote no-group" data-username="OvermindDL1" data-post="105" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>Just make your own patcher based on whatever format you encode it in</p>
</blockquote>
</aside>
<p>For simple cases (setting attributes and stuff like that), I can do it manually. For more complex cases, like replacing the children of an element, I can always use morphdom.  It’s a pretty good patcher actually. Or I can reuse some other VDOM library and sending pre-made patches from the server (encoded as JSON, BERT, HTML or whatever)…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101401" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/106">Post #105</a>
	                </div>
	            </div>
              <div id="likers-container-101401" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101401"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #105"></div>
  </section>
</div>
    <div class="postbit" id="101402" data-post-id="101402">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mischov" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mischov/120/2489_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mischov
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="OvermindDL1" data-post="105" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<blockquote>
<ol>
<li><strong>Templates should generate valid (X)HTML which is easy to analyze statically.</strong> The poor user is weak of spiritand cannot be trusted to generated valid (X)HTML unaided. Also, HTML5 is a freak show and should be erradicated from the face of the earth, not to taint it with its basphemy. This way, you can easily diff and optimize templates in a semantically meaningful way.</li>
</ol>
</blockquote>
<p>When you are dealing with javascript and all such, HTML5 should be used and enforced, it <em>is</em> the current web standard and will be for the long forseeable future.</p>
</blockquote>
</aside>
<p>Just don’t count on Floki to get the parsing right if you want HTML5. <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101402" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/107">Post #106</a>
	                </div>
	            </div>
              <div id="likers-container-101402" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101402"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #106"></div>
  </section>
</div>
    <div class="postbit" id="101404" data-post-id="101404">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="mischov" data-post="107" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mischov/48/2489_2.png" class="avatar"> mischov:</div>
<blockquote>
<p>Just don’t count on Floki to get the parsing right if you want HTML5. <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>Don’t worry, I don’t count on anything at all to parse HTML5 right <img src="https://forum.elixirforum.com/images/emoji/apple/smile.png?v=15" title=":smile:" class="emoji" alt=":smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101404" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/108">Post #107</a>
	                </div>
	            </div>
              <div id="likers-container-101404" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101404"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #107"></div>
  </section>
</div>
    <div class="postbit" id="101406" data-post-id="101406">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Although Floki actually supports self-closing tags, which is actually pretty good:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex&gt; Floki.parse(~s'&lt;input value="x"&gt;')
{"input", [{"value", "x"}], []}
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101406" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/109">Post #108</a>
	                </div>
	            </div>
              <div id="likers-container-101406" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101406"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #108"></div>
  </section>
</div>
    <div class="postbit" id="101407" data-post-id="101407">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tmbb" data-post="106" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Morphdom takes up a string representing HTML and patches it into the DOM.</p>
</blockquote>
</aside>
<p>That sounds fairly horrifyingly inefficient…  ^.^;</p>
<p>Depending on how it works (swapping?) it could cause lose of HTML state too (like editing an input box that suddenly clears just because something was patched).</p>
<aside class="quote no-group" data-username="tmbb" data-post="106" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Contrast that with a haskell web framework like <a href="https://www.yesodweb.com/" rel="noopener nofollow ugc">Yesod</a>, which enforces valid HTML at compile time with a mixture of macros and the type system.</p>
</blockquote>
</aside>
<p>Oh that sounds blissful.  ^.^</p>
<p>But still, Floki can verify and parse it quite well.</p>
<aside class="quote no-group" data-username="tmbb" data-post="106" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Currently, I can just tell someone who wants faster templates to replace <code>use Phoenix.HTML</code> by <code>use Vampyre.HTML</code> . If I start to require type safety and removing flexibility when writing templates then I’ll be creating my own little type-safe world incompatible with everything else, which will be used by a total of 3 people, including both of us <img src="https://forum.elixirforum.com/images/emoji/apple/smile.png?v=15" title=":smile:" class="emoji" alt=":smile:" loading="lazy" width="20" height="20"> By working within the conventions of the Phoenix ecosystem (even if I don’t necessarily agree with them), I make the benefits of Vampyre templates available to the wider community.</p>
</blockquote>
</aside>
<p>For an HTML parser sure, Floki would verify it is all written properly (or the user would get warnings/errors about invalid html, I’d opt for errors as that would be a bug regardless).  For the generic non-html parser, that’s stimple string munging then.</p>
<aside class="quote no-group" data-username="tmbb" data-post="106" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>My <code>Vampyre.HTML.Tag.tag</code> macro already returns a specialized structure for use with Vampyre templates, namely a <code>Segment.container()</code> , which contains a list of static and dynamic segments. Unlike the default <code>Phoenix.HTML.Tag.tag</code> function, which builds an iolist at compile-time. Vampyre’s specialized structures make it probably the fastest possible template implementation for EEx (without messing with the elixir compiler)</p>
</blockquote>
</aside>
<p>That also means that people that want to make their own things have a lot more hoops to jump through because it is designed to be implanted into a generic system instead of something domain-specific (as HTML is).</p>
<aside class="quote no-group" data-username="tmbb" data-post="106" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>and work on a proper VDOM implementation on the server, as you suggest.</p>
</blockquote>
</aside>
<p>Eh, don’t need a VDOM on the server, only at compile-time where it’s information is used to build the specific processes to perform efficient hotpatching, the vdom would not exist past compile-time.</p>
<aside class="quote no-group" data-username="tmbb" data-post="106" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>It would be as fast on the initial render as Vampyre is, because I can always compile HTML into super-fast iolists using Vampyre’s optimizing compiler.</p>
</blockquote>
</aside>
<p>Yep, initial render would be virtually indistinguishable to a generic templater (aside that it should return and/or inject javascript for fast in-position hotpatching).</p>
<p>A quick look at morphdom makes it look like it is passing the string to the browser and having it create all elements, then it transforms the differences from the instanced elements to the DOM elements, then destroys the instanced elements… that seem pretty horrifying…  ^.^;</p>
<p>Some quick googling on performance of it shows it is not too bad at element to element diffing (understandable, they are native), but the instancing of the string to an element tree is not very fast, and there are hicks in FPS and performance when the elements are later garbage collected.  It is not something you want to call on large DOM trees or with rapid changes (both of which Drab entirely and fully supports without issue).</p>
<aside class="quote no-group quote-modified" data-username="tmbb" data-post="106" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>I’m thinking concretely of diffing lists on the server to send smarter diffs like "replace 3rd child of element with id <code>128736182</code> ", instead of sending the full child list and leaving it up for the client to fix things.</p>
</blockquote>
</aside>
<p>Yep this here!  I think there is even a JSONPatch spec that would make that more simple too.</p>
<aside class="quote no-group" data-username="mischov" data-post="107" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mischov/48/2489_2.png" class="avatar"> mischov:</div>
<blockquote>
<p>Just don’t count on Floki to get the parsing right if you want HTML5. <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>I thought it added an HTML5 parser not too long ago that was optionally selectable?  It’s mainly useful if you intend to ‘edit’ the html anyway, if just reading the meeseeks is better/faster.</p>
<p>I havn’t seen Floki go wrong with any of my HTML that I’m using with Drab for near on a year now though.  Do you have examples of correct HTML where it fails?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101407" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/110">Post #109</a>
	                </div>
	            </div>
              <div id="likers-container-101407" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101407"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #109"></div>
  </section>
</div>
    <div class="postbit" id="101408" data-post-id="101408">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="OvermindDL1" data-post="110" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>I thought it added an HTML5 parser not too long ago that was optionally selectable?</p>
</blockquote>
</aside>
<p>I’s a parser written in Rust for Firefox. You definitely don’t want to require an instalation of Rust in the user’s machine to compile templates.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="101408" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/111">Post #110</a>
	                </div>
	            </div>
              <div id="likers-container-101408" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="101408"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #110"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/16533/load_more?page=12">Load more posts (31 remaining)</a>
</div></template></turbo-stream>