I've been thinking about efficently re-rendering Twig template in the browser recently...
Given this template:
<div>{{ variable }}</div>
{% if flag == true %}
<div>{{ variable2 }}</div>
{% endif %}
And this context:
{
variable: "foo",
variable2: "bar",
flag: true,
}
You would get the render:
<div>foo</div>
<div>bar</div>
What if we decorated the template like so at compile time:
{% if hasChanged(variable) %}
<!--variable-0-start-->
<div>{{ variable }}</div>
<!--variable-0-end-->
{% endif %}
{% if hasChanged(flag,variable2) %}
<!--flag-0-start,variable2-0-start-->
{% if flag == true %}
<div>{{ variable2 }}</div>
{% endif %}
<!--flag-0-end,variable2-0-end-->
{% endif %}
Where hasChanged
is a hypothetical method that knows is variables changed between renders.
The 0
is there because there may be many instances of a variable. In this example there's just one of each.
Then the first render would be:
<!--variable-0-start-->
<div>foo</div>
<!--variable-0-end-->
<!--flag-0-start,variable2-0-start-->
<div>bar</div>
<!--flag-0-end,variable2-0-end-->
If you rendered the template again, and changed flag
to false, the render would be:
<!--flag-0-start,variable2-0-start-->
<!--flag-0-end,variable2-0-end-->
Then when updating the DOM, we would just look for the comment boundry and update what's inside that (with an empty string).
I think the logic needs to be more complex to efficently support nested blocks, but this would save a lot of render time.