histoire-dev / histoire

⚡ Fast and beautiful interactive component playgrounds, powered by Vite
https://histoire.dev
MIT License
3.11k stars 181 forks source link

histoire-plugin-nuxt: provide from plugin not working with useNuxtApp in component #666

Open CIB opened 6 months ago

CIB commented 6 months ago

Describe the bug

When using provide from a nuxt plugin, and inserting the provided value into a component using useNuxtApp, the provided value will not be available, and an error will be thrown.

Reproduction

Stackblitz: https://stackblitz.com/edit/nuxt-starter-7avtmp?file=components%2Ftest.vue

In plugins/example.ts:

  return {
    provide: {
      example: { foo: 'bar' },
    },
  };

In components/test.vue

const nuxtApp = useNuxtApp();
const foo = nuxtApp.$example.foo;

Then try to start histoire dev with a story that includes <Test />, and an error will be thrown that nuxtApp.$example is undefined.

System Info

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: 10.2.3 - /usr/local/bin/npm
    pnpm: 8.14.0 - /usr/local/bin/pnpm
  npmPackages:
    @histoire/plugin-nuxt: ^0.17.8 => 0.17.8 
    @histoire/plugin-vue: ^0.17.8 => 0.17.8 
    histoire: ^0.17.8 => 0.17.8

Used Package Manager

npm

Validations

stackblitz[bot] commented 6 months ago

Fix this issue in StackBlitz Codeflow Start a new pull request in StackBlitz Codeflow.

dreitzner commented 6 months ago

Same issue when using nuxtApp.provide('helpers', helpers); (which I guess has the same logic under the hood.

positiveprogrammer commented 6 months ago

This is because Histoire/plugin-next stub out useNuxtApp?

0x100101 commented 1 month ago

This is because Histoire/plugin-next stub out useNuxtApp?

That's the problem.

The stub could replicate a simple provide by doing something like this:

const nuxtApp = {
    runWithContext: async fn => await fn(),
    provide(key, value) {
        const propertyName = '$' + key;
        nuxtApp[propertyName] = value;
    }
}

export const useNuxtApp = () => nuxtApp

However, this doesn't completely solve the issue, because I'm seeing that plugins don't get access to the stubbed nuxtApp. So anything they provide still won't be available to components in histoire.

export default defineNuxtPlugin(async (nuxtApp) => {
  // nuxtApp here is not the stubbed one
})
export default defineNuxtPlugin(() => {
  return {
    // This is not going to interact with the stubbed nuxtApp
    provide: {
      img: useImage(),
    },
  }
})

I don't fully understand the context around why the decision was made to stub nuxtApp.

If I disable it (by removing the imports:sources hook) here: https://github.com/histoire-dev/histoire/blob/main/packages/histoire-plugin-nuxt/src/index.ts#L147, histoire is able render all of my components as expected without any noticeable issue.

@Akryum, @danielroe, or others. Some additional high-level info may help someone address the issue.

Related: https://github.com/histoire-dev/histoire/pull/710