Dynamically load the component (dynamic import in render function) inside the render function

problem description

want to achieve a component X, according to the incoming prop mode, dynamic load component C1 / component c2max. / component c10000 in one of the
requirements can not be loaded extra chunk, to achieve lazy load
that is, if the prop input request to load C1, never load other components such as c2 js chunk load, until prop change the requirement to display c2 before allowing asynchronous loading of c2 corresponding chunk (a bit of cmd taste). Therefore, it is not possible to load all the chunk in Chinese style and then display it on demand

.

the environmental background of the problems and what methods you have tried

the first thing that comes to mind is that the first parameter of createElement in render can be async function and webpack"s dynamic import
document
clipboard.png

.

there is also related support in the source code
https://github.com/vuejs/vue/.

my related code

directory structure

.
 Bar.vue
 Baz.vue
 Fail.vue
 Foo.vue
 X.vue

my code

<script>
export default {
    name: "X",
    props: {
        mode: String,
    },
    render(createElement) {
        let child;
        switch (this.mode) {
            case "Foo":
            case "Bar":
            // ... some other case
            case "Baz":
                child = () => import(`./${this.mode}`);
                break;
            default:
                child = () => import("./Fail");
                break;
        }
        
        return createElement(child);
    },
};
</script>
< H2 > but < / H2 >

as a result, the program keeps executing render, and falls into an endless loop
if changed to return createElement (() = > child (). Then (o = > o.defalut));
, it will not be executed only once, but an empty node is created

at this point, the problem can be changed into the following minimum reproducible model, and the render is still executed in an endless loop

.
export default {
    name: "X",
    render(createElement) {
        debugger;
        return createElement(
            () => new Promise(resolve => {
                setTimeout(
                    () => resolve("p"),
                2000);
            })
        );
    },
}; 

what result do you expect? What is the error message actually seen?

normal render. Do not want to use template to implement, require to use render function rigid
if not, please point out the reasons for not being able to do so

Oct.21,2021

cannot do this, because it is a function that will be re-executed every time there is a change. You can use a key-value pair to save your asynchronous component

const comps = {
    a: () => import('./a')
}

since component loading depends on props, try putting judgment logic on computed.

export default {
  name: "X",
  data() {
    return {
      mode: 'Foo'
    }
  },
  computed: {
    com() {
      let child;
      switch (this.mode) {
        case "Foo":
        case "Bar":
        case "Baz":
          child = () => import(`./${this.mode}`);
          break;
        default:
          child = () => import("./Fail");
          break;
      }
      return child;
    },
  },
  methods: {
    clickHandler(e) {
      this.mode = e;
    },
  },
  render(createElement) {
    return createElement('div', {}, [
      createElement('button', {
        on: {
          click: () => this.clickHandler('Foo'),
        },
      }, 'Foo'),
      createElement('button', {
        on: {
          click: () => this.clickHandler('Bar'),
        },
      }, 'Bar'),
      createElement('button', {
        on: {
          click: () => this.clickHandler('Baz'),
        },
      }, 'Baz'),
      createElement(this.com),
    ]);
  },
}
Menu