Tresjs / tres

Declarative ThreeJS using Vue Components
https://tresjs.org
MIT License
2.27k stars 107 forks source link

Document is not defined when using `useTexture` #444

Closed fsyntax closed 11 months ago

fsyntax commented 1 year ago

Describe the bug

Using the TresJS nuxt module on Nuxt 3.8.1. When trying to use useTexture directly in a script setup, I'm getting a "500 - document is not defined" error upon loading the page!

So this:

<script setup lang="ts">
import { extend } from '@tresjs/core';
import { OrbitControls } from '@tresjs/cientos';

extend({ OrbitControls });

const pbrTexture = await useTexture({
  map: 'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_Displacement.jpg',
  displacementMap:
    'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_Displacement.jpg',
  roughnessMap:
    'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_Roughness.jpg',
  normalMap:
    'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_NormalGL.jpg',
  ambientOcclusion:
    'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_AmbientOcclusion.jpg',
});
</script>

Is throwing the error when directly calling the correspondig route.

What is working is wrapping useTexture inside a onBeforeMount hook:

<script setup lang="ts">
import { extend } from '@tresjs/core';
import { OrbitControls } from '@tresjs/cientos';

extend({ OrbitControls });

const pbrTexture2 = ref();

onBeforeMount(async () => {
  pbrTexture2.value = await useTexture({
    map: 'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_Displacement.jpg',
    displacementMap:
      'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_Displacement.jpg',
    roughnessMap:
      'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_Roughness.jpg',
    normalMap:
      'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_NormalGL.jpg',
    ambientOcclusion:
      'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_AmbientOcclusion.jpg',
  });
});
</script>

I've provided a very basic reproduction below!

Reproduction

https://stackblitz.com/edit/nuxt-starter-fn4snl?file=app.vue

Steps to reproduce

Simply navigate to the reproduction link

System Info

From Stackblitz:  
System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.18.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.4.2 - /usr/local/bin/npm
    pnpm: 8.9.2 - /usr/local/bin/pnpm
  npmPackages:
    @tresjs/cientos: ^3.6.0 => 3.6.0 
    @tresjs/nuxt: ^1.2.2 => 1.2.2 
    @tresjs/post-processing: ^0.5.0 => 0.5.0 

From my Local environment:
  System:
    OS: Windows 11 10.0.22621
    CPU: (16) x64 13th Gen Intel(R) Core(TM) i7-1360P
    Memory: 10.65 GB / 31.64 GB
  Binaries:
    Node: 18.18.2 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - C:\Program Files\nodejs\yarn.CMD
    npm: 9.8.1 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.10.2 - ~\AppData\Local\pnpm\pnpm.EXE
  Browsers:
    Edge: Chromium (119.0.2151.58)
    Internet Explorer: 11.0.22621.1

Used Package Manager

pnpm

Code of Conduct

alvarosabu commented 11 months ago

Hi @fsyntax this is because you are doing SSR with Nuxt, so you need to wrap your components with

<ClientOnly />

I suggest you to use the official module that does this for you https://tresjs.org/guide/nuxt.html

fsyntax commented 11 months ago

Well as far as I can tell I did. Have you had a look at the reproduction?

WangShuan commented 11 months ago

@fsyntax Hi, I encountered the same problem, and after trying many times, I found that if I use the Suspense wrapper code directly in app.vue or /pages/xxx.vue, the error will occur! You need to encapsulate it into a component and use to wrap the component in the page to execute it correctly.