Jacob.

Module Federation in Rollup.JS

Profile picture for Jacob Ebey
Jacob Ebey

With Webpack 5 Module Federation revolutionizing how we think about JavaScript architecture on large scales, I thought it would only be fair to bring the Rollup.JS community into the loop.

TL;DR

Plugin: https://www.npmjs.com/package/@module-federation/rollup-federation Example: https://github.com/module-federation/module-federation-examples/tree/master/rollup-federation-demo

What is Module Federation?

Module Federation is a scalable solution to sharing code between independently bundled applications. There are a few concepts we need to wrap our head around: Hosts, Remotes, and Bidirectional-Hosts.

A Host can be thought of as your bundle that loads and executes when you land on your webpage. A host can consume federated modules from a Remote, as well as share vendor dependencies to prevent a Remote from loading it's own copy of say "lodash".

A Remote is a separate, standalone bundle where part of it can be consumed by a Host. A Remote can federate any number of modules, as well as provide fallbacks for vendors that the Host does not share itself.

A Bidirectional-Host is a Host that also acts as a Remote, i.e it has the ability to consume federated modules, as well as provide them to others.

In figure 1 we can see a Landing Site (Bidirectional-Host) that exposes the Hero and Footer consumed by the Media Site, the Media Site (Bidirectional-Host) exposes a VideoPlayer consumed by the Landing Site, while both the Landing Site and Media Site consume the Button and Card from the Admin Site (Remote).

figure 1 figure 1

As stage-1 to both prove out and gauge community interest, I have brought the ability for a Rollup.JS bundle to be a Host. This allows you to consume modules from Webpack built Remotes.

This is enabled through the @module-federation/rollup-federation plugin available directly from the Module Federation Org.

Plugin: https://www.npmjs.com/package/@module-federation/rollup-federation Example: https://github.com/module-federation/module-federation-examples/tree/master/rollup-federation-demo Source: https://github.com/module-federation/rollup-federation

Consuming a remote

Let's assume we have a Webpack Remote located at http://localhost:8081/remote-entry.js that was built to target SystemJS and exposes a "./hello" module that itself exports a default function.

You can now consume this remote in a Rollup.JS build with the following setup:

rollup.config.js

Configure the @module-federation/rollup-federation plugin. In this simple example we are going to alias the remote as "webpack_remote". The key is the name we will be importing from in our javascript modules, and the value in this case is the name in our SystemJS import map. We will keep them the same for consistency.

import federation from '@module-federation/rollup-federation';

export default {
  input: './src/index.js',
  output: { format: 'system', dir: './dist' },
  plugins: [
    federation({
      remotes: {
        'webpack_remote': 'webpack_remote'
      },
    })
  ]
};

src/index.js

Dynamically import the remote "hello" module from the Webpack Remote we have aliased as "webpack_remote" in the plugin.

(async () => {
  // Import the hello module from the remote
  const hello = await import('webpack_remote/hello');
  
  // Call the default export of the remote hello module
  hello.default();
})();

index.html

Configure SystemJS import map so it know's where "webpack_remote" lives and start our app by importing the main entry point.

<!doctype html>
<html>
<body>
  <script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>
  
  <script type="systemjs-importmap">
    {
      "webpack_remote": "http://localhost:8081/remote-entry.js",
      "main": "./dist/main.js"
    }
  </script>
<script type="systemjs-module" src="import:main"></script>
</body>
</html>

And that's it! You are now consuming Federated Modules!

For more a more advanced use-case checkout the Module Federation Examples repository located at: https://github.com/module-federation/module-federation-examples/tree/master/rollup-federation-demo

Limitations

Right now a Rollup.JS bundle can only act as a Host, meaning it can only consume federated modules and share runtime vendor dependencies with the Remotes it consumes. I may explore adding the ability to be a Remote, and in the process, enable Bidirectional-Hosts if there is interest.

Feel free to direct questions, or bug me to enable remote on Twitter @ebey_jacob. Also feel free to open PR's to the examples repo for AMD, contribute fixes or additions to the plugin, etc… All contributions welcome!


More Stories

Fighting Burnout During COVID-19

When the hardest thing about software encounters steroids, how can we fight it?

Profile picture for Jacob Ebey
Jacob Ebey

Federated Micro-Frontends in React

Our recommendations on how to travel and stay safe in Asia.

Profile picture for Jacob Ebey
Jacob Ebey

Check out what I could be doing for you.