storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.59k stars 9.31k forks source link

[Bug]: Nuxt 3 version 3.1.2: nuxt instance unavailable - useNuxtApp().$app.filters #21196

Open Ibochkarev opened 1 year ago

Ibochkarev commented 1 year ago

Describe the bug

When using use methods from useNuxtApp().$app.filters storybook and vitest gives errors when using

To Reproduce

When using use methods from useNuxtApp().$app.filters storybook and vitest gives errors when using

a-avatar.stories.js

import AAvatar from './a-avatar.vue'

export default {
  title: 'Атомы/a-avatar',
  component: AAvatar,
  parameters: {
    docs: {
      description: {
        component:
          // eslint-disable-next-line max-len
          'Компонент вывода аватара — это настраиваемый компонент, который обычно используется для отображения профиля пользователя в виде изображения, значка или короткого текста',
      },
    },
  },
  argTypes: {
    type: {
      description: 'Тип аватара',
      options: ['film', 'user'],
      control: {
        type: 'radio',
      },
    },
    withInitials: {
      description: 'Включение отображения инициалов',
      table: {
        defaultValue: {
          summary: true,
        },
      },
      control: {
        type: 'boolean',
      },
    },
    name: {
      description: 'Имя',
      control: {
        type: 'text',
      },
    },
    surname: {
      description: 'Фамилия',
      control: {
        type: 'text',
      },
    },
    photoSrc: {
      description: 'Путь до изображения',
      control: {
        type: 'text',
      },
    },
    profession: {
      description: 'Профессия',
      control: {
        type: 'text',
      },
    },
    counter: {
      description: 'Счетчик',
      table: {
        defaultValue: {
          summary: 0,
        },
      },
      control: {
        type: 'number',
      },
    },
  },
}

const Template = (args) => ({
  components: { AAvatar },
  setup() {
    return { args }
  },
  template: '<AAvatar v-bind="args" />',
})

export const Film = Template.bind({})
Film.args = {
  type: 'film',
  name: 'Иван',
  surname: 'Иванов',
  profession: 'тестеровщик',
}

export const FilmWithPhoto = Template.bind({})

a-avatar.vue

<template>
  <div class="a-avatar__wrapper">
    <div v-if="counter && !filmAvatar" class="a-avatar__counter">
      {{ counterText }}
    </div>
    <div
      class="a-avatar"
      :class="[avatarTypeClass, photoSrc && 'a-avatar--photo']"
      :style="{ backgroundImage: photoSrc ? `url('${photoSrc}')` : 'none' }"
    >
      <span v-if="!photoSrc && withInitials" class="a-avatar__initials">
        {{ initials }}
      </span>
      <i v-else-if="avatarWithIcon" class="a-icons icon-user a-avatar__icon" />
    </div>
    <div v-if="filmAvatar" class="a-avatar__info">
      <h6 class="a-avatar__info-name font-body">
        <span>{{ name }}</span>
        <span>{{ surname }}</span>
      </h6>
      <h6 class="a-avatar__info-profession font-body">
        {{ profession.toLowerCase() }}
      </h6>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { useNuxtApp } from 'nuxt/app'
import { computed } from 'vue'

const props = defineProps({
  /**
   * Тип аватара: film или user.
   */
  type: {
    type: String,
    default() {
      return avatarVariants.types[0]
    },
    validator(value: string) {
      return useNuxtApp().$app.filters.validatePropStringByArray(value, avatarVariants.types)
    },
  },
  /**
   * Включение отображения инициалов
   */
  withInitials: {
    type: Boolean,
    default: true,
  },
  /**
   * Имя
   */
  name: {
    type: String,
    default: '',
  },
  /**
   * Фамилия
   */
  surname: {
    type: String,
    default: '',
  },
  /**
   * Путь до изображения
   */
  photoSrc: {
    type: [String, Boolean],
    default: false,
  },
  /**
   * Профессия
   */
  profession: {
    type: String,
    default: '',
  },
  /**
   * Счетчик
   */
  counter: {
    type: Number,
    default: 0,
  },
})

const avatarTypeClass = computed(() => {
  return useNuxtApp().$app.filters.setAtomClassByProp(props.type, avatarVariants.types, 'a-avatar')
})

const filmAvatar = computed(() => {
  return props.type === 'film'
})

const avatarWithIcon = computed(() => {
  return props.type === 'user' && !props.photoSrc
})

const counterText = computed(() => {
  return props.counter > 99 ? '+' : props.counter
})

const initials = computed(() => {
  return `${props.name[0]?.toUpperCase()}${props.surname[0]?.toUpperCase()}`
})
</script>

<script lang="ts">
const avatarVariants = {
  types: ['film', 'user'],
}
</script>

<style lang="scss" src="./a-avatar.scss" />

System

Environment Info:

  System:
    OS: macOS 13.1
    CPU: (10) arm64 Apple M1 Pro
  Binaries:
    Node: 16.17.0 - ~/.nvm/versions/node/v16.17.0/bin/node
    Yarn: 3.2.4 - ~/node_modules/.bin/yarn
    npm: 8.15.0 - ~/.nvm/versions/node/v16.17.0/bin/npm
  Browsers:
    Chrome: 110.0.5481.100
    Firefox: 107.0
    Safari: 16.2
  npmPackages:
    @storybook/addon-a11y: ^6.5.16 => 6.5.16 
    @storybook/addon-essentials: ^6.5.16 => 6.5.16 
    @storybook/builder-vite: ^0.3.0 => 0.3.0 
    @storybook/vue3: ^6.5.16 => 6.5.16

Additional context

nuxt instance unavailable

Error: nuxt instance unavailable
    at useNuxtApp (http://localhost:6006/node_modules/.vite-storybook/deps/nuxt_app.js?v=9a516d33:424:13)
    at validator (http://localhost:6006/components/_ui/atoms/a-avatar/a-avatar.vue?t=1674476744983:16:16)
    at validateProp (http://localhost:6006/node_modules/.vite-storybook/deps/chunk-HK4EIWFA.js?v=9a516d33:4842:21)
    at validateProps (http://localhost:6006/node_modules/.vite-storybook/deps/chunk-HK4EIWFA.js?v=9a516d33:4816:5)
    at initProps (http://localhost:6006/node_modules/.vite-storybook/deps/chunk-HK4EIWFA.js?v=9a516d33:4567:5)
    at setupComponent (http://localhost:6006/node_modules/.vite-storybook/deps/chunk-HK4EIWFA.js?v=9a516d33:7114:3)
    at mountComponent (http://localhost:6006/node_modules/.vite-storybook/deps/chunk-HK4EIWFA.js?v=9a516d33:5901:7)
    at processComponent (http://localhost:6006/node_modules/.vite-storybook/deps/chunk-HK4EIWFA.js?v=9a516d33:5879:9)
    at patch (http://localhost:6006/node_modules/.vite-storybook/deps/chunk-HK4EIWFA.js?v=9a516d33:5597:11)
    at ReactiveEffect.componentUpdateFn [as fn] (http://localhost:6006/node_modules/.vite-storybook/deps/chunk-HK4EIWFA.js?v=9a516d33:5992:11)
shilman commented 1 year ago

Any help here @storybookjs/vue ?

chakAs3 commented 1 year ago

Any help here @storybookjs/vue ?

I will be working on it... but this may be a vite issue, I'm not sure but I will reproduce it and see!

Ibochkarev commented 1 year ago

@chakAs3 we are talking about importing composable useNuxtApp

chakAs3 commented 1 year ago

@chakAs3 we are talking about importing composable useNuxtApp

Hi @Ibochkarev it won't work like this there is some workaround to do in vite config, but it is not the proper way it is just mocking. nuxt implementation still not yet done.

cwe-spb commented 1 year ago

@chakAs3 And when will we be able to come up with an alternative? We have a DI container in useNuxtApp, in which the entire core architecture of the project is located. And it is impossible to emulate it in every story

chakAs3 commented 1 year ago

yes @cwe-spb it is in our plan to do that properly, so I would like you to share your architecture with us earlier so we can have it in mind. if you can take some time to create a reproduction git repo with the typical project that you would like to have and share it with me, that would be great!

FieldMarshallVague commented 1 year ago

I have the same issue, I have some components working with my nuxt project, but now I am adding one with 'useNuxtApp' in it (pulling in a plugin) and it fails.

My component has this:

const { $debounce } = useNuxtApp()

And my preview.ts is like this:

import { setup } from '@storybook/vue3'
import { createPinia } from 'pinia'
// import { useNuxtApp } from '#app'
// import { useNuxtApp } from 'nuxt/dist/app'

/**
 * This is used by the preview panel in the storybook UI.
 * Setup global deps for previewing components here, to avoid duplication.
 */

/** @type { import('@storybook/vue3').Preview } */
const preview: import('@storybook/vue3').Preview = {
  parameters: {
    backgrounds: {
      default: 'light',
    },
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  },
}

export default preview

const pinia = createPinia()

// const { $debounce } = useNuxtApp()

setup((app) => {
  app.use(pinia)
  // app.use($debounce)
})

// NOTE: I have commented out my attempt to import useNuxtApp function

And I get 'useNuxtApp is undefined.'

As you can see, I've tried providing it to the preview setup. If I uncomment the lines above that import the useNuxtApp function into preview.ts then I get this error:

12:02:40 [vite] Internal server error: Missing "./dist/app" specifier in "nuxt" package
  Plugin: vite:import-analysis
  File: C:/sb-test/.storybook/preview.ts
      at e (file:///C:/sb-test/node_modules/vite/dist/node/chunks/dep-ca21228b.js:14845:25)
      at n (file:///C:/sb-test/node_modules/vite/dist/node/chunks/dep-ca21228b.js:14845:627)
      at o (file:///C:/sb-test/node_modules/vite/dist/node/chunks/dep-ca21228b.js:14845:1276)
      at resolveExports (file:///C:/sb-test/node_modules/vite/dist/node/chunks/dep-ca21228b.js:22033:20)
      at resolveDeepImport (file:///C:/sb-test/node_modules/vite/dist/node/chunks/dep-ca21228b.js:22052:31)
      at tryNodeResolve (file:///C:/sb-test/node_modules/vite/dist/node/chunks/dep-ca21228b.js:21737:20)
      at Context.resolveId (file:///C:/sb-test/node_modules/vite/dist/node/chunks/dep-ca21228b.js:21488:28)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at async Object.resolveId (file:///C:/sb-test/node_modules/vite/dist/node/chunks/dep-ca21228b.js:41612:32)
      at async TransformContext.resolve (file:///C:/sb-test/node_modules/vite/dist/node/chunks/dep-ca21228b.js:41363:23)
FieldMarshallVague commented 1 year ago

@chakAs3 I've been trying to create a repro for you, let me know if you need something more, or were looking for something else.

https://github.com/FieldMarshallVague/sb-nuxtapp-repro

PLEASE NOTE: yarn build will break if the '#build' line in vite.config.ts is left. Comment it out for build, but leave it in for running story to see error below.

I got nuxt working to a point with auto-imports based on advice from here

But while simple components work fine, stories with more complex ones that include nuxt plugins (from the plugins folder, i.e. functions you want to be globally available) need the nuxtapp instance.

NOTE: I could in this example use a composable instead, but this is just an example of requiring nuxtapp.

The beta has changed since I created my project, but I've applied some config to it to recreate the fundamental issue of NuxtApp not being provided correctly (or so it seems).

Storybook runs fine, but the preview panel shows an error:

ReferenceError: process is not defined
    at http://localhost:6006/node_modules/nuxt/dist/app/compat/idle-callback.mjs?v=bd12faad:1:36

I hope this helps :)

chakAs3 commented 1 year ago

Hi @FieldMarshallVague i really appreciate your work, it definetly helps, i will get sometime this week to work on it. i know the nuxtapp issue i have already some ideas to make it work properly. i let you know if i need your help on something . Thanks again

Ibochkarev commented 1 year ago

@chakAs3 Good afternoon

Is there any news on correcting the errors set forth in this issue

chakAs3 commented 1 year ago

@chakAs3 Good afternoon

Is there any news on correcting the errors set forth in this issue

Hello @Ibochkarev it is in my plans, waiting some PR to get merge first which required in order to have this implementation, i will keep posted once there is a PR addressing this in next few days

Ibochkarev commented 1 year ago

@chakAs3 Good afternoon

Is there any news on correcting the errors set forth in this issue

cwe-spb commented 1 year ago

@chakAs3 Hey! This problem is still relevant. We can't use composable useNuxtApp() in storybook stories. This severely limits the ability to use storybook with Nuxt 3. Are there any options to make it work?

chakAs3 commented 1 year ago

Hi @cwe-spb it is not an issue of composable, but nuxt configuration that may have some conflicts with storybook, when it comes to composables you can check this repo https://github.com/chakAs3/vue3-sb-composable

VegasChickiChicki commented 1 year ago

@chakAs3 Hi! Many of my components use useNuxtApp composable, in particular I decided to use the Veux repository and made it a global plugin. I use it like this: const { $store } = useNuxtApp(). Right now, useNuxtApp always returns - {}. Are there plans to fix this behavior? This is very important for my project. Thanks!

chakAs3 commented 1 year ago

Hi @VegasChickiChicki I put nuxt integration as a priority this week so I will notify you once it is ready for test

VegasChickiChicki commented 1 year ago

Hi @VegasChickiChicki I put nuxt integration as a priority this week so I will notify you once it is ready for test

Thank you so much for your work! This is very important for .

Ibochkarev commented 1 year ago

@chakAs3 Good afternoon

Is there any news on correcting the errors set forth in this issue

chakAs3 commented 1 year ago

hi @Ibochkarev did you try npx storybook-nuxt init ?

cwe-spb commented 1 year ago

@chakAs3 it work just with nuxt 2. For nuxt-3 isn't work. Or i am wrong?

chakAs3 commented 1 year ago

no @cwe-spb it works mainly for Nuxt 3, but should work for both i did not test it for Nuxt 2

Ibochkarev commented 1 year ago

@chakAs3 hello! tried it on a working project

image

image

Storybook Environment Info:

  System:
    OS: macOS 13.5.2
    CPU: (10) arm64 Apple M1 Pro
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.17.1 - ~/.nvm/versions/node/v18.17.1/bin/node
    Yarn: 1.22.17 - /opt/homebrew/bin/yarn
    npm: 9.6.7 - ~/.nvm/versions/node/v18.17.1/bin/npm
    pnpm: 8.7.0 - ~/.nvm/versions/node/v18.17.1/bin/pnpm <----- active
  Browsers:
    Chrome: 117.0.5938.62
    Safari: 16.6
  npmPackages:
    @storybook/addon-a11y: ^7.4.1 => 7.4.1 
    @storybook/addon-essentials: next => 7.5.0-alpha.2 
    @storybook/addon-interactions: next => 7.5.0-alpha.2 
    @storybook/addon-links: next => 7.5.0-alpha.2 
    @storybook/blocks: next => 7.5.0-alpha.2 
    @storybook/builder-vite: next => 7.5.0-alpha.2 
    @storybook/testing-library: ^0.2.0 => 0.2.1 
    @storybook/vue3: next => 7.5.0-alpha.2 
    @storybook/vue3-vite: ^7.4.1 => 7.4.1 
    eslint-plugin-storybook: ^0.6.13 => 0.6.13 
    storybook: next => 7.5.0-alpha.2 
    storybook-addon-designs: ^6.3.1 => 6.3.1 
chakAs3 commented 1 year ago

@Ibochkarev i don't see @storybook-vue/nuxt here you need to install latest version v0.1.0

Ibochkarev commented 1 year ago

@chakAs3 hello

  "devDependencies": {
    "@commitlint/cli": "^17.7.1",
    "@commitlint/config-conventional": "^17.7.0",
    "@namics/stylelint-bem": "^9.0.0",
    "@nuxt/test-utils-edge": "3.7.4-28244742.f000e8b6",
    "@nuxtjs/eslint-config-typescript": "^12.1.0",
    "@pinia-plugin-persistedstate/nuxt": "^1.1.1",
    "@storybook/addon-a11y": "^7.4.1",
    "@storybook/addon-essentials": "next",
    "@types/lodash": "^4.14.198",
    "@typescript-eslint/eslint-plugin": "^6.7.0",
    "@vueuse/nuxt": "^10.4.1",
    "commitizen": "^4.3.0",
    "cz-customizable": "^7.0.0",
    "eslint": "8.49.0",
    "eslint-config-prettier": "^9.0.0",
    "eslint-plugin-prettier": "^5.0.0",
    "eslint-plugin-storybook": "^0.6.13",
    "happy-dom": "^11.0.6",
    "husky": "^8.0.3",
    "jsdom": "^22.1.0",
    "lint-staged": "^14.0.1",
    "nuxt": "^3.7.3",
    "nuxt-vitest": "^0.10.5",
    "prettier": "^3.0.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "sass": "^1.67.0",
    "storybook-addon-designs": "^6.3.1",
    "stylelint": "^15.10.3",
    "stylelint-config-prettier": "^9.0.5",
    "stylelint-config-standard-scss": "^11.0.0",
    "stylelint-order": "^6.0.3",
    "stylelint-prettier": "^4.0.2",
    "stylelint-scss": "^5.1.0",
    "stylelint-selector-bem-pattern": "^3.0.1",
    "typescript": "^5.2.2",
    "vitest": "0.33.0",
    "vitest-environment-nuxt": "^0.10.5",
    "storybook": "next",
    "@types/node": "^18.17.5",
    "@storybook/vue3": "next",
    "@storybook-vue/nuxt": "rc",
    "@storybook-vue/nuxt-storybook": "rc",
    "@storybook/addon-interactions": "next",
    "@storybook/addon-links": "next",
    "@storybook/blocks": "next",
    "@storybook/builder-vite": "next",
    "@storybook/testing-library": "^0.2.0"
  },

.storybook/main.ts

import type { StorybookConfig } from "@storybook-vue/nuxt";

const config: StorybookConfig = {
  stories: [
    '../stories/**/*.stories.mdx',
    '../stories/**/*.stories.@(js|jsx|ts|tsx)',
    '../src/shared/ui/**/*.stories.@(js|jsx|ts|tsx)',
    '../src/entities/**/*.stories.@(js|jsx|ts|tsx)',
    '../src/widgets/**/*.stories.@(js|jsx|ts|tsx)',
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions",
  ],
  framework: {
    name: "@storybook-vue/nuxt",
    options: {},
  },
  docs: {
    autodocs: "tag",
  },
};
export default config;

image

image

image

chakAs3 commented 1 year ago

@Ibochkarev check this https://medium.com/@flashchakir/unleash-your-creativity-with-the-new-storybook-nuxt-module-b7beb1441bed

RGaskinLtd commented 1 year ago

okay, I've done a bit of testing on the nuxtjs/storybook package and it does not support nuxt plugins. it supports composables but sometimes you need access to the nuxt instance.

so please can you create a nuxt plugin like so in the /plugins folder. call it anything. with the following code.

export default defineNuxtPlugin(() => {
  function useMyComposable() {
    // Because your composable is called in the right place in the lifecycle,
    // useRuntimeConfig will also work
    const config = useRuntimeConfig();
    // console.log('useMyComposable config', config)
    return { config };
  }
  return {
    provide: { useMyComposable },
  };
});

and then try to use the plugin in a component like MyComposable like so.

<script setup lang="ts">
const { $useMyComposable } = useNuxtApp();
const { config } = $useMyComposable();
</script>

<template>
  <h1>Using composables :</h1>
  <h5>runtime config :</h5>
  <pre>{{ JSON.stringify(config, null, 2) }}</pre>
</template>

I hope this is a good demostraion of what the problem is. @chakAs3

chakAs3 commented 1 year ago

Hi @RGaskinLtd would please you the latest versions this seems old. please refer to https://storybook.nuxtjs.org/examples/composables and let me know if you still facing an issue

RGaskinLtd commented 1 year ago

I run my test on that exact page with the provide ide

RGaskinLtd commented 1 year ago

if you do the same you will see pretty fast :)

chakAs3 commented 1 year ago

Yes my bad, this example is not up to date

RGaskinLtd commented 1 year ago

ahh okay. let me pull down the repo and try again

RGaskinLtd commented 1 year ago

okay using this repo https://github.com/nuxt-modules/storybook#readme I get the same problem when viewing the component in storybook.

I used the code I provide above. if there's anything I'm missing let me know but the result I get is this.

Error: [nuxt] instance unavailable
  at setup (/components/MyPlugin.vue:7:34))
  at callWithErrorHandling (/node_modules/.cache/sb-vite/deps/chunk-R7BYHUHE.js?v=ca10f6f6:1787:18))
  at setupStatefulComponent (/node_modules/.cache/sb-vite/deps/chunk-R7BYHUHE.js?v=ca10f6f6:8853:25))
  at setupComponent (/node_modules/.cache/sb-vite/deps/chunk-R7BYHUHE.js?v=ca10f6f6:8814:36))
  at mountComponent (/node_modules/.cache/sb-vite/deps/chunk-R7BYHUHE.js?v=ca10f6f6:7219:7))
  at processComponent (/node_modules/.cache/sb-vite/deps/chunk-R7BYHUHE.js?v=ca10f6f6:7185:9))
  at patch (/node_modules/.cache/sb-vite/deps/chunk-R7BYHUHE.js?v=ca10f6f6:6658:11))
  at mountChildren (/node_modules/.cache/sb-vite/deps/chunk-R7BYHUHE.js?v=ca10f6f6:6902:7))
  at processFragment (/node_modules/.cache/sb-vite/deps/chunk-R7BYHUHE.js?v=ca10f6f6:7119:7))
image
chakAs3 commented 1 year ago

ahh okay. let me pull down the repo and try again

yes it should be fine, here is the repo maybe some issue with stackblitz i could not update it https://github.com/chakAs3/nuxt-storybook-composables-example

chakAs3 commented 1 year ago

https://stackblitz.com/~/github.com/chakAs3/nuxt-storybook-composables-example

RGaskinLtd commented 1 year ago
image
RGaskinLtd commented 1 year ago

composables work fine. it's just plugins

RGaskinLtd commented 1 year ago

not sure how to fix it myself tbh been trying for days to intergrate storybook into an existing nuxt3 project with no luck. all comes down to this useNuxtApp being empty.

chakAs3 commented 1 year ago

I can't see your issue but you can start from the link i shared with you, it should work like this image

Otherwise you can just create a reproduction repo for me. i can help be fix the issue

Ibochkarev commented 1 year ago

@chakAs3 Hello

After installation and going to the component description tabs I get an error

ERROR Internal server error: At least one <template> or <script> is required in a single file component. 10:38:06 AM
   Plugin: vite:vue
   File: /Users/ibochkarev/Projects/v3/src/widgets/templates/w-feed-template/w-feed-template.vue

image

This error is displayed in all VUE components described in the story.

Ibochkarev commented 11 months ago

@chakAs3 hello!

Related https://github.com/storybook-vue/storybook-nuxt/issues/4

chakAs3 commented 11 months ago

Salam @Ibochkarev, please can you use the latest version of @storybook-vue/nuxt recently published, it may fix your issue inshallah update nuxt to latest i think 3.8.1

rpowersstl commented 11 months ago

@Ibochkarev I am having the same problem

' ERROR Internal server error: At least one