-
-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JS file always runs after the turbo:load event, causing x-data to throw a ReferenceError on first navigation #31
Comments
Hi @timohermans Just to clarify, you have something like site.js import * as Turbo from "@hotwired/turbo"
import 'alpine-turbo-drive-adapter'
import 'alpinejs';
window.testComponent = function() {
return {foo: 'bar'}
} a.html <html>
<head>
<script src="site.js">
</head>
<body>
<div x-data x-text="'Alpine has loaded'"></a>
<a href="b.html">click me</a>
</body>
</a> b.html <html>
<head>
<script src="site.js">
</head>
<body>
<div x-data="testComponent()" x-text="foo"></a>
</body>
</a> Is that correct? |
Thanks for the quick reply! Not quite right. Let me see if I can edit your example: site.js import * as Turbo from "@hotwired/turbo"
import 'alpine-turbo-drive-adapter'
import 'alpinejs';
window.testComponentA = function() {
return {foo: 'bar'}
} a.html <html>
<head>
<script src="site.js"></script>
</head>
<body>
<nav>
<div x-data="testComponentA()" x-text="'Alpine has loaded'"></a>
</nav>
<a href="b.html">click me</a>
</body>
</html> custom.js window.testComponentB = function() {
return {foo: 'bar'}
} b.html <html>
<head>
<script src="site.js"></script>
<script src="custom.js"></script>
</head>
<body>
<nav>
<div x-data="testComponentA()" x-text="'Alpine has loaded'"></a>
</nav>
<div x-data="testComponentB()" x-text="foo"></div>
</body>
</html> |
@timohermans I think it's a bug, or at least an unexpected behavior, in turbo, unless I misunderstood their events. While I'm trying to understand it better, it would work if you use a single bundle with all your controllers in it. |
I think you are absolutely right. I still had the MPA mindset to separate all the JS per page. But with using turbo the border between MPA and SPA is fading and I guess it makes sense to put this all in one bundle, even though payload would become bigger and bigger per page load :(. so possible solutions are:
Agree
So then the question is: how can we tackle this issue 😊? |
I'm looking into it. I tried to delay the Alpine callback and I wrote a test to replicate the issue, it passes locally but it fails on github. I assume the turbo:load event fires independently from the page assets so there's no easy way to check when the new javascript has been downloaded, maybe I'll ask the turbo guys. I'll keep you posted. |
So, I ran more tests and it was actually the same with the old turbolinks. The main problem is that the turbo events (render, load, etc) fire when the new dom is ready but additional assets are loaded asynchronously and they can take an arbitrary time to load so, when turbo/turbolinks fire the load event, your custom.js may or may not be ready. I can delay the execution a bit but people with a slow connection would still experience the issue so I'd rather not add an incomplete fix. Unfortunately, the native readystate only works on a real page load and it cannot be used for those quick loadings so it seems it's impossible to know when your js libraries are ready. This becomes obvious with Alpine but you would have the same issue if you try to start a js datepicker on a secondary page if the script is loaded only on that page, for instance. Blocking the page until the js is ready, if it's ever possible, would defeat the purpose of Turbo where the website should act as an SPA so for now the easy way would be one of the two you mentioned. If you go for a single bundle the payload won't grow at each page load since it will only be loaded the first time (and possibly cached by the browser for future visits). Depending on your backend framework, it may be easy to include those scripts inline as well |
So when I'm trying to move from page A to page B with Turbo (7-beta4) drive, the alpine x-data function that is in a separate js file is always executed after the
initCallback
of this package, causing a ReferenceError. I'm not sure if it has anything with the following setup:Both page A and B have a
site.js
(it's in the layout file) script that contains the following:Page A has some alpine functionality in the navbar.
Page B has an additional scripts which loads only the x-data functions. Example:
I've tried several things that didn't work:
The only thing that works (aside from reloading the page) is when I put the page B functions in a script tag in the HTML itself.
Does it have something to do with the fact that the
site.js
script doesn't get reloaded when moving from page A to B?See gif below
The text was updated successfully, but these errors were encountered: