Skip to content

Instantly share code, notes, and snippets.

@mortenson
Last active April 16, 2018 23:40
Show Gist options
  • Save mortenson/c63d2ed3d89c444c54ad37758b4d228f to your computer and use it in GitHub Desktop.
Save mortenson/c63d2ed3d89c444c54ad37758b4d228f to your computer and use it in GitHub Desktop.
Thinking about Twig.js re-rendering

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment