[Vuejs]-Failed to mount component on new laravel 5.5 project

3👍

If you haven’t changed anything and and have correctly bundled and installed JavaScript then the issue may lie with the default Laravel implementation.

The error message you are receiving means that you are likely importing the runtime only build (vue without the template compiler) in to an app that needs the template compiler.

To better understand this, Vue compiles everything into render functions (essentially a pure JavaScript representation of your webpage). When using single file components you end up with one base component that you mount to your Vue instance, which serves up your all your views, so, we would get something like this:

components/App.vue

<template>
  <div>
    I'm a base component
    <!-- vue-router will mount components here -->
    <router-view></router-view>
  </div>
</template>

app.js

import App from './components/App.vue' 

// "h" is just a standard taken from JSX
new Vue({
  render: h => h(App)
}).$mount("#app");

app.blade.php

<html>
  <head>
    <!-- head stuff -->
  </head>
  <body>
    <div id="app"></div>
    <script src="app.js"></script>
  </body>
</html>

The important thing here is that app.blade.php only acts as a mounting point for your entire app and App.vue serves as the base component, which is turns serves every other view (this would usually be done via vue-router). To get that to work we need to compile our assets into app.js via webpack, which creates all our render functions for us, so we don’t need the compiler because everything has already been compiled. All that’s left to do is create a route in routes/web.php to serve up the index blade file. That’s essentially setting up an SPA.

What Laravel encourages you do, is add Vue components directly in your markup and register components globally, so you would do:

app.js

Vue.component('my-component', require('./components/My-component.vue'));

const app = new Vue({
    el: '#app'
});

index.blade.php

<html>
  <head>
    <!-- head stuff -->
  </head>
  <body>
    <div id="app">
      <my-component></my-component>
    </div>
    <script src="app.js"></script>
  </body>
</html>

Because we’ve added our component to the markup we need the template compiler to compile the bit between our app div tags into a render function at runtime. So, we need to import vue + compiler, which is what Laravel Mix should do for you by aliasing the runtime + compiler version of Vue (you can find details of how to do that in the docs).

To be honest, I’m not a fan of Laravel Mix because it abstracts away crucial implementation details that as a developer you need to know, such as, "is Laravel Mix correctly aliasing the Vue + compiler build"?, in your case it looks like it isn’t.

In the end it’s usually easier to just setup your own webpack config directly so you have total control over your config, you can use Vue’s webpack simple config as a base.

Once you’ve correctly setup webpack, you just then need to add the alias to webpack config and you have your runtime + compiler build in:

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

I realise that I haven’t really given a soultion to your specific problem. I find it hard to believe that Webpack Mix isn’t correctly aliasing the vue + compiler build, but that is what that message implies. Hopefully though, this gives you enough information to find where the problem lies.

Leave a comment