module-federation / module-federation-examples

Implementation examples of module federation , by the creators of module federation
https://module-federation.io/
MIT License
5.67k stars 1.76k forks source link

feat: shared-directory #4300

Closed zhangHongEn closed 3 weeks ago

zhangHongEn commented 1 month ago

https://github.com/module-federation/vite/pull/131

An alternative solution for the functionality of shared: ["./shared/xxxx.js"].

github-actions[bot] commented 1 month ago

Workflow status is success ✅ Unfortunately test report wasn't generated, it can be if no workspaces changed. Please check the workflow run below. Link to GitHub workflow: Github Workflow Link

github-actions[bot] commented 1 month ago

Workflow status is success ✅ Unfortunately test report wasn't generated, it can be if no workspaces changed. Please check the workflow run below. Link to GitHub workflow: Github Workflow Link

github-actions[bot] commented 1 month ago

Workflow status is success ✅ Unfortunately test report wasn't generated, it can be if no workspaces changed. Please check the workflow run below. Link to GitHub workflow: Github Workflow Link

github-actions[bot] commented 1 month ago

Workflow status is success ✅ Unfortunately test report wasn't generated, it can be if no workspaces changed. Please check the workflow run below. Link to GitHub workflow: Github Workflow Link

Pong420 commented 4 weeks ago

Thanks for the example, it is helpful. For my case I am using vite as the host and found some issues with the plugin

There is my version

import type { FederationRuntimePlugin } from '@module-federation/enhanced/runtime';

type LoadEntryParams = Parameters<NonNullable<FederationRuntimePlugin['loadEntry']>>[0];
type RemoteEntryExports = Awaited<ReturnType<NonNullable<FederationRuntimePlugin['loadEntry']>>>;

const modules = import.meta.glob(['./*.ts', '!./plugin.ts']) as Record<string, () => Promise<Record<string, any>>>;

export default function () {
  return {
    name: 'delegate-modules-plugin',
    loadEntry({ remoteInfo }: LoadEntryParams) {
      if (remoteInfo.name === 'shared') {
        const exports: RemoteEntryExports = {
          init() {},
          get(id: string) {
            return () => modules[id + '.ts']();
          }
        };
        return exports;
      }
    }
  };
}

Issues

  1. dynamic import not work as expected, so using

    const modules = import.meta.glob(['./*.ts', '!./plugin.ts']) as Record<string, () => Promise<Record<string, any>>>;
  2. By the type definition, the get function is a function that return a function that will return Promise instead of a async function Promise<() => any>. But both works

    type RemoteEntryExports = {
    get: (id: string) => () => Promise<Module>;
    init: (shareScope: ShareScopeMap[string], initScope?: InitScope, remoteEntryInitOPtions?: RemoteEntryInitOptions) => void | Promise<void>;
    };
  3. No idea why destructure the object and assign the __esModule will make it not work in host but work in remote

    get(id: string) {
    return async () => {
    const result = await modules[id + '.ts']();
    return {
      ...result,
      __esModule: true
    };
    };
    }
zhangHongEn commented 3 weeks ago

@Pong420

  1. The import(`./${path}`) in the example is valid. As a demonstration, this is the simplest approach, and using import.meta.glob() is absolutely correct.
  2. host works correctly in this example.
ScriptedAlchemy commented 3 weeks ago

This is same as how webpack would do it as far as I remember.