ReferenceError: document is not defined in Svelte 3
ReferenceError: document is not defined in Svelte 3
我正在尝试在 <script>
中手动 document.createElement
然后 appendChild
一个 audio
每次调用 eventListener
来替换它. 在浏览器中一切正常,除了页面加载时非常快的错误,但持续时间不到 100 毫秒。终端也有错误
ReferenceError: document is not defined
at Object (webpack:///./src/components/Record/Component.svelte?:26:17)
上面好像是在文档还没有准备好的时候调用的,后来就好了,怎么解决?或者在 Svelte 世界 (Sapper) 中销毁和重新创建组件的首选方法是什么?
document
未在服务器上定义,因此您需要在组件中防止这种情况,以便特定的代码片段在浏览器中仅 运行。
您可以使用 onMount
函数,该函数仅在组件已呈现后在浏览器中 运行。
<script>
import { onMount } from 'svelte';
onMount(() => {
document.createElement(...);
// ...
});
</script>
Sapper 适用于大多数您可能遇到的 third-party 库。然而,有时,third-party 库以允许它与多个不同模块加载器一起工作的方式捆绑在一起。有时,此代码会创建对 window 的依赖性,例如检查 window.global 是否存在。
由于在像 Sapper 的 server-side 环境中没有 window,简单地导入这样一个模块的操作可能会导致导入失败,并终止 Sapper 的服务器并出现错误,例如:
ReferenceError: window 未定义
解决此问题的方法是从 onMount 函数(仅在客户端调用)中为您的组件使用动态导入,这样就永远不会在服务器上调用您的导入代码。
<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"/>
感谢, 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');
}
})();
对于我自己的项目(使用 theme.js
),我必须使用以下逻辑(基于位于 here 的 theme.js
的 svelte 示例):
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)
})
我正在尝试在 <script>
中手动 document.createElement
然后 appendChild
一个 audio
每次调用 eventListener
来替换它. 在浏览器中一切正常,除了页面加载时非常快的错误,但持续时间不到 100 毫秒。终端也有错误
ReferenceError: document is not defined
at Object (webpack:///./src/components/Record/Component.svelte?:26:17)
上面好像是在文档还没有准备好的时候调用的,后来就好了,怎么解决?或者在 Svelte 世界 (Sapper) 中销毁和重新创建组件的首选方法是什么?
document
未在服务器上定义,因此您需要在组件中防止这种情况,以便特定的代码片段在浏览器中仅 运行。
您可以使用 onMount
函数,该函数仅在组件已呈现后在浏览器中 运行。
<script>
import { onMount } from 'svelte';
onMount(() => {
document.createElement(...);
// ...
});
</script>
Sapper 适用于大多数您可能遇到的 third-party 库。然而,有时,third-party 库以允许它与多个不同模块加载器一起工作的方式捆绑在一起。有时,此代码会创建对 window 的依赖性,例如检查 window.global 是否存在。
由于在像 Sapper 的 server-side 环境中没有 window,简单地导入这样一个模块的操作可能会导致导入失败,并终止 Sapper 的服务器并出现错误,例如:
ReferenceError: window 未定义
解决此问题的方法是从 onMount 函数(仅在客户端调用)中为您的组件使用动态导入,这样就永远不会在服务器上调用您的导入代码。
<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"/>
感谢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'); } })();
对于我自己的项目(使用 theme.js
),我必须使用以下逻辑(基于位于 here 的 theme.js
的 svelte 示例):
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)
})