noelrappin / rails_javascript_documention_drafts

25 stars 4 forks source link

Turbolinks #11

Open domchristie opened 4 years ago

domchristie commented 4 years ago

I have been reviewing the most common issues with Turbolinks with the aim of providing some ideas as to what we might include in the Rails guides. Obviously Turbolinks is a separate project to Rails, so I'm still questioning what belongs where. However I thought it might serve as a starting point for some ideas.

Feedback on whether this fits in with the scope of this project is welcome, or if anyone has ideas for sections or topics, then let me know.

Integrating with third-party libraries

I like how Turbolinks makes you avoid crazy overblown JS libs because they likely break with it. (I mean that seriously). from @madrobby: https://twitter.com/thomasfuchs/status/895416259151515648

Many third-party libraries rely on DOMContentLoaded to initialise, and therefore won't re-initialise on subsequent Turbolinks page loads. Bootstrap's data-* API exemplifies this; developers will discover that their behaviours are added on the initial load and on refresh, but not thereafter. Rather than using the automatic data-* methods, it is preferable to manually control third-party libraries by calling their JavaScript functions directly if possible. (This a form of "conceptual expansion": developers can no longer just add data-* attributes and expect it to work; coming from this path, they'll have to have some concept of how Turbolinks works. I suppose this is one tradeoff for snappier page loads.)

Unfortunately some libraries (such as chat widgets) can only be integrated by adding a script tag to the <body>. This can cause errors when the widget's HTML is destroyed in a Turbolinks render, but the library's internal state is not. Currently there is no good solution to this, but perhaps there will be in the upcoming release.

On the plus-side, pulling in a load of jQuery plugins is not as prevalent as it used to be.

Running page-specific JavaScript

It's common to customise behaviour for a specific page by adding a <script> at the bottom of a page, then running code within a turbolinks:load listener. (This stems from the common practice of sprinkling $(document).ready(…) snippets in the <body>.) With Turbolinks, this can cause some issues. Firstly, it gives the impression that the code will run only on that page, but code in a turbolinks:load listener will run on every subsequent page load. What's more, if a user revisits that page, the listener will be attached again and again, resulting in confusing duplication. Secondly, turbolinks:load could be fired before the code has loaded, meaning it will never run. Often the solution is to run the code outside the turbolinks:load listener, but in general, inline scripts should be avoided.

There are often questions about organising code for running on a specific page. Stimulus encourages developers away from the "page-specific" mindset, and towards organising code in controllers that are automatically initialised whenever the related element is rendered; be that on a Turbolinks page load or via some other dynamic rendering. Developers may not be in a position to reorganise their JavaScript as Stimulus controllers, but perhaps it's worth steering them in that direction.

Understanding Caching & Previews

The Turbolinks caching mechanisms and previews are great, but if you're not aware of them as features, their behaviours might seem unexpected. Developers often ask why they briefly see the old page version, or why their plugin has reinitialised. Previews are mentioned in the Application Visits section of the Turbolinks readme, and there is a really great section on Understanding Caching but perhaps this could be promoted more as a feature and outlined in the Rails guides.

Forms

Turbolinks doesn't currently handle form submissions. turbolinks-rails does support redirects in collaboration with rails-ujs (typically after a successful form submission), but submitting and directly rendering a form response as HTML is not supported by Turbolinks itself. From what I gather, form submissions will be supported in the next version 🎉

noelrappin commented 4 years ago

I'm going to wait and see on this until the new Turbolinks comes out, which I think will change some of this, and some of this documentation my be produced separately.