---
title: "Dynamic Remotes, Webpack Module Federation"
description: "How to dynamically load remotes at runtime with Webpack Module Federation. Practical notes and code examples on Dynamic."
url: "https://h3manth.com/scribe/dynamic-remotes-webpack-module-federation/"
canonical_url: "https://h3manth.com/scribe/dynamic-remotes-webpack-module-federation/"
markdown_url: "https://h3manth.com/scribe/blog/dynamic-remotes-webpack-module-federation.md"
publishDate: "2021-06-06T00:00:00.000Z"
author: "Hemanth HM"
category: "web"
tags: ["webpack","javascript","module-federation","microfrontends"]
word_count: 500
reading_time_minutes: 3
x_markdown_tokens: 1082
content_signal: "ai-train=yes, search=yes, ai-input=yes"
---

# Dynamic Remotes, Webpack Module Federation

> How to dynamically load remotes at runtime with Webpack Module Federation. Practical notes and code examples on Dynamic.

The [webpack module federation](/blog/webpack-module-federation) post resulted in many folks asking me if remote URLs need to be known at build-time? Or is there a way to specify the remotes after building, as runtime configuration somewhere.

Well, we have an easy way to load the component dynamically, here is a suggested method from the docs:

```javascript
function loadComponent(scope, module) {
  return async () => {
    // Initializes the shared scope. Fills it with known provided modules
    // from this build and all remotes
    await __webpack_init_sharing__("default");
    
    const container = window[scope]; // or get the container somewhere else
    
    // Initialize the container, it may provide shared modules
    await container.init(__webpack_share_scopes__.default);
    
    const factory = await window[scope].get(module);
    const Module = factory();
    
    return Module;
  };
}

loadComponent("Comic", "XKCD");
```

## Diving Into the Details

### `__webpack_init_sharing__`

`__webpack_init_sharing__` is defined as:

```javascript
{
  __webpack_init_sharing__: {
    expr: RuntimeGlobals.initializeSharing,
    req: [RuntimeGlobals.initializeSharing],
    type: "function",
    assign: true
  }
}
```

Where `RuntimeGlobals.initializeSharing` is exported as:

```javascript
/**
 * The sharing init sequence function (only runs once per share scope).
 * Has one argument, the name of the share scope.
 * Creates a share scope if not existing
 */
exports.initializeSharing = "__webpack_require__.I";
```

### `__webpack_share_scopes__`

`__webpack_share_scopes__` is defined as:

```javascript
{
  __webpack_share_scopes__: {
    expr: RuntimeGlobals.shareScopeMap,
    req: [RuntimeGlobals.shareScopeMap],
    type: "object",
    assign: false
  },
}
```

`shareScopeMap` would be:

```javascript
/**
 * an object with all share scopes
 */
exports.shareScopeMap = "__webpack_require__.S";
```

`__webpack_share_scopes__.default` would resolve into:

```javascript
{
  "react-dom": {
    "17.0.2": {
      "from": "home-app",
      "eager": true,
      "loaded": 1
    }
  },
  "react": {
    "17.0.2": {
      "from": "home-app",
      "eager": true,
      "loaded": 1
    }
  }
}
```

### `__webpack_require__`

In case you are more curious:

```javascript
Object.keys(__webpack_require__);
// ["m", "c", "n", "d", "f", "e", "u", "g", "o", "l", "r", "nmd", "S", "I", "p"]
```

### `window[scope]`

Getting back to `window[scope]`, in this context `scope` is `Comic`:

```javascript
Object.getOwnPropertyNames(window[scope]);
// ["get", "init"]
```

`init` accepts the shared scope object which is used as a shared scope in the remote container and is filled with the provided modules from a host. It can be leveraged to connect remote containers to a host container dynamically at runtime.

`await window[scope].get(module)` would resolve into a function that on invocation would result in the Module:

```javascript
() => ((__webpack_require__(/*! ./app.jsx */ \"./app.jsx\")))
```

```javascript
{__esModule: true, Symbol(Symbol.toStringTag): "Module"}
```

`Module.default` would be the component that is shared.

## Key Points

The most important point to be mindful is that we need to load the container before attempting to dynamically connect a remote container.

So, basically it boils down to:

1. **Dynamically injecting the remote js file** to the head, so that it loads.
2. **Loading the component** for the given `scope` and `module` as highlighted above.
3. **(Lazy) loading the component.**

P.S: The patterns in the above sandbox is heavily influenced by [dynamic-system-host](https://github.com/module-federation/module-federation-examples/blob/master/dynamic-system-host/app1/src/App.js#L3) sample, also the sandbox example uses `System` custom component and is very verbose for better understanding. In the real world usage you need not be so verbose and might just have a single function that does all the three steps.
