question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Vue component Error: Failed to mount component

See original GitHub issue

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:

  1. Create story of a custom component.
  2. start-storybook -p 9001 -c .storybook
  3. See error in console

Expected behavior Component Renders correctly

Screenshots Components___Logo_-_Logo_⋅_Storybook_and_New_Issue_·_storybookjs_storybook

System:

  • OS: MacOS
  • Device: Macbook Pro 2018
  • Browser: chrome
  • Framework: vue, nuxt
  • Version: 5.0.11
  • node -v v12.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?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:4
  • Comments:20 (11 by maintainers)

github_iconTop GitHub Comments

2reactions
pockacommented, Dec 14, 2019

This is a configuration issue, not a casing nor loader’s one.

The problem

Adding vue-loader to loaders array. Storybook (in this case, @storybook/vue) has its own preconfigured loaders array. Adding vue-loader to module.rules causes duplicated vue-loader rules, which does <source code> -> vue-loader -> vue-loader.

// like this
module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: ['vue-loader', 'vue-loader']
      }
    ]
  }
}

So you should not add vue-loader without removing an existing one.

How to fix

  1. Just remove the ~vue-loader~ rule for .vue file 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).
// .storybook/webpack.config.js
module.exports = ({ config }) => {
  // config.module.rules.push({
  //   test: /\.vue$/,
  //   use: [{
  //     loader: 'vue-loader',
  //   }]
  // })

  return config
}
  1. If you need to use vue-loader with non-default options, you can add it with removing default one.
// .storybook/webpack.config.js
module.exports = ({ config }) => {
  // Remove SB's default vue-loader
  config.module.rules = config.module.rules.filter(rule =>
    !(rule.test instanceof RegExp) || !rule.test.test('.vue')
  )

  config.module.rules.push({
    test: /\.vue$/,
    use: [
      {
        loader: 'vue-loader',
        options: { /* your options here */ }
      }
    ]
  })
}
1reaction
martinmckennacommented, Jan 4, 2020

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 sass and the scss rules are the semicolon at the end of the imported styles.scss file. 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

const path = require('path');

module.exports = async ({ config }) => {

  function resolve(dir) {
    return path.join(__dirname, '..', dir);
  }

  /** removes existing scss rule */
  config.module.rules = config.module.rules.filter(rule =>
    !rule.test.test('.scss')
  )
  config.module.rules.push({
    test: /\.sass$/,
    use: [
      'vue-style-loader',
      'css-loader', {
        loader: 'sass-loader',
        options: {
          implementation: require('sass'),
          data: `
            @import '@/styles/styles.scss'
          `,
        }
      },
    ],
  }, {
    test: /\.scss$/,
    use: [
      'vue-style-loader',
      'css-loader', {
        loader: 'sass-loader',
        options: {
          implementation: require('sass'),
          data: `
            @import '@/styles/styles.scss';
          `,
        }
      },
    ],
  })

  config.resolve = {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      vue$: 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    },
  };

  return config;
}; 
Read more comments on GitHub >

github_iconTop Results From Across the Web

VueJs: Failed To Mount Component - Stack Overflow
You have not imported your component in app.js file, you should import this component file. Let say it's name is xyz.vue.
Read more >
【Help Wanted】Failed to mount Vue component error #4644
I've managed to make it work without typescript. Thise error: [Vue warn]: Failed to mount component: template or render function not defined.
Read more >
Failed to mount component: template or render function not ...
From this forum and SO, It seems the error in the subject line is commonly fixed by adding “.default” after a require statement,...
Read more >
Failed to mount component: template or render ... - Laracasts
after gulp ,i visit the page but return an error Failed to mount component: template or render function not defined, my code below...
Read more >
Jest Vue: [Vue warn]: Failed to mount component: template or ...
I get the following error and shallowMount or mount return empty html console.error node_modules/vue/dist/vue.js:634 [Vue warn]: Failed to ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found