Why do you need to learn about WebPack5 Module Federation? Because the EMP micro front end scheme is based on this revolutionary function, it has a historical breakthrough significance. In this article, you will learn the principles of WebPack5 Module Federation, master the underlying building blocks of EMP micro front-end solutions, and make it easier to use and apply EMP micro front-end solutions.

Webpack5 has recently been released, and one of the most exciting new features is Module Federation (mf), which is the main character of the day. The following three aspects (what, how, where) will explore the mystery of this feature.

I. What is it

In the official webpack document, the real meaning of Module Federation is not given, but the motivation of using this function is given. The original text is as follows

Multiple separate builds should form a single application. These separate builds should not have dependencies between each other, so they can be developed and deployed individually.

This is often known as Micro-Frontends, but is not limited to that.
Copy the code

Translated into Chinese is

Multiple independent builds can form an application. These separate builds do not depend on each other, so they can be developed and deployed separately. This is often called a micro front end, but it's not limited to that.Copy the code

Combined with the above, it is not difficult to see that what MF is really trying to do is to combine multiple non-interdependent, independently deployed applications into one. In general terms, MF provides the ability to remotely load applications on other servers within the current application. To this, the following two concepts can be introduced:

  • Host: An application that references another application
  • Remote: an application used by another application

Given mf’s capabilities, we can fully implement onedecentralizedApplication deployment cluster: Each application is deployed on its own server. Each application can refer to and be referenced by other applications. That is, each application can serve as a host or a remote.

How to use it

Configuration example:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

module.exports = {
  // Other WebPack configurations...
  plugins: [
    new ModuleFederationPlugin({
        name: 'empBase'.library: { type: 'var'.name: 'empBase' },
        filename: 'emp.js'.remotes: {
          app_two: "app_two_remote".app_three: "app_three_remote"
        },
        exposes: {
          './Component1': 'src/components/Component1'.'./Component2': 'src/components/Component2',},shared: ["react"."react-dom"."react-router-dom"]]}})Copy the code

From the above configuration, we have a preliminary understanding of mf. To use MF, we need to configure several important properties:

The field name type meaning
name string The mandatory value, that is, the output module name, is referenced remotely in the path of${name}/${expose}
library object How to declare a global variable with name as umD name
filename string Build the file name of the output
remotes object Mapping of the remote referenced application name and its alias. The name is a key value
exposes object Resource paths and aliases that can be exposed when referenced remotely
shared object Third-party dependencies that can be shared with other applications so that you don’t have to load the same dependencies repeatedly in your code

3. Build the analytical principle

Let’s look at the code after the build:

var moduleMap = { "./components/Comonpnent1": function() { return Promise.all([__webpack_require__.e("webpack_sharing_consume_default_react_react"), __webpack_require__.e("src_components_Close_index_tsx")]).then(function() { return function() { return (__webpack_require__(16499)); }; }); }}; var get = function(module, getScope) { __webpack_require__.R = getScope; getScope = ( __webpack_require__.o(moduleMap, module) ? moduleMap[module]() : Promise.resolve().then(function() { throw new Error('Module "' + module + '" does not exist in container.'); })); __webpack_require__.R = undefined; return getScope; }; var init = function(shareScope, initScope) { if (! __webpack_require__.S) return; var oldScope = __webpack_require__.S["default"]; var name = "default" if(oldScope && oldScope ! == shareScope) throw new Error("Container initialization failed as it has already been initialized with a different share scope"); __webpack_require__.S[name] = shareScope; return __webpack_require__.I(name, initScope); }Copy the code

As you can see, the code consists of three parts:

  • ModuleMap: A collection of modules generated through exposes
  • Get: host This function is used to retrieve components from remote
  • Init: host injects dependencies into remote using this function

Look at the moduleMap, which loads its dependencies through __webpack_require__.e before returning the corresponding component. Let’s see what __webpack_require__.e does:

__webpack_require__.f = {};
// This file contains only the entry chunk.
// The chunk loading function for additional chunks
__webpack_require__.e = function(chunkId) {
    // Get the dependencies in __webpack_require__.f
  return Promise.all(Object.keys(__webpack_require__.f).reduce(function(promises, key) {
    __webpack_require__.f[key](chunkId, promises);
 	returnpromises; } [])); }; __webpack_require__.f.consumes =function(chunkId, promises) {
// Check whether the chunk to be loaded is declared as a shared resource in the configuration item using __webpack_require__.o. If it can be found, use it instead of requesting it
 if(__webpack_require__.o(chunkMapping, chunkId)) {
 	chunkMapping[chunkId].forEach(function(id) {
 		if(__webpack_require__.o(installedModules, id)) return promises.push(installedModules[id]);
 		var onFactory = function(factory) {
 			installedModules[id] = 0;
 			__webpack_modules__[id] = function(module) {
 				delete __webpack_module_cache__[id];
 				module.exports = factory(); }};try {
 			var promise = moduleToHandlerMapping[id]();
 			if(promise.then) {
 				promises.push(installedModules[id] = promise.then(onFactory).catch(onError));
 			} else onFactory(promise);
 		} catch(e) { onError(e); }}); }}Copy the code

After reading through the core code, we can summarize it as follows:

  • First, MF will allow Webpack tofilenameGenerate files as file names
  • Second, a named var is exposed in the file as varnameWhich contains the global variableexposesAs well assharedIs configured in the
  • Finally, ashost, pass firstremotetheinitMethod will itselfsharedwriteremoteMiddle, pass againgetTo obtainremoteIn theexposeAs a component ofremoteThe judgehostIs there a shared dependency available in the. If yes, load ithostIf none is found, the dependency itself is loaded.

Iv. Application Scenarios

Let’s take a look at the application scenarios of MF:

  • Micro front: Through shared and exposes, multiple applications can be brought into the same application for management. The EMP micro front plan independently developed by the Web front end team of YY business center is based on MF capabilities.
  • Reuse resources, reduce compilation volume: Common components used by multiple applications can be deployed separately, and the MF function can be introduced to other projects at Runtime, so that the component code will not be compiled into the project, but also meet the needs of multiple projects at the same time, kill two birds with one bird.

5. The last

At present, only EMP micro front end solution is a set of micro front end solution with mature scaffolding and complete ecology based on Module Federation, and 80% of large projects have been applied in Yy Company. From this paper, we can also recognize that EMP micro front end solution is forward-looking, extensible and has reliable foundation. For EMP micro front-end solutions, there is a complete wiki for you to learn:

  • Basic Knowledge analysis

    What is a micro front end

    Compare a variety of micro front end solutions

    Learn principles of WebPack5 Module Federation

    The design architecture of EMP

  • Quick start

    How does the React project use and access EMP

    How do VUE projects use and access EMP

    Tutorial for using auxiliary plug-ins

  • Advanced tutorial

    How do Vue and React projects call each other remotely

    How to use and access EMP for cocos2D project

    Teach you base station building skills