tmbb
@josevalim has published this video, where he livecodes some improvemens to EEx templates based on ideas from PhoenixUndeadView/Vampyre: Twitch
It was very interesting to see @josevalim going more or less down the same paths while solving a problem similar to my own with my Vampyre/PhoenixUndeadView project.
It’s amazing the way he managed to live code all of that without any preparation. My own solution to more or less the same problem is clearly over-engineered when compared to @josevalim’s solution, but it solves a different problem with different requirements, so it can’t be directly compared. My implementation also took much longer and is not as elegant (again, different requirements, so they can’t be directly compared).
I guess the main take-away from @josevalim’s video is that one can be very naïve when naming the variables, because variables nested deeper into the template will not overwrite the ones outside. I believe I had proved that to myself, but I still wanted unique names, so I went ahead anyway… I still think there is some value in having unique variable names (it makes it easier to inspect the compiled output), but seeing how much simpler it is to implement it the way @josevalim did it, I guess I think it’s not worth it to do it like I did.
The main difference between the new EEx improvements and Vampyre (and the reason why you can’t compare both probjects) is that EEx doesn’t attempt to expand macros and optimize the result (it wouldn’t even make sense in the case of such a generic project as EEx). It might make sense in a more specialized engine, like Vampyre, or the engine in Phoenix.HTML, where one expects a library of widgets to be available. That way, optimizing those widgets as much as possible makes sense.
From now on, I and @josevalim will probably pursue further optimizations in different directions, as explained on this github issue.
I’m still betting on using macros to do as much work as possible at compile-time and generate templates which are as optimized as possible, and regenerate all the dynamic parts each time the template is rendered. That is not as bad as it sounds, as I’ve managed to make the dynamic parts as minimal as possible and to make my templates as flat as possible.
On the other hand, @josevalim is now thinking about optimizing the templates by building a dependency graph on the template assigns, so that it’s possible to optimize only those segment that depend on the data that has changed.
Anyway, this was an amazing video
Trending in Discussions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ai
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #metaprogramming
- #hex










Showing Posts 35 to 26- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
tmbb
Yes, you are there. Vampyre is not there by design. I’ve made the conscious choice of avoiding that optimization for the time being. Sorry if I wasn’t clear.
EDIT: this is a criticism of Vampyre, not a criticism of LiveView
chrismccord
LV allows
assign(socket, a: 1, b: 2, c: 3)and it will will send the minimal dynamic segments as necessary in a single payload, so I think we are there?tmbb
A little offtopic: I’ve had trouble falling asleep last night.
I’ve spent a lot of time thinking about keeping the HTML generation as semantically correct as possible.
That would allow me to send VDOM (again, “Vampyre DOM”, not “Virtual DOM”) fragments to the client (encoded as json, for example, which is even more compact than raw HTML for most use cases). That would allow me to build a Marko VDOM on the client very cheaply and diff that against the Real DOM using morphdom. This would bypass the slowest part of Morphdom, which is to build a DOM from parsing raw HTML strings.
The main problem with this is that I’d be moving more complexity towards the server in exchange for a more performant client. And I have no idea on how to run meaningful JS benchmarks lol. This wouldn’t kill performance on the server, because most of the complexity would happen at compile time. I hope.
tmbb
Yes, that’s true, but it’s also true that LiveView’s design is only made possible because you’re willing to use morphdom on the client. Fortunately for us, morphdom allows us to oretend that the DOM doesn’t exist on the server and simply send binary segments.
Which is a very powerful idea, of course, but one which costs you some performance on the client.
A big difference between LiveView and Drab on one side and Vampyre on the other the first two force the user to manually update the assigns one by one, while I’d like to alllow the user to pass a completely new group of assigns with little performance impact. So yeah, there is a difference in API here that’s impacting the design choices.
josevalim
Right, we are all working on the same domain and we are all exploring different trade-offs at the template level. Texas also tries a different approach, correct?
But I would say those trade-offs came from doing different choices at the high level, user facing API, rather than the opposite (i.e. the template is not dictating how the user API should work).
tmbb
IMO, @grych did pretty much everything that LiveView claims it will do, just with different tradeoffs which naturally led to a different design in the templates.
The main difference is that LiveView (and Vampyre, which derives from the proto-vaporware LiveView demo) are letting the browser handle the entirety of the DOM with the morphdom library.
If one decides not to use the morphdom library (which offloads complexity to the client), them onr mist implement something like Drab. It’s possible that Drab could be enhanced with morphdom with interesting effects too.
The main problem with something like Drab, which tries to preserve the semantic meaning of the HTML is that there are some restrictions on where you can put some HTML tags. Id you had a “neutral” HTML tag which you could nest literally everywhere (say, a
<template>tag), then Drab would be clearly superior to LiveView and Vampyre (and a partial server-side VDOM solution might have been even better).Basically, what LiveView and Vampyre are doing is just a reinvention of Drab in the morphdom world. It’s not clear that our aproach will lead to better performance or a better API than Drab.
I should write about some of the ideas I have fot the API of live controllers.
tmbb
On further thought, if your “change” to
form_formaintains compatibility, I guess i’ll maintain it too. That way, Vampyre will continue to be a drop-in replacement for Phoenix.HTML and can remain available for the total speed junkies who want to try it without changing their templates (assuming I can keep up with al your awesome oprimizations, of course!)tmbb
Sorry, I was still thinking in “Vampyre”… In your architecture that doesn’t make as much sense. I can see it being used in the name for input tags:
<input name="<%| form.name %>[field1]" ...>.The
[fieldI1]suffix is already purely static in Vampyre, as long as you supply a compile-time constant (like the:field1atom). I’m not declaring theform.nameas “fixed” in Vampyre yet because it seems a little too risky: what if the user wants to replace that with a form with a different name? But I think declaring that as fixed (i.e., something that doesn’t change after the initial render) is the right choice.Currently in Vampyre, I have 4 kinds of segments:
<%= ... %>)<% ... %>)<%/ ... %>); this is good for CSRF tokens and static translations (which never change after the initial page render)<%= content %>, wherecontentis a macro that is expanded into a certain format). Container segments can be flattened into the outer template and have their static bits merged.I think that adding the fixed type to LiveEEx is worth it because of some translations that will never change. In a completely localized page, maybe most of the text will be translations. But if those translations don’t depend on the assigns, that’s not a problem to you, I guess.
josevalim
Yeah, that’s what I meant.
FWIW, LiveEEx assumes that any code without assigns is never reloaded. So we kinda get the
<%| %>behaviour for “free”. We will force devs to push their changes through assigns.Also, huge thanks to @grych for braving a lot of this more than a year ago and forcing us to improve the template engine. One of the reasons we can do this now so trivially is because of
handle_beginand custom terminators and other stuff that we wouldn’t have added to EEx without him pushing EEx to its limits at the time.tmbb
Yeah, you’re right. That doesn’t break backward compatibility.
I’d like it if tag worked like
content_tagwhen given a list of arguments. Something like:That would make templates more “semantically correct”, I think. That would be the way forward if I wanted to transition Vampyre’s inner workings into a VDOM. Currently, the
tag/2function incentivizes template authors to dump unclosed opening tags (like you’re doing with form). But it’s a pretty minor issue, and maybe not worth breaking backward compatibility over…You probably mean something like
<%| ... %>, because the thing you’ve written is not valid EEx.