Tresjs / nuxt

TresJS integration for Nuxt.
https://tresjs.org/
MIT License
210 stars 6 forks source link

Unable to use `useNuxtApp()` since `@tresjs/core@3.1.0` #33

Closed kekkorider closed 1 year ago

kekkorider commented 1 year ago

Describe the bug

I tried upgrading the @tresjs/core package from 3.0.1 to 3.1.x and now every attempt to use the useNuxtApp() composable breaks the application.

Screenshot 2023-08-30 alle 00 45 56

Reproduction

https://stackblitz.com/github/kekkorider/nuxt-tres-starter/tree/tresjs-core-3-1?file=components%2FSampleBox.vue

Steps to reproduce

In /components/SampleBox.vue, comment out line 19, the one where useNuxtApp() is used. The error will be gone.

System Info

System:
    OS: macOS 13.4.1
    CPU: (8) arm64 Apple M1
    Memory: 280.75 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.16.0 - ~/.nvm/versions/node/v18.16.0/bin/node
    Yarn: 1.22.19 - ~/.yarn/bin/yarn
    npm: 9.5.1 - ~/.nvm/versions/node/v18.16.0/bin/npm
    pnpm: 8.7.0 - /opt/homebrew/bin/pnpm
  Browsers:
    Chrome: 116.0.5845.110
    Edge: 114.0.1823.55
    Safari: 16.5.1

Used Package Manager

pnpm

Code of Conduct

alvarosabu commented 1 year ago

Hey @kekkorider try the new release, I updated the core here https://github.com/Tresjs/nuxt/pull/35

kekkorider commented 1 year ago

@alvarosabu if you're talking about the 3.1.1 version, the error persists 🥲🔫

alvarosabu commented 1 year ago

I meant updating the version of the @trejs/nuxt .

kekkorider commented 1 year ago

Just updated @tresjs/nuxt to 1.1.5 and nothing changed unfortunately 😕

alvarosabu commented 1 year ago

Hey @danielroe I might need your support here. 😅 nuxtAppInstance = getCurrentInstance()?.appContext.app.$nuxt;

getCurrentInstance() returns null

To fix the devtools, we introduce these changes on @tresjs.core@3.1.0 https://github.com/Tresjs/tres/pull/375/files#diff-d554b20c605a72c68b2d429ff9915cca4afa8e118026f56ede93382d130382a7

This means we don't longer mount a second app with the Tres renderer, We actually managed to have a "reconciliation" layer inside TresCanvas. I think this is causing the' useNuxtApp' composable to break when used inside of the <TresCanvas /> context.

Any idea if we could potentially fix this?

Appreciate your time 🙏🏻

danielroe commented 1 year ago

If this is purely client-side, you can access the current Nuxt app instance with window.useNuxtApp (in the latest versions).

kekkorider commented 1 year ago

Just made a quick test 👇

  1. Keep const { $gsap } = useNuxtApp() commented out
  2. Instantiate a let gsap variable
  3. Set the value of the above gsap variable inside the onMounted() hook this way 👉 gsap = window.useNuxtApp().$gsap

This way, it works.


I also tested some other potential solutions, but none of these succeeded 👇

  1. Rename SampleBox.vue to SampleBox.client.vue
  2. Wrap <SampleBox /> with <ClientOnly /> in MyScene.client.vue
danielroe commented 1 year ago

I'm not entirely sure of the details - maybe a reproduction would help me.

Ideally users wouldn't need to update their code, and should be able to use useNuxtApp as is in their components.

Are all the Nuxt injections missing from the Tres canvas?

kekkorider commented 1 year ago

@danielroe thanks for the reply!

Have you checked the reproduction link? 👉 https://stackblitz.com/github/kekkorider/nuxt-tres-starter/tree/tresjs-core-3-1?file=components%2FSampleBox.vue

By default the application breaks, but if you follow my instructions you'll see that it works

  1. Keep const { $gsap } = useNuxtApp() commented out
  2. Instantiate a let gsap variable
  3. Set the value of the above gsap variable inside the onMounted() hook this way 👉 gsap = window.useNuxtApp().$gsap
kekkorider commented 1 year ago

Are all the Nuxt injections missing from the Tres canvas?

I tested a bunch of random composables provided by Nuxt, most of them don't work and trigger the same error.

  1. useRoute()
  2. useRouter()
  3. useSeoMeta()
  4. useFetch()
  5. useState()
danielroe commented 1 year ago

I think there will be a lot of situations where users expect to be able to access an injection provided by a module's plugin, for example. Might be worth considering how to proxy injections across? Depending on the lifecycle (is the tres app created subsequent to all nuxt plugins?) you might be able to pass the injections across.

alvarosabu commented 1 year ago

Yeah users should be able to acces those

In the TresCanvas we "mount" the renderer like this:

const mountCustomRenderer = (context: TresContext) => { 
   const InternalComponent = createInternalComponent(context) 
   render(h(InternalComponent), scene.value as unknown as TresObject) 
 }

Being render a method from the customRenderer.

@danielroe to inject them would be at this level or in the nuxt module itself?

JaimeTorrealba commented 1 year ago

I have the same error here, any fix?

alvarosabu commented 1 year ago

@danielroe been investigating a little bit and the problem is that when getCurrentInstance is used inside a Tres component (Inside the context of the custom renderer) app is null

Since all this composable on nuxt uses it, they get broken.

Screenshot 2023-09-10 at 18 49 25

Actually, @enpitsulin helped us out with the custom render, there would be any way to provide the custom renderer the app value of it's parent (the vue app)?

enpitsuLin commented 1 year ago

It seems that using the custom renderer will create appContext which doesn't contain context from the root Vue App(Like Nuxt provided), I think this is expected

use custom renderer will create separate contexts just like creating different App Instances, whether using the render function or createApp

we need to provide useful context alone as TresJs does

but it's unreasonable, I think proxy the root App's context to the context created by the custom renderer might be a solution, but don't know how to :)

alvarosabu commented 1 year ago

Hi @enpitsuLin thanks for your insights! I manually proxy the context of the vue wrapper app to the TresJS one, really manual, not sure if it's the best approach but, might fix the issue.

Do you mind to give it a look? Thanks for your support

kekkorider commented 1 year ago

Confirming that with the 1.1.6 version of @tresjs/nuxt the error is gone.