vite-plugin-federation icon indicating copy to clipboard operation
vite-plugin-federation copied to clipboard

if (module.default) module = module.default not work for some libraries like naive-ui

Open tky753 opened this issue 2 years ago • 8 comments

Versions

  • vite-plugin-federation: 1.2.2
  • vite: 4.3.5

Reproduction

My Vue Project uses naive-ui as ui library, when i share naive-ui between host and remote, the remote can't load naive-ui. After I dug into federation_fn_import.js, I found code:

async function getSharedFromRuntime(name, shareScope) {
 ......
 if (module) {
    if (module.default) module = module.default
    moduleCache[name] = module
    return module
  }
}

and naive-ui libray indeed has default export with other components at the same level image

Maybe there should be an option for not running?

if (module.default) module = module.default

tky753 avatar May 09 '23 02:05 tky753

I have the same issue. Is there any workaround or are there plans to customize this behavior?

BSoft-online avatar May 10 '23 13:05 BSoft-online

I found a workaround for this issue. I will explain it on the zustand example.

zustand returns a function as a default export but it has a lot of named exports. vite-plugin-federation loads only that function without the rest of the exports because of the issue @tky753 described.

The workaround: In your remote application's vite.config.ts stop zustand from being imported from the remote app:

...
shared: [
  {
    zustand: {
      import: false,
    },
  },
],
...

In your host application prepare a wrapper that will change the way of zustand's exporting (of course you need to install zustand there):

const baseZustand = require('zustand');

const { default: react, ...rest } = baseZustand;
const zustand = { react, ...rest };

module.exports = zustand;

and use this wrapper in your host's vite.config.ts file:

...
shared: [
  {
    zustand: {
     packagePath: './src/utils/wrappers/zustand.cjs',
    },
  },
],
...

It creates problems if you would like to use the default export in your code and the remote app won't work on its own but it will work together with the host app.

This particular example helps also with multiple React instances issue (because zustand's deps use React and that may be a problem).

BSoft-online avatar May 11 '23 10:05 BSoft-online

This can be a problem because not all libraries follow a standard, some libraries have all exports in their defaults, while others may have their defaults at the same level as other exports

Jiannan-dev avatar May 16 '23 07:05 Jiannan-dev

Even if I could add a manual configuration to let the user choose, it would be a disaster to configure this option for projects with many dependencies

Jiannan-dev avatar May 16 '23 07:05 Jiannan-dev

@ruleeeer I think it's still better than what we have now - we have to write wrappers for such dependencies or we shouldn't share those libraries (and that's the tricky part if the library uses React).

Besides the possibility to decide how to treat a single shared library's export would give us a chance to handle this behavior for specific cases only (not for all of the shared dependencies).

The best solution would be to handle the problematic cases without the need to add a new option (by checking if the default export contains the named exports or by some better solution :) ).

BSoft-online avatar May 16 '23 08:05 BSoft-online

@ruleeeer I found a standard import('xxx module ') returns something like image

so, what about changing

if (module.default) module = module.default

to

if (module?.default[Symbol.toStringTag] === 'Module') module = module.default

tky753 avatar May 30 '23 07:05 tky753

This doesn't seem to work with react. I tried to use the packages/examples/react-vite example and it won't work with the main branch but with the v1.2.3 release commit

MauriceAyasse avatar Aug 30 '23 11:08 MauriceAyasse

The fix has been released so we can try it now :)

BSoft-online avatar Sep 18 '23 05:09 BSoft-online