Skip to content

Support async-node and Module Federation #939

Closed
@ScriptedAlchemy

Description

@ScriptedAlchemy

🚀 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;

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions