0
votes

I have got a fresh install of Laravel Mix and I am trying to setup lazy loading components in the project. I have got the correct setup with the babel plugin 'syntax-dynamic-import' so the import statement in app.js works as expected. The issue occurs when I attempt to use the lazy loaded component with vue-router.

My app.js file looks like this:

require('./bootstrap');

import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

const EC = () => import(/* webpackChunkName: "example-component" */ './components/ExampleComponent.vue');

const router = new VueRouter({
    mode: 'history',
    routes: [
        { path: '/', component: EC }
    ]
});

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

and my welcome.blade.php file looks like this:

<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>Laravel</title>

    <link href="{{ asset('css/app.css') }}" rel="stylesheet">

    <base href="/" />
</head>
<body>
<div id="app">
    <h1>Base title</h1>
    <example-component></example-component>
</div>

<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>

So I just trying to land on the root route and display the Example Component. The example component is included in the welcome.blade.php file.

I am receiving this error in the console:

[Vue warn]: Unknown custom element: <example-component> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

(found in <Root>)

I think I am missing something simple, any advice is appreciated.

3

3 Answers

1
votes

First, i think you are mixing routes concepts with core components vue concepts...

Try loading the component directly in your vue app...

const app = new Vue({
    router,
    el: '#app',
    components: {
        'example-component': () => import('./components/ExampleComponent.vue')
    }
});

Component loading is done with <component>

<component v-bind:is="currentTabComponent"></component>

Check the docs, for more info on dynamic components: https://vuejs.org/v2/guide/components-dynamic-async.html

0
votes

@Erubiel answer did work but it still quite wasn't the setup I wanted. As I am trying to use vue-router I needed to update the view by removing the explicit call to the component and adding the tag in the welcome.blade.php file. This now means my routes are injected into that space. The updated area is:

...
<body>
<div id="app">
    <router-view></router-view>
</div>

<script src="{{ asset('js/app.js') }}"></script>
</body>
...
0
votes

The problem is in the scss splitting in Vue and using mix.scss() both. Laravel mix when having both creates a css file with manifest js file content in it. which is definitely a bug. which the community mentions a bug from Webpack and will be resolved in webpack 5. But If you use only code splitting in Vue and have the default app.scss file imported to main Vue component like this(not in scope), so each other component will get the styling properly

// resources/js/components/app.vue
<template>
 <!-- Main Vue Component  -->
</template>

<script>
// Main Script
</script>

<style lang="scss">
  @import '~@/sass/app.scss';
</style>

and the webpack.mix.js file will have no mix.scss function to run only a single app.js file. here is my file.

// webpack.mix.js
const mix = require('laravel-mix')
mix.babelConfig({
  plugins: ['@babel/plugin-syntax-dynamic-import'] // important to install -D
})

mix.config.webpackConfig.output = {
  chunkFilename: 'js/[name].bundle.js',
  publicPath: '/'
}

mix
  .js('resources/js/app.js', 'public/js')
  .extract(['vue'])
  .webpackConfig({
    resolve: {
      alias: {
        '@': path.resolve('resources/') // just to use relative path properly
      }
    }
  })

Hope this solves everyone's question