storybook: Vue component Error: Failed to mount component
Describe the bug Custom components imported to Storybook do not render, console error:
[Vue warn]: Failed to mount component: template or render function not defined.
found in
---> <Logo> at components/logo/Logo.vue
To Reproduce Steps to reproduce the behavior:
- Create story of a custom component.
start-storybook -p 9001 -c .storybook- See error in console
Expected behavior Component Renders correctly
Screenshots

System:
- OS: MacOS
- Device: Macbook Pro 2018
- Browser: chrome
- Framework: vue, nuxt
- Version: 5.0.11
node -vv12.3.1
Additional context
package.json
{
// ...
"author": "Alvaro Saburido",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
"precommit": "npm run lint",
"test": "jest --verbose",
"serve:static": "nuxt generate && serve ./dist",
"storybook": "start-storybook -p 9001 -c .storybook"
},
"dependencies": {
"@nuxtjs/pwa": "^2.6.0",
"babel-plugin-dynamic-import-node": "^2.2.0",
"cross-env": "^5.2.0",
"nuxt": "^2.8.0",
"nuxt-i18n": "^5.12.3",
"save": "^2.4.0"
},
"devDependencies": {
"@nuxtjs/eslint-config": "^0.0.1",
"@nuxtjs/style-resources": "^0.1.2",
"@storybook/addon-actions": "5.0.11",
"@storybook/addon-centered": "5.0.11",
"@storybook/addon-console": "^1.1.0",
"@storybook/addon-options": "5.0.11",
"@storybook/addon-storysource": "5.0.11",
"@storybook/addon-viewport": "5.0.11",
"@storybook/addons": "5.0.11",
"@storybook/vue": "^5.0.11",
"@vue/test-utils": "^1.0.0-beta.27",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.1",
"babel-jest": "^24.8.0",
"babel-preset-vue": "^2.0.2",
"eslint": "^5.16.0",
"eslint-config-prettier": "^4.3.0",
"eslint-config-standard": ">=12.0.0",
"eslint-loader": "^2.1.2",
"eslint-plugin-import": ">=2.17.3",
"eslint-plugin-jest": ">=22.6.4",
"eslint-plugin-node": ">=9.1.0",
"eslint-plugin-nuxt": ">=0.4.3",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-promise": ">=4.1.1",
"eslint-plugin-standard": ">=4.0.0",
"eslint-plugin-vue": "^5.2.2",
"jest": "^24.8.0",
"node-sass": "^4.12.0",
"nodemon": "^1.19.1",
"prettier": "^1.17.1",
"sass-loader": "^7.1.0",
"storybook-readme": "^5.0.3",
"vue-jest": "^3.0.4",
"vue-loader": "^15.7.0"
}
}
.sotybook/config.js
import { configure } from '@storybook/vue'
import { setOptions } from '@storybook/addon-options'
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
Vue.component('nuxt-link', {
functional: true,
render: function(createElement, context) {
let allClass = {}
let arrClass = context.data.staticClass
? context.data.staticClass.split(' ')
: []
arrClass.forEach(theClass => {
allClass[theClass] = true
})
return createElement('a', { class: allClass }, context.children)
}
})
Vue.component('no-ssr', {
functional: true,
render(_createElement, context) {
return context.children
}
})
setOptions({
name: 'Arepa Ipsum',
url: 'https://github.com/hunterliu1003/blog',
addonPanelInRight: true
})
const req = require.context('../components', true, /stories\.js$/)
function loadStories() {
req.keys().forEach(filename => req(filename))
}
configure(loadStories, module)
.storybook/webpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.stories\.js?$/,
loaders: [require.resolve('@storybook/addon-storysource/loader')],
enforce: 'pre'
},
{
test: /\.vue?$/,
use: ['vue-loader', 'vue-style-loader']
}
]
},
resolve: {
alias: {
'@': path.dirname(path.resolve(__dirname)),
vue$: 'vue/dist/vue.common.js'
}
}
}
Logo.vue
<template>
<h1 class="logo">
<img src="~/assets/svg/icon.svg" alt="Arepa Ipsum Logo" />
</h1>
</template>
<style scoped>
.logo {
width: 256px;
height: 256px;
}
</style>
⚠️UPDATE: after a lot of digging into it, the problem is when using vue-loader in the webpack.config.js together with storybook. I saw in other issues it’s a pretty common problem reported before. Any known fix?
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 4
- Comments: 20 (11 by maintainers)
This is a configuration issue, not a casing nor loader’s one.
The problem
Adding
vue-loaderto loaders array. Storybook (in this case,@storybook/vue) has its own preconfigured loaders array. Addingvue-loadertomodule.rulescauses duplicatedvue-loaderrules, which does<source code> -> vue-loader -> vue-loader.So you should not add
vue-loaderwithout removing an existing one.How to fix
vue-loader~ rule for.vuefile from your custom webpack config (.storybook/webpack.config.js). In many cases, you won’t need to set it manually (@storybook/vue’s default config does the job well).vue-loaderwith non-default options, you can add it with removing default one.I posted in #7593, but I suppose it makes more sense to post my final webpack config here as well for anyone who’s having similar issues:
From #7593 :
ok I got this working with the following config. Hoping this helps someone in the future. The difference between the
sassand thescssrules are the semicolon at the end of the importedstyles.scssfile. One expects semicolons and one doesn’t so combining them into 1 loader became impossible.Frankly getting Storybook working with Vuetify is entirely too much trouble
OK, my bad I just did not look at your screenshot hard enough. I have your story. Just as a rule of thumb, if you want to share code, it usually is better to share it with text 😉
Thank you for sharing.