render_async
Speed up rendering Rails pages with this gem.
render_async
renders partials to your views asynchronously. This is done
through adding Javascript code that does AJAX request to your controller which
then renders your partial into a Rails view.
Workflow:
- user visits a Rails page
- AJAX request on the controller action
- controller renders a partial
- partials renders in the place where you put
render_async
helper
Javascript is injected into <%= content_for :render_async %>
so you choose
where to put it.
Installation
Add this line to your application's Gemfile:
gem 'render_async'
And then execute:
$ bundle install
Usage
-
Include
render_async
view helper somewhere in your views:# app/views/comments/show.html.erb <%= render_async comment_stats_path %>
-
Then create a route that will
config/routes.rb
# config/routes.rb get :comment_stats, :controller => :comments
-
Fill in the logic in your controller
# app/controllers/comments_controller.rb def comment_stats @stats = Comment.get_stats render :partial => "comment_stats" end
-
Create a partial that will render
# app/views/comments/_comment_stats.html.erb <div class="col-md-6"> <%= @stats %> </div>
-
Add
content_for
in your base view file# application.html.erb <%= content_for :render_async %>
Advanced usage
Passing in HTML options
render_async
takes two arguments, path
and html_options
.
path
is the AJAX-capable controller action you're looking to call viaGET
. e.g.comments_stats_path
,posts_path
, etc.html_options
is an optional hash that gets passed to a railsjavascript_tag
, to drop html tags into thescript
element.
Example of utilizing html_options
with a nonce
:
<%= render_async users_path, nonce: 'lWaaV6eYicpt+oyOfcShYINsz0b70iR+Q1mohZqNaag=' %>
Rendered code in the view:
<div id="render_async_18b8a6cd161499117471">
</div>
<script nonce="lWaaV6eYicpt+oyOfcShYINsz0b70iR+Q1mohZqNaag=">
//<![CDATA[
...
//]]>
</script>
Passing in a placeholder
render_async
can be called with a block that will act as a placeholder before
your AJAX call finishes.
Example of passing in a block:
<%= render_async users_path do %>
<h1>Users are loading...</h1>
<% end %>
Rendered code in the view:
<div id="render_async_14d7ac165d1505993721">
<h1>Users are loading...</h1>
</div>
<script>
//<![CDATA[
...
//]]>
</script>
After AJAX is finished, placeholder will be replaced with the request's response.
Passing in an event name
render_async
can receive :event_name
option which will emit Javascript
event after it's done with fetching and rendering request content to HTML.
This can be useful to have if you want to add some Javascript functionality
after your partial is loaded through render_async
.
Example of passing it to render_async
:
<%= render_async users_path, :event_name => "users-loaded" %>
Rendered code in view:
<div id="render_async_04229e7abe1507987376">
</div>
<script>
//<![CDATA[
...
document.dispatchEvent(new Event("users-loaded"));
...
//]]>
</script>
Then, in your JS, you could do something like this:
document.addEventListener("users-loaded", function() {
console.log("Users have loaded!");
});
Caching
render_async
can utilize view fragment caching to avoid extra AJAX calls.
In your views:
# app/views/comments/show.html.erb
# note 'render_async_cache' instead of standard 'render_async'
<%= render_async_cache comment_stats_path %>
# app/views/comments/_comment_stats.html.erb
<% cache render_async_cache_key(request.path), :skip_digest => true do %>
<div class="col-md-6">
<%= @stats %>
</div>
<% end %>
- The first time the page renders, it will make the AJAX call.
- Any other times (until the cache expires), it will render from cache instantly, without making the AJAX call.
- You can expire cache simply by passing
:expires_in
in your view where you cache the partial
Using with Turbolinks
On Turbolinks applications, you may experience caching issues when navigating
away from, and then back to, a page with a render_async
call on it. This will
likely show up as an empty div.
To resolve, tell turbolinks to reload your render_async
call as follows:
<%= render_async events_path, 'data-turbolinks-track': 'reload' %>
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run
rake spec
to run the tests. You can also run bin/console
for an interactive
prompt that will allow you to experiment.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/renderedtext/render_async.
License
The gem is available as open source under the terms of the MIT License.
Contributors
Thanks goes to these wonderful people (emoji key):
Nikola Đuza 💬 🐛 💻 📖 💡 👀 |
Colin 💻 📖 |
Kasper Grubbe 💻 |
Sai Ram Kunala 📖 |
Josh Arnold 💻 📖 |
Elad Shahar 💻 |
Sasha 💻 📖 |
---|
This project follows the all-contributors specification. Contributions of any kind welcome!