nanoc / features

Collection of feature requests
2 stars 1 forks source link

Add caching option for partials #6

Open connorshea opened 7 years ago

connorshea commented 7 years ago

Right now I have a header partial added to every page in our documentation. It's using dynamic URLs rather than static to ensure that the data it pulls from is updated when we add new versions.

Simplified version of the header partial:

<div class="header">
  <a href="/">
    <%= logo %>
    <p>GitLab Documentation</p>
  </a>
  <div>
    <ul>
      <%= search %>
      <% @config[:products].each do |name, product| %>
        <li>
          <%= link_to_stable %>
          <ul>
            <% product[:versions].each do |version| %>
              <%= link_to_version %>
            <% end %>
          </ul>
        </li>
      <% end %>
    </ul>
  </div>
</div>

Essentially, every version's README needs to be found for the dropdowns to be generated (link_to_version is actually <a href="<%= @items["/#{product[:slug]}/#{version_name}/#{product[:index_file]}"].path %>">), which is expensive to compute on every single page. The content is entirely static and could be cached and reused across every page on the site which would make the site a lot faster.

Adding caching to the partial, a la Rails' partial caching would be a huge benefit for us.

Right now in layouts/default.html we have:

<%= render '/header.*' %>

I would imagine caching would just look like:

<%= render '/header.*', cache: true %>

It could also be called static? Perhaps to simplify the code, cached partials couldn't use yield?

Thoughts?

gpakosz commented 7 years ago

I wonder whether that could be just a matter of adding memoization to the #render() helper.

You could also do it the following way:

This would effectively build the nav once and make all other items depend on it.

connorshea commented 7 years ago

@gpakosz interesting idea, trying that now, thanks! :)

connorshea commented 7 years ago

Before: 808.68s.

After: 419.13s

Almost 50% cut off the compile time, awesome! Thanks for the suggestion @gpakosz. 🎉

I still would prefer if this were implemented as part of the Rendering helper though.

gpakosz commented 7 years ago

@connorshea Please try https://github.com/gpakosz/nanoc/tree/rendering-memoization

denisdefreyne commented 7 years ago

Generalised caching is not trivial because of dependency generation. When a partial is initially compiled for a item, it might (probably will!) generate dependencies on other items and layouts. When an item uses a cached partial, Nanoc needs to generate the same dependencies for the item for which the cached partial is used.

This extends to helper caching in general (not just for #render) and that’s something I haven’t tackled yet (definitely a tricky subject).