5
votes

ReferenceError: le document n'est pas défini dans Svelte 3

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)?


0 commentaires

3 Réponses :


14
votes

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>


1 commentaires

Il faut changer de mentalité pour se rappeler qu'au départ, tout est sur le serveur.



6
votes

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"/>


0 commentaires

1
votes

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');
  }
})();


0 commentaires