Simple Lazy Loading jQuery Plugin and Defense of Turbolinks
#1 – Lightweight and common functions that were used site-wide were declared unobtrusively via event delegation on the document object.
#2 – Page/interface-specific initialization functions were bound to custom jQuery events.
1 2 3 4
s argument placeholder allows us to pass in the scope of the DOM we are only interested in initializing as a jQuery selector, i.e.
$(document).trigger("init:publisher","#content"). If no argument is supplied, the scope defaults to the entire page. This allows us to trigger these events more conservatively which is particularly useful for custom non-turbolinks ajax callbacks. If the parent element that needs initializing isn’t found within the scope, the function doesn’t waste any more time.
#3 – The
page:change event assumed the role of
1 2 3 4 5 6 7
Once scripts were massaged into place, the app was multitudes faster. Most page requests were completed under 300ms and the lack of a loading page flash gave the app a much more native-like experience. The dashboard, however, was still taking too long to load. The
dashboard#index controller action was heavy – it had to publisher with tabbed forms for different content types, a stream of recent activity had to be rendered, and a handful of sidebar widgets had to each run their specific database queries.
Since the various sidebar widget queries were the slowest chunk of
dashboard#index, as well as the least immediately relevant information on the page, they were the prime candidate to be lazily loaded. I extracted them to their own controller actions that render widget partials and created routes for each of them. Then I wrote this tiny jQuery function to load them after the new page was turbolinked in.
1 2 3 4 5 6 7 8
On the initial dashboard view, an
<div> empty with an attribute of
data-lazy-url=<%= specific_widget_url %> holds the place for the widget that is on the way. If you need to update the widget before the next
page:change, you can the add
data-lazy-url attribute to outermost element of the returned widget and call
$("[data-lazy-url]").lazy() whenever you need to. The result was a huge speed boost, cutting the page load time in half, and the widgets were usually in place before the user would even notice them not being there.