Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReferenceError: document is not defined in Svelte 3

Tags:

svelte

I'm trying in the <script> to manually document.createElement and then to appendChild an audio every time an eventListener is called to replace it. Everything works fine in the browser, apart a really quick error when the page loads but this lasts less then 100ms. There is an error in the Terminal as well

ReferenceError: document is not defined
    at Object (webpack:///./src/components/Record/Component.svelte?:26:17)

Seems that the above is called when document is not ready yet but afterwards it is fine, how to fix it? Or what is the preferred way to destroy and recreate components in Svelte world (Sapper)?

like image 517
Mac_W Avatar asked May 17 '19 06:05

Mac_W


People also ask

How do I fix ReferenceError document is not defined?

To solve the"ReferenceError: document is not defined" error, make sure to only use the document global variable on the browser. The variable relates to the Document Object Model, which represents a web page that is loaded in the browser and can't be used on the server side (e.g. in Node. js).

Is not defined $( document?

Basically $ is an alias of jQuery() so when you try to call/access it before declaring the function, it will endup throwing this $ is not defined error . This usually indicates that jQuery is not loaded and JavaScript does not recognize the $. Even with $(document).

Why does it say document is not defined JavaScript?

The most common reason for this error is because you're using Node. That is to say, you are trying to access the document object on the server, but the server does not have access to the document object because it lives on the browser.

Is not defined reference error?

The ReferenceError: event is not defined usually occurs while using an event handler if the event parameter is either not declared or declared incorrectly. For example, if on an onclick event, the handler does not declare the event parameter, this error is thrown.

How to solve the 'ReferenceError document is not defined' error?

To solve the"ReferenceError: document is not defined" error, make sure to only use the document global variable on the browser. The variable relates to the Document Object Model, which represents a web page that is loaded in the browser and can't be used on the server side (e.g. in Node.js).

What does it mean when a document is not defined?

It is the most common error when running an HTML file in the browser. There are specific reasons for the “ReferenceError: document is not defined” error, such as: Misspelled the global variables; global variables should be in lower cases.

Why can't I reference a document in Node JS?

Node is a server-side runtime so if you're on Node, you cannot reference the document object, which is an in-memory representation of the Document Object Model. That also includes when you're doing server-side rendered applications, which can sometimes have universal code that can run on both the server and the browser.


3 Answers

document is not defined on the server, so you need to guard against that in your component so that particular piece of code is only run in the browser.

You can use the onMount function which is only run in the browser when the component has been rendered.

<script>
  import { onMount } from 'svelte';

  onMount(() => {
    document.createElement(...);

    // ...
  });
</script>
like image 146
Tholle Avatar answered Oct 12 '22 11:10

Tholle


Sapper works well with most third-party libraries you are likely to come across. However, sometimes, a third-party library comes bundled in a way which allows it to work with multiple different module loaders. Sometimes, this code creates a dependency on window, such as checking for the existence of window.global might do.

Since there is no window in a server-side environment like Sapper's, the action of simply importing such a module can cause the import to fail, and terminate the Sapper's server with an error such as:

ReferenceError: window is not defined

The way to get around this is to use a dynamic import for your component, from within the onMount function (which is only called on the client), so that your import code is never called on the server.

<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"/>
like image 20
Rutuja Avatar answered Oct 12 '22 13:10

Rutuja


Thank you to Rutuja's answer here, I was also able to get my application working. Adding to Rutuja's answer, if anyone runs into this issue while using Sapper + Svelte + another package (in my case theme.js), you may also need to import multiple components. This is described in Mozilla's documentation here for import.

When importing a default export with dynamic imports, it works a bit differently. You need to destructure and rename the "default" key from the returned object.

(async () => {
  if (somethingIsTrue) {
    const { default: myDefault, foo, bar } = await import('/modules/my-module.js');
  }
})();

For my own project (using theme.js), I had to use the following logic (based on the svelte example for theme.js located here):

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)
})
like image 1
ctwheels Avatar answered Oct 12 '22 13:10

ctwheels