Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support types consumption with RuntimePlugins #3379

Open
2 tasks done
arivasnxt opened this issue Dec 19, 2024 · 6 comments
Open
2 tasks done

Support types consumption with RuntimePlugins #3379

arivasnxt opened this issue Dec 19, 2024 · 6 comments

Comments

@arivasnxt
Copy link

arivasnxt commented Dec 19, 2024

Clear and concise description of the problem

As a developer using Module Federation I want that remote types can also be consumed for remotes changed or created at runtime with a RuntimePlugin so that the @mf-types can be generated in my host app for those modules too.

Suggested solution

Refetch types if the remotes change at runtime.

Alternatives

Additional context

Module Federation runtime plugins allow developers to manage the module federation lifecycle at runtime. My issue is that we are providing a template URL in the bundlers plugin configuration, and with a plugin at runtime we are replacing the placeholders. This works for fetching the module, but not the types, as they are fetched in another lifecycle.

Examples
rspack.config.ts

const MFPlugin = new ModuleFederationPlugin({
  name: 'HostApp',
  remotes: {
    myRemote: 'MyRemote@https://example.org/myRemote/$VERSION/mf-manifest.json',
  },
  runtimePlugins: [resolve(__dirname, './versionInjectionPlugin.ts')],
}),

plugin

export const versionInjectionPlugin: () => FederationRuntimePlugin = () => {
  return {
    name: "mfe-version-injection-plugin",
    beforeRequest(args) {
      args.options.remotes = (args.options.remotes as RemoteWithEntry[]).map((remote) => {
        remote.entry = remote.entry.replace("$VERSION", version);
        return remote;
      });
      return args;
    },
  };
};

The ConsumeTypesPlugin uses my template URL instead of the one with the injection, so the @mf-types folder is not generated in my host proejct. The remote module is fetched correctly.

image

Validations

  • Read the Contributing Guidelines.
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
@zhoushaw
Copy link
Collaborator

@arivasnxt We are considering providing a cli to support the pull type, which can provide more flexible capabilities

@reactexcell
Copy link

reactexcell commented Jan 15, 2025

` I just added runtimePlugin to override the entry point here is my plugin file

`const runtimePlugin: () => FederationRuntimePlugin = function () {
return {
name: 'module-federation-runtime-plugin',
beforeInit: args => {
return args;
},
init: async args => {
if (!isLocalServer()) {
args.options.remotes.forEach((remote: any) => {
remote.entry = getRunTimeRemoteUrl(remote.entry);
});
}
return args;
},
beforeLoadShare: async args => {
return args;
},
}
};

export default runtimePlugin;`

and this is my moduleFederation config file

import NextFederationPlugin from "@module-federation/nextjs-mf";
import withSvgr from "next-plugin-svgr";
import { containerBasePath } from "./basePath.config.mjs";
import nextFederationPluginConfig from "./moduleFederation.config.mjs";
import MadgePlugin from "./madgePlugin.mjs";

const isStandaloneEnabled = process.env.ENABLE_STANDALONE === '1';

const nextConfig = withSvgr({
poweredByHeader: false,
eslint: {
ignoreDuringBuilds: true,
},
basePath: containerBasePath,
sassOptions: {
prependData: $containerBasePath: '${containerBasePath}';,
},
experimental: {
instrumentationHook: true,
},
webpack(config, { isServer }) {
config.plugins.push(
new NextFederationPlugin(nextFederationPluginConfig(isServer)),
);
config.plugins.push(new MadgePlugin())
config.output.publicPath = 'auto';
return config;
},
...(isStandaloneEnabled && { output: 'standalone' }),
});

export default nextConfig;

I tested it on local and local-production, it's working fine but failing during CICD deployment, and getting this error

TypeError: Cannot read properties of undefined (reading 'consumes')
at webpack_require.f.consumes (/app/.next/server/webpack-api-runtime.js:249:150227)
at /app/.next/server/pages/api/health.js:249:6550
at Object. (/app/.next/server/pages/api/health.js:249:6760)
at Module._compile (node:internal/modules/cjs/loader:1469:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1548:10)
at Module.load (node:internal/modules/cjs/loader:1288:32)
at Module._load (node:internal/modules/cjs/loader:1104:12)
at Module.require (node:internal/modules/cjs/loader:1311:19)
at mod.require (/app/node_modules/next/dist/server/require-hook.js:65:28)
at require (node:internal/modules/helpers:179:18)

Please help, Thanks.

@reactexcell
Copy link

reactexcell commented Jan 15, 2025

@arivasnxt @ScriptedAlchemy Can you please look into my issue?

@arivasnxt
Copy link
Author

@reactexcell I believe yours is not related to this issue. Please, open a new issue and provide more information about your project, not only the error.

@arivasnxt
Copy link
Author

We are considering providing a cli to support the pull type

@zhoushaw any news about this topic?

Also, doesn't it make sense to refetch types after a remote is updated during a runtime hook? I understand that if I modify a remote in the beforeRequest hook there might be a first request that is not updated, but IMO there should be a second request that fetches the types of the updated remote along with the updated module files.

@ScriptedAlchemy
Copy link
Member

We are considering providing a cli to support the pull type

@zhoushaw any news about this topic?

Also, doesn't it make sense to refetch types after a remote is updated during a runtime hook? I understand that if I modify a remote in the beforeRequest hook there might be a first request that is not updated, but IMO there should be a second request that fetches the types of the updated remote along with the updated module files.

Via runtime plugin could be tricky since runtime plugins are technically bundled, so you'd end up bundling the runtime plugin before starting the actual build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants