\"Failed to mount component” error on Laravel 5.3.

2019-09-16 01:53发布

问题:

I have been working on Laravel + Vue.js. I would like to develop Vue components onto Laravel Blade template, but when I tried doing that, the following error occured, and it doesn’t work well.
* For the purpose of checking, I have just written only a minimal code of Vue components.

I tried various things in reference to the following articles.
https://github.com/vuejs/vue-loader/issues/287

The problem which is occuring and the error message

[Vue warn]: Failed to mount component: template or render function not defined. (found in anonymous component - use the "name" option for better debugging messages.)

index.blade.php

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
    <div id="app"></div>
<script src="js/bundle.js"></script>
</body>
</html>

app.js

import Vue from 'vue'
import InputText from './components/InputText.vue'

new Vue({
    render(h) {
      return h(InputText)
    }
}).$mount('#app')

InputText.vue

<template>
    <input class="input-text" type="text">
</template>

<script>
export default {
}
</script>

<style lang="sass" scoped>
</style>

gulp.file.js

const elixir = require('laravel-elixir');
require('laravel-elixir-vue-2');

elixir(mix => {
    mix.sass('**/*.scss')
       .webpack('')
});

webpack.config.js

const webpack = require('webpack');

module.exports = {
  entry: {
    bundle: './resources/assets/js/app.js',
  },
  output: {
    filename: '[name].js',
  },
  resolve: {
    root: __dirname,
    extensions: ['', '.js', '.vue'],
    modulesDirectories: ['node_modules'],
    alias: {
      vue: 'vue/dist/vue.js',
    },
  },
  module: {
    loaders: [
      {
        test: /\.vue?$/,
        loader: 'vue-loader',
      },
      {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/,
      },
      {
        test: /\.html$/,
        loader: 'vue-html',
      },
      {
        test: /\.(jpg|png)$/,
        loader: 'url-loader?limit=10000',
      },
    ],
  },
  vue: {
    loaders: {
      scss: 'style!css!sass',
    },
  },
};

package.json

"devDependencies": {
    "babel-core": "^6.17.0",
    "babel-loader": "^6.2.5",
    "babel-plugin-transform-runtime": "^6.15.0",
    "babel-preset-es2015": "^6.16.0",
    "babel-runtime": "^6.11.6",
    "laravel-elixir": "^6.0.0-11",
    "laravel-elixir-browsersync-official": "^1.0.0",
    "laravel-elixir-vue-2": "^0.2.0",
    "laravel-elixir-webpack-official": "^1.0.6",
    "vue": "^2.0.1",
    "vue-loader": "^9.5.1",
    "webpack": "^1.13.2"
    ...
}

complementary information

Laravel 5.3.10
Node.js 6.4.0
npm 3.9.3

回答1:

You need to register the InputText component in order to use it within your root component. Here it is using the ES2015 shorthand.

import Vue from 'vue'
import InputText from './components/InputText.vue'

new Vue({
    components: {
        InputText
    },

    render(h) {
      return h(InputText)
    }
}).$mount('#app')


回答2:

Add esModule: true next to loaders under vue in your webpack.config.js and you should be good to go.

Alternatively you may use const Vue = require('vue') instead of import Vue from 'vue' which tries to load the default export from the generated module from your component, and it is unable to do so, unless you tell the vue-loader to generate compatible code.

Actually it is a more general incompatibility between the specs, where export default foo doesn't mean the same as module.exports = foo. When you require the former, it will give you an object { default: foo } whereas the latter will return foo unencapsulated.

That's why you have to tell vue-loader if you are using either of the specs.