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 async-node and Module Federation #939

Closed
ScriptedAlchemy opened this issue Dec 31, 2022 · 5 comments
Closed

Support async-node and Module Federation #939

ScriptedAlchemy opened this issue Dec 31, 2022 · 5 comments
Labels

Comments

@ScriptedAlchemy
Copy link

🚀 Feature Proposal

A clear and concise description of what the feature is.

Motivation

Async loads do not work with either target: "async-node" or when using module federation on the server (which uses the same mechanics as async-node does under the hood)

Example

import(federated/remote) or require(federated/remote)
import(local/file)

both do not work with async targets, loadable fails to look up the module, likely because theres no chunk load global to patch into.

Ive tested this with the async-node example in this repo, without federation and have the same issue.

Pitch

Federation support would be nice.

Solution

In the other issue with bruno, we discussed adding an option to babel parser to flip require.resolveWeak over to require.
That works, for the most part - but host files cannot be loaded due to all of chunk loading depending on the async-node model.

One solution that solves federation on server and async-node targets is a little loader:

// import { getOptions } from 'loader-utils';

function loader(source) {
  // const options = getOptions(this);

  const { plugins, target } = this._compiler.options;

  const moduleFederationPlugin = plugins.find((plugin) => ['NodeFederationPlugin', 'ModuleFederationPlugin', 'UniversalFederationPlugin'].includes(
    plugin.constructor.name,
  ));

  const regex = new RegExp('require.resolveWeak\\(([\'"])(.+?)\\1\\)');
  const foundWeak = regex.exec(source);
  if (foundWeak && (!target || target === 'async-node')) {
    return [`require("${foundWeak[2]}")`, source].join('\n');
  }

  if (!moduleFederationPlugin) {
    return source;
  }
  const remotes = Object.keys(moduleFederationPlugin.options.remotes);

  // const regex = new RegExp(`require.resolveWeak\\([\"'](${remotes.join('|')})\/(.+?)[\"']\\)`);

  // Replace instances of import() statements that start with "app2" with require()
  // return source.replace('require.resolveWeak','require')
    if (regex.test(source)) {
      const modifiedSource = source.replace(regex, 'require("$1/$2")');
      // return ['require("app2/PokemonList")', source].join('\n');

      console.log('[FEDERATION-LOADER]', modifiedSource);
      return modifiedSource;
    }
  return source;
}

export default loader;
@ScriptedAlchemy
Copy link
Author

this loader would be applied after babel-loader, and would only transform the source of server/node based builds.

@fivethreeo
Copy link
Contributor

fivethreeo commented Dec 31, 2022

Maybe add it to the loadable plugin? Hook into parse and use a constdependency?

@theKashey
Copy link
Collaborator

From this angle option #2 from #938 (comment) sounds more feasible - track all loadable definitions and allow user to pre-import all required components before server starts.
That would require one command to added before "server.start", and no babel/webpack specific logic.

@brunos3d
Copy link

Just moving this discussion further with this new issue

@stale
Copy link

stale bot commented Apr 2, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Apr 2, 2023
@stale stale bot closed this as completed Aug 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants