jeffreyguenther / vue-turbolinks

A Vue mixin to fix Turbolinks caching
MIT License
287 stars 20 forks source link

Blinking #25

Closed feliperaul closed 6 years ago

feliperaul commented 6 years ago

When I'm on a page with a vue component mounted, and I click on a link to load a different page inside my app, I see the entire page (because my Vue app takes almost the entire viewport) blink, every single time.

Is this by design? Any way to avoid it ? It's very bad for UX the way it is.

Anyways, congrats for the nice gem!

excid3 commented 6 years ago

It's not intentional, of course, but there's not really any way around it. The HTML on the page must be updated by Turbolinks before Vue can render. That's always going to introduce some lag as things get mounted up.

You'll have to build a single page app if you want a better experience.

feliperaul commented 6 years ago

@excid3 Chris, but the blinking happens BEFORE navigating away to a page that DOES NOT have the Vue app.

I tried to make a gif to explain. Notice that the blinking happens on navigating AWAY from the the Vue app.

example

I don't bother at all to see a blank space when I'm navigating TO the Vue.app, it's normal and expected since the page is loading. But when I'm navigating AWAY from the Vue app it's weird, it seems the page RELOADED and then the next page (the one with the table, with no Vue app on it) appears.

feliperaul commented 6 years ago

Looking at dev tools, I found out that Turbolinks is first doing a GET using xhr (as expected), but then it triggers a regular page navigation to the destination:

image

image

image

feliperaul commented 6 years ago

I found out why: I was loading my pack tags like this:

<% content_for :js_in_head  do%>

  <%= javascript_pack_tag 'planilha', 'data-turbolinks-track': 'reload' %>
  <%= stylesheet_pack_tag 'planilha', 'data-turbolinks-track': 'reload' %>

<% end %>

And using <%= yield :js_in_head %> inside application.html.erb tag.

If I move the script directly in the template, then the blinking does not occur, and turbolinks does not invalidate that page as it was doing before.

The only issue is I don't want this pack loaded in my entire application, as it's only needed in a subset of pages. How one would accomplish that then?

excid3 commented 6 years ago

So the reason the library works like it does is because of the Turbolinks cache. When you visit a page, Vue mounts to an HTML tag and then replaces it. Navigating to another page, Turbolinks takes a snapshot of the page for the cache. If we did that when the Vue app is on the page, we end up with the Vue HTML cached which doesn't have the same element on the page you used to mount with. Then if you navigate back and Turbolinks renders the page from cache, your Vue app won't be loaded. That's why we have to teardown the Vue app before cache and you see some flickering. It's a bit unfortunate, but these weren't designed to work together.

feliperaul commented 6 years ago

@excid3 I'm closing this since I think this is a turbolinks issue rather then this lib's issue. After removing the content_for :head scripts and placing them directly in the layouts's header, turbolinks worked fine and there was no blinking anymore. But now I need to study how to load different packs in different parts of the application since if I do using content_for, turbolinks will not work properly and issue a regular HTTP request instead of a XHR (ajax) one.

connorshea commented 5 years ago

@feliperaul did you end up making any other progress on this? I'm having the same problem, but it's occurring despite the javascript_pack_tag being in the head of the page.

One solution was to remove the 'data-turbolinks-track': 'reload', but that causes other issues like rails-ujs has already been loaded! in the browser console :/

EDIT: #16 helps explain this a lot

roooodcastro commented 5 years ago

16 does explain a lot (along with #8), but @serradura offered (what it looks to be) a good solution on https://github.com/jeffreyguenther/vue-turbolinks/pull/8#issuecomment-316758827, and that was dismissed for being "too much".

Given that we know that this flickering is an issue, shouldn't his solution be implemented by default? I mean, as far as I understand, it solves the disabled cache issue that was solved by using turbolinks:visit, while also allowing the use of turbolinks:before-cache when the cache is enabled, which gets rid of the flickering from what I understand. Is there another hidden issue on using that approach that I can't see?

vortechron commented 4 years ago

this blink issue is the reason im not using turbolink in my vuejs app. going back to pace.js @@