Storybook: Vue components will not mount

Created on 6 Jul 2018  路  19Comments  路  Source: storybookjs/storybook

Custom components imported to Storybook do not render, console error:

[Vue warn]: Failed to mount component: template or render function not defined.

found in

---> <Button> at src/components/Button.vue

This is still following the example given in the docs pretty closely, mostly just renaming components and fitting things into my existing project's dir structure. Non-component stories (e.g. <h2 style="${style}">${content}</h2>) render correctly.

  • @storybook/vue ^3.4.8
  • @storybook/cli: ^4.0.0-alpha.12
  • vue-loader: 14.2.1

.storybook/config.js

import { configure } from '@storybook/vue'
import Vue from 'vue'
import Button from '../src/components/Button'
import Welcome from '../src/stories/Welcome'

// Register custom components.
Vue.component('Button', Button)
Vue.component('Welcome', Welcome)

function loadStories() {
  // You can require as many stories as you need.
  require('../src/stories')
}

configure(loadStories, module)

src/stories/index.js

import { storiesOf } from '@storybook/vue';
import { action } from '@storybook/addon-actions';

import Button from '../components/Button.vue';

storiesOf('Button', module)
.add('story as a component', () => ({
  components: { Button },
  template: ` <Button :rounded="true">rounded</Button> `
}))

src/components/Button.vue

<template>
  <a class="button" :class="{'is-outlined': outlined}" @click="func">
    <slot></slot>
  </a>
</template>

<script>
export default {
  props: {
    func: Function,
    outlined: Boolean
  }
}
</script>

Also have a large, custom webpack config, but I don't know if that's implicated in this or not. Let me know :) It does, however, include:

module.exports = {
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  },
vue question / support

Most helpful comment

I had the same problem but it went away after I removed vue-loader rule from rules in webpack.config.js. Not sure why that worked though.
{ test: /\.vue$/, loader: 'vue-loader', options: { loaders: { } // other vue-loader options go here } },

All 19 comments

I see two gotchas I think you should try correcting to see if they resolve your issue.

1. Vue components should have a hyphenated name that is lower-case in the template.

Button won't work because it's the name of a native element when lowercased, and from what I can tell, camel-cased names might not work in the template function.

Check out the Vue.js Style Guide for more explanation:
Vue.js - v2 - Style Guide - Multi-word component names

2. If you're trying to use v-bind / :, you need to add data to your story.

_This took me a long time to figure out and it's essential to getting Vue components running in Storybook. This should really be added to their example documentation._

In this example:

src/stories/index.js

import { storiesOf } from '@storybook/vue';
import { action } from '@storybook/addon-actions';

import Button from '../components/Button.vue';

storiesOf('Button', module)
.add('story as a component', () => ({
  components: { Button },
  template: ` <Button :rounded="true">rounded</Button> `
}))

(We'll pretend you've renamed your Button component to VueButton throughout.)

Make the storiesOf bit into either this鈥攊f you want to bind a data value to rounded:

storiesOf('VueButton', module)
  .add('story as a component', () => ({
    components: { VueButton },
    data() {
      return {
        rounded: true
      }
    },
    template: `<vue-button :rounded="rounded">rounded</vue-button> `
  }))

Or this鈥攊f you just want to hardcode the boolean:

storiesOf('VueButton', module)
  .add('story as a component', () => ({
    components: { VueButton },
    template: `<vue-button rounded="true">rounded</vue-button> `
  }))

馃寛Basically, in each story, _you're creating a Storybook-specific Vue component to run your component_, so if it doesn't work in a parent component in Vue, it won't in Storybook!

Realizing this really dissolved the illusion of what Storybook was doing. Hope this ends your rendering woes!

@aminimalanimal: Thanks for your response. I've gone through and renamed Button to a compound name and modified the data() values, but I'm still getting the same error.

I don't see anything else that I know would break it in the example you provided. I have Vue working with Storybook in an environment using the same versions of things (though I didn't use @storybook/cli to set mine up), so I do think this is an issue you can resolve somehow and isn't necessarily a bug with Storybook.

I'm not really sure how to continue helping from here without more insight into your current codebase. If you have a public repo, you could share a branch of it, or you can update your example with your latest in hopes there's something obvious that can be caught in code review, or you might try just bootstrapping a simpler project with vue-cli and getting it running there so that you can compare your environments.

My versions:

"@storybook/vue": "^3.4.8",
"vue": "^2.5.16",
"vue-loader": "14.2.1",

I had the same problem but it went away after I removed vue-loader rule from rules in webpack.config.js. Not sure why that worked though.
{ test: /\.vue$/, loader: 'vue-loader', options: { loaders: { } // other vue-loader options go here } },

I seem to be running into the same issue. Project was created with Vue-CLI, nothing fancy apart from using Pug for templates and loading resources with style-resources-loader. At first I added Storybook with @storybook/cli but whole project stopped working so I reset and added it manually.

This is the webpack.config.js:

const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    module: {
        rules: [
            { test: /\.vue$/, use: 'vue-loader' },
            { test: /\.pug$/, use: 'pug-plain-loader' },
            {
                test: /\.styl(us)?$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'stylus-loader'
                ]
            },
        ],
    },

    plugins: [
        new VueLoaderPlugin(),
    ],

    resolve: {
        alias: {
            vue$: 'vue/dist/vue.esm.js',
        }
    },
};

This is component:

<template lang="pug">
p Test
</template>

<script>
export default {
    name: 'Test',
};
</script>

<style scoped lang="stylus">
p
    color fuchsia
</style>

This is story:

import { storiesOf } from '@storybook/vue';
import Test from '../src/components/Test.vue';

storiesOf('Test', module)
    .add('as dumb as possible', () => ({
        components: { Test },
        template: '<test></test>',
    }));

Thanks to VueLoaderPlugin and alias for vue$ all should load. But the component doesn鈥檛 load and in console I can find:

vue.esm.js:591 [Vue warn]: Failed to mount component: template or render function not defined.

found in

---> <Test> at src\components\Test.vue
       <Anonymous>
         <Root>

If I put template: '<div>test</div>, it will load without problems, so parsing component fails.


Whole code can be seen here: todo-vue.

@krazov I'm having the exact same issue, my setup and config is almost identical to yours except I'm not using pug in my template. I'm also getting [Vue warn]: Failed to mount component: template or render function not defined.

I'm having the same problem with an extremely vanilla vue-cli project. Has anyone found the solution to this?

@nickolas1, what I discovered was that setting vue-loader to version 14 was fixing Storybook, but breaking Vue app, so due to time constraints we dropped storybook in our project.

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

I've run into this issue as well. Is it possible vue-loader and single file components don't work well with storybook?

Has anyone gotten single file components to work?

Do you have a reproduction repo?

Right now my code is private but I can post something public shortly.

Cool

Repo is here @igor-dv
https://github.com/unjust/storybook_vue

If you install and run the app yarn run storybook MyButton.vue - the single file component, gives an error.

Thanks. Will try to get into this later tody.

I tried using vue-cli-plugin-storybook which seems to be working ok.

@unjust , I've checked your repo. You are using @storybook/[email protected] that has a peer to vue-loader@14, while you are using vue-loader@15. Also, you have extended the webpack config with the vue rules to use a new loader version + plugin, while storybook has its own vue rules. All these introduce a conflict.

What you can do:

  1. Downgrade the loader to v14 (I assume you don't want to do this)
  2. Use a full control mode of the extended webpack config and replace the SB vue rules with yours
  3. Use vue-cli-plugin-storybook that solves different problems with SB and vue integrations - @pksunkara can elaborate more on this
  4. Upgrade Storybook to v4 - which already works with a new version of the vue-loader

ok thank you for the suggestions. Upgraded to Storybook v4 and deleted my webpack config and it works now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

levithomason picture levithomason  路  3Comments

zvictor picture zvictor  路  3Comments

shilman picture shilman  路  3Comments

tirli picture tirli  路  3Comments

miljan-aleksic picture miljan-aleksic  路  3Comments