DEV Community

Cover image for A few sneak peeks into technology (IV - Turbolinks frames continued)
Matouš Borák
Matouš Borák

Posted on • Updated on

A few sneak peeks into technology (IV - Turbolinks frames continued)

Update as of Dec 2020: now that the Hey support code has been extracted and officially released under the name Hotwire, we know that this article actually speaks about the Turbo Frames. Basecamp renamed and polished a few things but the principles stay the same as described here.

In the previous post, I looked into the new feature of Turbolinks - the Frames. We saw that they allow you to download any page area content automatically from the server with a separate async request upon main page load.

But that’s not all! Often it is convenient to load a page area from the server not right after the main content loads, but some time later, when the user requests it. It’s all the menus, submenus, popup windows, overlays, alerts and more we’re talking about here! There are usually many of them on a typical site with users to log in and get their job done… The distinct quality of these elements is that they are not needed often, that’s why they are hidden from the main content view in the first place! And Turbolinks frames allow the browser to be unaware of them until specifically requested by the user.

Again, this is usually a good thing as it can greatly lighten and speed up your pages. Why load all the stuff that you need just once a day? On the other hand, I think this approach makes your users more dependent on a stable network connection. I guess this might be a part of the problem with the Hey web that its offline experience is not particularly great (however, note that the mobile app works offline nicely, we’re talking about the web here). AFAIK, the Hey team is looking into this matter so we’ll see what they come with later on…

Loading page parts interactively uses this technique quite heavily, let’s take a look at the contact page, for example: the main menu, my profile menu, the action to edit the contact name as well as the settings buttons underneath, all these elements are (re-)loaded freshly from the server when I click on them:

Turbolinks frames on contacts page

In the Network developer tool it looks like this (note that the requests were not simultaneous but sequential, as I clicked on the elements, one after another):

Turbolinks frames on contacts page - Network

All responses to these requests are pure HTML and note that all of them are cached as I’ve already visited them a few minutes ago.

How does this work? In the previous post we learned that these updates are handled by the new Turbolinks custom element called turbolinks-frame. It watches its src attribute for changes and when such change occurs, it visits the src URL via AJAX and replaces its own content with the server response.

So, all we have to do, is alter the given element’s src attribute somehow to update the corresponding part of the web page. There are many ways to do it but all the usual ones are dependent on JS code (if you use Stimulus, you can e.g. find and update the element in a Stimulus controller).

Nice, but does the new Turbolinks provide a way to do the same without having to write any JavaScript at all? Well, of course it does! Let’s take a look at the main menu in Hey, for example.

When we reload the page to have it fresh and clean and use the Page inspector Element picker tool in Dev tools to show what’s inside the HEY logo, we’ll see something like this:

Main Hey menu in Dev tools

So, again, we have the turbolinks-frame custom element here but this time it’s not empty, it contains a link. And this link has a data-turbolinks-frame attribute with the value equal to the HTML id of the Turbolinks frame element. This must mean something!

If we search through the JS sources for "data-turbolinks-frame", we’ll find, among other results, the shouldInterceptNavigation in the FrameController class that supports the frame element. This method returns true if it finds a data-turbolinks-frame attribute in the link and tells Turbolinks whether it should leave the link up to normal Turbolinks processing (i.e. visit the URL) or intercept it and handle differently (i.e. trigger update of that page part).

If the frame element decides to intercept the click event, the code eventually gets to the linkClickIntercepted method, which just updates the src attribute of the frame element:

linkClickIntercepted method

As we’ve seen before, this change is noticed by the browser and leads to an AJAX call to the server followed by an update of the frame element’s content with the response.

Once the Hey main menu frame element is loaded, it is much more complex than before and it gets linked to a few Stimulus controllers that further define it’s behavior − open up the popup menu, activate live search, etc…

Main Hey menu

Summary and notes

I’m pretty sure that most of what we talked about here, is a too low-level stuff, that you won’t need to deal with at all once they release the new Turbolinks. The Basecamp / Hey team will definitely come with some nice helpers / DSL that will make this pattern a breeze.

Also, clicking links for sure is not the only way to trigger the updates. I’ve seen in the source code that Turbolinks supports also forms associated with frame elements, so a form submit can trigger a partial page update, again without needing custom JS. But of course, as we said, it can be easily triggered from JS code, too.

Overall, it seems to me that the Turbolinks frames feature is a successor of the Rails UJS library, that, among other things, allowed to issue an AJAX request triggered by an interactive event and process the result somehow, without needing much JS code.

However the new Turbolinks frames are both more radical (normally they expect only HTML on the wire) and more opinionated (they simply replace the frame element content with the response). This alone, I guess, will cover most of the partial page update use cases, while still not touching any custom JS code! And if you need something more complex, you can always “sprinkle” your HTML with Stimulus attributes and put that JS code into controllers.

Next, we’ll take a short peek into some new syntactic sugar in the Stimulus controllers, stay tuned!

Top comments (5)

pavelloz profile image
Paweł Kowalski

Are you sure its turbolinks feature though? I cant find one word about it in turbolinks repo, so i would say its just feature that works with turbolinks.

borama profile image
Matouš Borák

Not absolutely sure about anything here 😌... Still, it's quite usual for the Basecamp team to extract new features into Rails / Stimulus / Turbolinks and this time they promise big changes in Turbolinks.

mike1o1 profile image
Mike Wilson

I've seen them mention it will be in the next version of Turbolinks (Turbolinks 6).

pavelloz profile image
Paweł Kowalski

Cant wait for the release then :)

pcreux profile image
Philippe Creux

Thank you for sharing your findings. While looking around I noticed and googling for it lead me to your posts. Keep them coming!