kit
kit copied to clipboard
beforeinstallprompt doesnt get fired in +layout.svelte
Discussed in https://github.com/sveltejs/kit/discussions/11550
Originally posted by rheanV January 9, 2024
I have an installable PWA (for sveltekit app). I want to add a custom button for installing the app. I placed my window.addEventListener('beforeinstallprompt', (event) => { event.preventDefault(); //logic }); in the onMount of the +layout.svelte file. I have all other configurations correct, meets all installation criteria, and can be installed via the browser download option in the URL bar. However, my "beforeinstallprompt" does not get fired in the +layout.svelte. If I place it in app.html then it is fired but not in +layout.svelte. How should I fix this? What am I missing in my sveltekit app setup?
Same issue here - no clue if the use of this event in app.html can be a workaround? Please help
EDIT: A good workaround is
<script nonce="%sveltekit.nonce%">
window.addEventListener('beforeinstallprompt', event => {
event.preventDefault()
window.deferredInstallPrompt = event
})
</script>
and then where it's needed:
const showInstallPrompt = async () => {
if (window.deferredInstallPrompt) {
await window.deferredInstallPrompt.prompt()
window.deferredInstallPrompt = null
canInstallApp = false
}
}
where canInstallApp is for displaying a button
Same issue here.
Not only is the window.addEventListener for beforeinstallprompt not working, but also the event in the svelte:window tag is not fired too.
It triggers very intermittently when adding the event listener to <svelte:window> so it's a timing issue. I wonder if we should try to somehow replay this event or wait for it to stablise across browsers. https://developer.mozilla.org/en-US/docs/Web/API/BeforeInstallPromptEvent
There's no guaranteed time this event is fired, but it usually happens on page load.
- https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeinstallprompt_event
<svelte:window
onbeforeinstallprompt={() => {
console.log("beforeinstallprompt");
}}
/>
EDIT: A good workaround is
<script nonce="%sveltekit.nonce%"> window.addEventListener('beforeinstallprompt', event => { event.preventDefault() window.deferredInstallPrompt = event }) </script>
This is great, and super helpful, however it does mean that pre-rendering is no longer an option (due to the included nonce)... but removing the nonce means that CSP wouldn't be able to be used in any secure fashion. 🙃
I can even put it into a component that gets loaded in the root +layout.svelte.
<script module lang="ts">
let installPrompt: Event;
</script>
<svelte:window
onbeforeinstallprompt={(e) => {
installPrompt = e;
}}
/>
It is worth mentioning that it only fires in production mode via https.