jeffreyguenther / vue-turbolinks

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

Errors when using vue-turbolinks with separate js files #30

Closed tleish closed 4 years ago

tleish commented 4 years ago

When using Rails View (RView) with separate javascript files, each loading Vue Components, this library throws errors and page renders odd as a result.

Reproduce

  1. Setup 2 Rails views (RviewA and RviewB), each with their own JS file and and vue components and turbolinks
  2. Using an href link, reference the other page.
  3. Click back and forth between pages.

Observed

DOMException: Failed to set the 'outerHTML' property on 'Element': This element has no parent node. ...

DOMException: Failed to set the 'outerHTML' property on 'Element': This element has no parent node. ...

Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option. (found in ) ...


- Refresh RviewB, view renders correctly.

Stack traces lead back to turbolinks and/or teardown code.

I uploaded a simple Rails app example of this here:
https://github.com/tleish/vuerails-test

Removing tubolinks and vue-turbolinks allows views with vue components to render as expected.

Bug or have I configured something incorrectly?
excid3 commented 4 years ago

Your example app here isn't really using vue-turbolinks at all, hence your problems.

You're using Turbolinks to load page-specific Javascript, so you would not want vue-turbolinks for those vue components in that situation.

If you want to use vue-turbolinks, you would write the code in one Javascript file that is loaded once and used across every Turbolinks page.

tleish commented 4 years ago

@excid3 - Thank you for your response. Are you saying vue-tubolinks is a good fit for an SPA, or a good fit for a multi-page app sharing the same javascript file?

excid3 commented 4 years ago

Nope. Unless you're considering Turbolinks an SPA.

If you want page-specific Javascript files, read up on how to do it with Turbolinks. You don't need this library for that.

Turbolinks is designed so you put all your Javascript and CSS into one file a piece and nothing has to reload on other page views. vue-turbolinks just makes it so your vue components are mounted anytime Turbolinks changes the page.

Your code isn't doing that. You're putting a script tag in the body, so Turbolinks will automatically evaluate that on each page. You don't need to hook into Turbolinks events to reload things if you're doing that.

Definitely give the Turbolinks documentation a read so you can understand the difference between script tags in the head vs in the body with Turbolinks.

tleish commented 4 years ago

@excid3 - I created the small app as an example of how you might break up a large site into smaller subsections of javascript. In other words, instead of one large javascript for 50 pages you might break it up into 3. I thought I understood turbolinks before, but after your comment and digging deeper into the documentation I understand it better.

FYI, I learned the heart of the issue has to do with turbolinks and rendering the javascript the the head vs the body. Rendering the javascript to the head solves the odd behavior issues I experienced.

<!-- views/layout/application.html.erb -->
<head>
   ...
  <%= stylesheet_pack_tag 'common', 'data-turbolinks-track': 'reload'  %>
  <%= javascript_pack_tag 'common', 'data-turbolinks-track': 'reload' %>
  <%= yield :head %>
</head>
<!-- views/articles/index.html.erb -->
<% content_for :head do %>
  <%= javascript_pack_tag 'articles', 'data-turbolinks-track': 'reload' %>
<% end %>

I would not have found the solution without your responses. Thank you.

excid3 commented 4 years ago

Awesome @tleish! Glad I could help! 🤘