Given a partial render call in Rails for an non-ambiguous partial file (which we want to encourage in the Linter through #160, #181), we could optimize these render calls, so we can avoid the slow partial file lookup at runtime.
Example:
app/views/posts/index.html
<h1>Posts</h1>
<% @posts.each do |post| %>
<%= render partial: "posts/post", locals: { post: post } %>
<% end %>
app/views/posts/_post.html.erb
<article id="<%= dom_id(post) %>" class="post">
<h1><%= post.title %></h1>
<p><%= post.body %></p>
</article>
Option 1: Inline Partial
We could entirly eliminate the partial call by inlining the app/views/posts/_post.html.erb partial when we are compiling the app/views/posts/index.html view file. There are probably a few cases where this wouldn't work, like recursion, maybe deeply-nested partial calls, etc.
But effectively, before compiling app/views/posts/index.html we would transform it to this:
<h1>Posts</h1>
<% @posts.each do |post| %>
<article id="<%= dom_id(post) %>" class="post">
<h1><%= post.title %></h1>
<p><%= post.body %></p>
</article>
<% end %>
So when we compile it, it would result in:
__herb = ::Herb::Engine; _buf = ::String.new;
_buf << '<h1>Posts</h1>
'.freeze; @posts.each do |post|; _buf << '
<article id="'.freeze; _buf << ::Herb::Engine.attr((dom_id(post))); _buf << '" class="post">
<h1>'.freeze; _buf << __herb.h((post.title)); _buf << '</h1>
<p>'.freeze; _buf << __herb.h((post.body)); _buf << '</p>
</article>
'.freeze; end; _buf << '
'.freeze;
_buf.to_s
And thus eliminating the slow partial file lookup at runtime.
Option 2: Rewriting the render call
Instead of inlining the partial, we could rewrite the render call to use the Action View-internal method directly. When Action View compiles the HTML+ERB files in app/views/** it defines methods for each template file it compiles.
So when we compile app/views/posts/_post.html.erb it will expose a method like _app_views_posts__post_html_erb_[digest]_[number]. Knowing this fact at compile time, we could rewrite the render partial call in app/views/posts/index.html to something like:
<h1>Posts</h1>
<% @posts.each do |post| %>
- <%= render partial: "posts/post", locals: { post: post } %>
+ <%= _app_views_posts__post_html_erb_[digest]_[number](post) %>
<% end %>
and with that, we avoid the slow partial file lookup at runtime which should improve the performance when rendering this view at runtime.
Given a partial render call in Rails for an non-ambiguous partial file (which we want to encourage in the Linter through #160, #181), we could optimize these render calls, so we can avoid the slow partial file lookup at runtime.
Example:
app/views/posts/index.htmlapp/views/posts/_post.html.erbOption 1: Inline Partial
We could entirly eliminate the partial call by inlining the
app/views/posts/_post.html.erbpartial when we are compiling theapp/views/posts/index.htmlview file. There are probably a few cases where this wouldn't work, like recursion, maybe deeply-nested partial calls, etc.But effectively, before compiling
app/views/posts/index.htmlwe would transform it to this:So when we compile it, it would result in:
And thus eliminating the slow partial file lookup at runtime.
Option 2: Rewriting the
rendercallInstead of inlining the partial, we could rewrite the
rendercall to use the Action View-internal method directly. When Action View compiles the HTML+ERB files inapp/views/**it defines methods for each template file it compiles.So when we compile
app/views/posts/_post.html.erbit will expose a method like_app_views_posts__post_html_erb_[digest]_[number]. Knowing this fact at compile time, we could rewrite therenderpartial call inapp/views/posts/index.htmlto something like:and with that, we avoid the slow partial file lookup at runtime which should improve the performance when rendering this view at runtime.