J'essaie dans le <script>
de document.createElement
manuellement, puis d' appendChild
un audio
chaque fois qu'un eventListener
est appelé pour le remplacer. Tout fonctionne bien dans le navigateur , à part une erreur très rapide lors du chargement de la page, mais cela dure moins de 100 ms . Il y a également une erreur dans le terminal
ReferenceError: document is not defined at Object (webpack:///./src/components/Record/Component.svelte?:26:17)
Semble que ce qui précède est appelé lorsque le document n'est pas encore prêt, mais après c'est bien, comment le réparer? Ou quelle est la meilleure façon de détruire et de recréer des composants dans le monde Svelte (Sapper)?
3 Réponses :
document
n'est pas défini sur le serveur, vous devez donc vous en prémunir dans votre composant afin que ce morceau de code particulier ne soit exécuté que dans le navigateur.
Vous pouvez utiliser la fonction onMount
qui n'est exécutée dans le navigateur que lorsque le composant a été rendu.
<script> import { onMount } from 'svelte'; onMount(() => { document.createElement(...); // ... }); </script>
Il faut changer de mentalité pour se rappeler qu'au départ, tout est sur le serveur.
Sapper fonctionne bien avec la plupart des bibliothèques tierces que vous êtes susceptible de rencontrer. Cependant, parfois, une bibliothèque tierce est fournie d'une manière qui lui permet de fonctionner avec plusieurs chargeurs de modules différents. Parfois, ce code crée une dépendance sur window, comme le fait de vérifier l'existence de window.global.
Puisqu'il n'y a pas de fenêtre dans un environnement côté serveur comme celui de Sapper, le simple fait d'importer un tel module peut entraîner l'échec de l'importation et mettre fin au serveur du Sapeur avec une erreur telle que:
ReferenceError: la fenêtre n'est pas définie
Le moyen de contourner ce problème est d'utiliser une importation dynamique pour votre composant, à partir de la fonction onMount (qui n'est appelée que sur le client), afin que votre code d'importation ne soit jamais appelé sur le serveur.
<script> import { onMount } from 'svelte'; let MyComponent; onMount(async () => { const module = await import('my-non-ssr-component'); MyComponent = module.default; }); </script> <svelte:component this={MyComponent} foo="bar"/>
Merci à la réponse de Rutuja ici , j'ai également pu faire fonctionner mon application. Ajoutant à la réponse de Rutuja, si quelqu'un rencontre ce problème en utilisant Sapper + Svelte + un autre package (dans mon cas, theme.js
), vous devrez peut-être également importer plusieurs composants. Ceci est décrit dans la documentation de Mozilla ici pour l'importation .
Lors de l'importation d'une exportation par défaut avec des importations dynamiques, cela fonctionne un peu différemment. Vous devez déstructurer et renommer la clé "par défaut" de l'objet retourné.
const themeState = { active: undefined, selected: undefined, themes: [], } onMount(async () => { const { default: Themer, auto, system } = await import('themer.js') themeState = { active: undefined, selected: light, themes: [light, dark, auto, system], } const themer = new Themer({ debug: true, onUpdate: (theme) => (themeState.active = theme), themes: { light, dark, auto, system }, }) function noThemeSupport({ theme }) { return theme === 'system' && !themer.themeSupportCheck() } function setTheme(theme) { themeState.selected = theme themer.set(theme) } themer.set(themeState.selected) })
Pour mon propre projet (en utilisant theme.js
), j'ai dû utiliser la logique suivante (basée sur l'exemple svelte pour theme.js
situé ici ):
(async () => { if (somethingIsTrue) { const { default: myDefault, foo, bar } = await import('/modules/my-module.js'); } })();