Subscribe on changes!

Error Report: cannot compile child components of asynchronous components

avatar
Oct 15th 2021

Version

3.2.20

Reproduction link

github.com

Steps to reproduce

cd vue3

npm install

npm start

cd vue2

npm install

npm start

What is expected?

Components are resolved recursively expected dom tree

<div>
    <span>my outer component</span>
    <div>hello world</div>
</div>

What is actually happening?

Only the outermost component is parsed, and the sub-components are not parsed correctly,which results in a dom node like this

<div>
  <span>my outer component</span>
  <hello-world></hello-world>
</div>

the same problem in https://github.com/vuejs/vue-next/issues/4799;

avatar
Oct 15th 2021

On first look, without running it, I'd say you forgot to exclude Vue from the federated bundle / declaring Vue as shared dependebcy in the federation, ending up with two copies of Vue in your final app.

It will end up being about something of that nature.

avatar
Oct 15th 2021

I just ran the Vue 3 example wih npm start and this is what I see: Bildschirmfoto 2021-10-15 um 19 18 40

Looks like everything is working?

For the record though, like with react, you likely want your mofed config to declare Vue as a shared dependency:

const moduleFederationConfig = {
  name: AssetMatrixModule.name,
  filename: AssetMatrixModule.fileName,
  exposes: {
    "./Main": "./src/pages/main.vue",
  },
  remotes: {},
  shared: {
    vue: {
      singleton: true,
      eager: true,
    },
  },
};
avatar
Oct 16th 2021

I just ran the Vue 3 example wih npm start and this is what I see: Bildschirmfoto 2021-10-15 um 19 18 40

Looks like everything is working?

For the record though, like with react, you likely want your mofed config to declare Vue as a shared dependency:

const moduleFederationConfig = {
  name: AssetMatrixModule.name,
  filename: AssetMatrixModule.fileName,
  exposes: {
    "./Main": "./src/pages/main.vue",
  },
  remotes: {},
  shared: {
    vue: {
      singleton: true,
      eager: true,
    },
  },
};

Hi, thanks for your reply. The Vue3 demo works well, while when it is used in Vue2, it cannot compile the child component, that is the question i am trying to resolve. And i have tried the shared configuration, but it not works for me. Maybe vue2 cannot use vue3 components? Or is there some other ways for using vue3 components in vue2? Hope to get your advice.

avatar
Oct 16th 2021

I see, that wasn't really clear to me.

The underlying issue is likely the same though. In the console you see these warnings:

[Vue warn]: resolveComponent can only be used in render() or setup(). [Vue warn]: withDirectives can only be used inside render functions.

These indicate that the imported Vue 3 component uses another copy of the vue package than the consuming application. Vue 3 internally relies on some singleton values though (similar to react), so you need to have one shared copy in the consuming app.

The problem here is likely that in the consuming app, Vue 3 is aliased as "vue3", and "vue" points to Vue 2, while the federated module uses "vue" for the Vue 3 package.

There might be a way to solve this with some combination of sharing hint options, but that is outside of my expertise and outside of the scope of this repository to solve.

https://webpack.js.org/plugins/module-federation-plugin/#sharing-hints

avatar
Oct 18th 2021

I see, that wasn't really clear to me.

The underlying issue is likely the same though. In the console you see these warnings:

[Vue warn]: resolveComponent can only be used in render() or setup(). [Vue warn]: withDirectives can only be used inside render functions.

These indicate that the imported Vue 3 component uses another copy of the vue package than the consuming application. Vue 3 internally relies on some singleton values though (similar to react), so you need to have one shared copy in the consuming app.

The problem here is likely that in the consuming app, Vue 3 is aliased as "vue3", and "vue" points to Vue 2, while the federated module uses "vue" for the Vue 3 package.

There might be a way to solve this with some combination of sharing hint options, but that is outside of my expertise and outside of the scope of this repository to solve.

https://webpack.js.org/plugins/module-federation-plugin/#sharing-hints

Hi, thanks a lot for your reply. And i have resolved the problem by setting the module federation shared options, and changed the vue3 dependency of vue to vue3. The config files as follows, in vue2,

const moduleFederationConfig =  {
  name: FinderWebClientModule.name,
  filename: FinderWebClientModule.fileName,
  exposes: {},
  remotes: {},
  shared: {
    vue3: {
      singleton: true,
    },
  },
}

in vue3,

const moduleFederationConfig =  {
  name: AssetMatrixModule.name,
  filename: AssetMatrixModule.fileName,
  exposes: {
    './Main': './src/pages/main.vue',
  },
  remotes: {},
  shared: {
    vue3: {
      singleton: true,
      eager: true,
    },
  },
};

and the dependency in package.json of vue3

 "vue": "^3.2.20",  ->  "vue3": "npm:vue@^3.2.20",

And thank you very much for the advice!