Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic imported vue component failed to resolve

When I try to import a dynamic component with the import() function I receive following error:

[Vue warn]: Failed to resolve async component: function () {
    return __webpack_require__("./src/components/types lazy recursive ^\\.\\/field\\-.*$")("./field-" + _this.type);
}
Reason: Error: Loading chunk 0 failed.

Unfortunately I don't know what causes this error. I already tried to set the esModule to false inside the vue-loader config due to the Release Notes.

I used vue-cli 2.9.2 with the webpack template to setup this project and this is the code of the actual component:

<template>
    <div>
        <component :is="fieldType">
            <children/>
        </component>
    </div>
</template>

<script>
export default {
    name: 'DynamicComponent',
    props: {
        type: String,
    },
    computed: {
        fieldType () {
            return () => import(`./types/type-${this.type}`)
        }
    }
}
</script>


[RESOLVED]
The code above works. The issue was based on the Loading chunk 0 failed due to an edge case. With webpack setting output: {publicPath: '/'} it delivers the chunks relative to the root instead of its origin. When I embed the http://localhost:8080/app.js in my external server and called from there the import function the linked chunk url was http://myserver.com/0.js instead of http://localhost:8080/0.js. To fixed this I had to set output: {publicPath: 'http://localhost:8080/'} in the webpack configuration.

like image 483
kindisch Avatar asked Apr 27 '18 00:04

kindisch


1 Answers

The root cause is import() is async (it returns a Promise) which the error you got already told you:

[Vue warn]: Failed to resolve async component

Using a watch will be better like below demo (Inside Promise.then(), change componentType), then hook beforeMount or mounted to make sure props=type is intialized correctly.:

<template>
    <div>
        <component :is="componentType">
            <children/>
        </component>
    </div>
</template>

<script>
import DefaultComponent from './DefaultComponent'

export default {
    name: 'DynamicComponent',
    components: {
        DefaultComponent
    },
    props: {
        type: String,
    },
    data: {
        componentType: 'DefaultComponent'
    },
    watch: {
        type: function (newValue) {
            import(`./types/type-${newValue}`).then(loadedComponent => { this.componentType = loadedComponent} )
        }
    },
    mounted: function () {
        import(`./types/type-${this.type}`).then(loadedComponent => { this.componentType = loadedComponent} )
    }
}
</script>
like image 93
Sphinx Avatar answered Oct 21 '22 02:10

Sphinx