Lightning00Blade
Lightning00Blade

Reputation: 175

Vue dynamic component overwrite

My project uses Laravel and Vue (compiled by Laravel-Mix). And has this structure :

enter image description here

What I want is to check if the components exist in the program folder of the overwrite and load it's chunk, if not default to the components folder. There will be multiple program folder in the end. The program names is set into Vuex store ATM. I know a part of this can be achieved by the Vue tag. But that requires explicit declaration of the components and I would like to avoid that as in the end each component would need a huge list of imports.

Upvotes: 1

Views: 684

Answers (1)

Lightning00Blade
Lightning00Blade

Reputation: 175

There is a way to accomplish this. The way you do it is though Webpack chunk splitting. Use the Dynamic Import - Import components via function that return new Promises and have something like '/components/${res}' in the path to the component. First we create a Promise that tries to load our default component as so:

export default function _getDefaultComponent(res){
return new Promise((resolve, reject) => {
    import(
        /* webpackChunkName: "js/chunk/[request]" */
        @/components/${res}
        )
        .then((component) => {
            resolve(component);
        })
        .catch((error) => {
            reject(error);
        });
}

After that we create the function for overwrite as such:

import _getDefaultComponent from "@/helpers/_getDefaultComponent";
import { program } from "@/store/program";

export default function _getComponent(res){
return new Promise((resolve, reject) => {
    let programName = program.state.programName;
    import(
        /* webpackChunkName: "js/chunk/program/[request]" */
        @/@program/${programName}/components/${res}
        )
        .then((component) => {
            resolve(component);
        })
        .catch((error) => {
            _getDefaultComponent(res)
                .then((component) => {
                    resolve(component);
                })
                .catch((error) => {
                    console.error(No Component with the name ${res}, error:, error);
                    reject(error);
                });
        });
    });
}

What we now do is take the name of the program (from Vuex in this case) we try to find a component that is in the program folder if it fails fall back to the default component if that fails as well console an error with component name trying to be resolved. Lastly to use it import is as such:

import _getComponent from "@/helpers/_getComponent";

After that in your component us like:

components:{
    Component: () => _getComponent('Component')
}

Upvotes: 2

Related Questions