I am creating a card template that runs a single-page application, more precisely a Svelte app. The HTML of the front template roughly looks like this:
<div id="app"></div>
<script>let side = 'question'</script>
<script type="module" crossorigin src="/_addons/705507113/assets/index-BZJA7hBY.js"></script>
The back template looks the same, only that the variable side is set to “answer”.
When the app is first displayed, everything is fine. But on all subsequent occasions, the app is not rendered. When I add a cache-busting query parameter to the script URL, things work again, but - of course - just once:
I am pretty sure that I can remedy this by dynamically inserting the script tag with a timestamp as a script parameter. But that seems to be a little bit awkward because it will reload and parse the exact same JavaScript code every time the app is displayed.
That works, because I see the value of side inside the console, whenever the view changes.
The “problem” is the attribute type="module" of the script tag. The JavaScript file (the Svelte app) ends with this piece of code:
console.log('creating app');
new App({
target: document.getElementById("app")
});
console.log('creating app done');
The console.log statements are from me and they are executed only once. In study mode that is, when the question is displayed. When I click “view answer” and for subsequent cards, they are not executed.
The solution would therefore be to omit the type="module" but that leads to tons of errors like const xy already defined. These errors would most probably go away if I changed the target from ES6 to ES3 so that no const is used. But I think that I will rather go with dynamically inserting the script with a timestamp URL parameter and force a re-load of the JavaScript.
The takeaway from my point of view is: Anki does not do a full page reload like a browser does, when the view changes. Scripts loaded statically with type="module" are executed only once. I have to verify that but I’m pretty sure that this is the case.
Yes, that is correct. A simple solution would be to put the bulk of the code in a module, and do the actual initialisation/creation of the app in an inline script tag.
Sure, but this is a Svelte app and Svelte, resp. vite-plugin-svelte does not seem to support that flexibility.
Any chance to get this somewhat surprising behaviour documented? I think it would be very helpful to have a description of the context in which JavaScript code inside card templates gets executed, and how that context differs from a “normal” browser context. For example, if you want to use const variable declarations in inline script tags or scripts not included with type="module", you have to scope them, for example with IIFEs.