Storybook: Unable to use Vuetify treeShake

Created on 9 Nov 2020  路  4Comments  路  Source: nuxt-community/storybook

I believe this is an issue with this module. When using the treeShake option in Vuetify config which is needed for customising the sass variables in Vuetify the <v-app> component isn't registered and therefore doesn't initialise.

Version

@nuxtjs/storybook: 3.1.0
nuxt: 2.14.9
@nuxtjs/vuetify: 1.11.2

Reproduction Link

https://codesandbox.io/s/elegant-forest-6juvw
https://6juvw.sse.codesandbox.io/?path=/story/button--primary-button

Steps to reproduce

Add treeShake: true to vuetify config block in nuxt.config.js. Run storybook as normal, see 'Primary Button' example.

What is Expected?

The button should be blue. If the VApp component were initialised correctly the v-application class is applied to the v-app element and the theme works.

What is actually happening?

See console for error - v-app is unregistered.

[Vue warn]: Unknown custom element: <v-app> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

found in

---> <Anonymous>
       <Root>
bug

Most helpful comment

To set up a VApp globally by referring to the method in the @dankellett

npx nuxt storybook eject

change .storybook/preview.js

import '~~/.nuxt-storybook/storybook/preview.js'
import {VApp} from 'vuetify/lib'

export const decorators = [() => {
  return {
    template: "<v-app><story/></v-app>",
    components: {VApp}
  }
}]

This way you don't have to call the VApp every time!

All 4 comments

While using treeShake: true the @nuxtjs/vutify module uses vuetify-loader to detect components. It seems that vuetify-loader only support SFC files and does not detect components that used in templates.

I'm not very familiar with vuetify-loader to know we can achieve this with loader. But there are other workarounds in your situation. You can create a Dummy component (let's call it SApp) and v-app inside this component and in your stories use s-app instead of v-app

SApp.vue

<template>
<v-app><slot /></v-app>
</template>

MyButton.stories.js

export const primaryButton = () => '<s-app><MyButton type="primary">Primary Button</MyButton></s-app>'

The following Story definition imports the Vuetify components and prevents the need for the custom "wrap" component. You will need to have the vuetify/lib reference in the types array of your tsconfig.json if you are using TypeScript. This works with tree shaking enabled, which in-turn allows the Vuetify variables to be set.

[working code]

import { VApp, VBtn } from 'vuetify/lib'
export default { title: 'Button' }

export const primaryButton = () => ({
  template:
    '<v-app><v-btn depressed color="primary">Primary Button</v-btn></v-app>',
  components: { VApp, VBtn },
})

If you want to use decorators, local or global, the Vuetify components also need to be referenced in the components property.

[working code]

import { VApp, VBtn } from 'vuetify/lib'
export default { title: 'Button' }

export const primaryButton = () => ({
  template: '<v-btn depressed color="primary">Another Button</v-btn>',
  components: { VBtn },
})
primaryButton.decorators = [
  () => ({
    template: `<v-app><story/></v-app>`,
    components: { VApp },
  }),
]

demo repo
https://github.com/dankellett/clean-nuxt-storybook-vuetify

To set up a VApp globally by referring to the method in the @dankellett

npx nuxt storybook eject

change .storybook/preview.js

import '~~/.nuxt-storybook/storybook/preview.js'
import {VApp} from 'vuetify/lib'

export const decorators = [() => {
  return {
    template: "<v-app><story/></v-app>",
    components: {VApp}
  }
}]

This way you don't have to call the VApp every time!

import '~~/.nuxt-storybook/storybook/preview.js'
import {VApp} from 'vuetify/lib'

export const decorators = [() => {
  return {
    template: "<v-app><story/></v-app>",
    components: {VApp}
  }
}]

It works, but I want to add some details.

First, you need to understand that we are configuring the module in manual mode.
https://storybook.nuxtjs.org/examples/manual

You need to create a directory /.storybook and two files main.js and preview.js

main.js

const { nuxifyStorybook } = require('../.nuxt-storybook/storybook/main.js')

module.exports = nuxifyStorybook({
  webpackFinal (config, options) {

    // extend config here

    return config
  },
  stories: [
    // Add your stories here
  ],
  addons: [
    // Add your addons here
  ],
  parameters: {
    backgrounds: {
      default: 'white',
      values: [
        { name: 'white', value: '#ffffff' },
        { name: 'black', value: '#000000' },
      ],
    },
  },
})

and preview.js

import '~~/.nuxt-storybook/storybook/preview.js'
import {VApp} from 'vuetify/lib'

export const decorators = [() => {
  return {
    template: "<v-app><story/></v-app>",
    components: {VApp}
  }
}]

Storybook configuration in the nuxt.config.js file is no longer required and can be deleted.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

armorkram picture armorkram  路  3Comments

behzadam picture behzadam  路  5Comments

seancolsen picture seancolsen  路  4Comments

Atinux picture Atinux  路  3Comments

ponnex picture ponnex  路  5Comments