Module Federation in Mockup#

Module Federation allows sharing of dependencies between bundles. Each bundle includes the whole set of dependencies. However, if multiple bundles have the same dependencies, then they are loaded only once.

For example, if bundle A and B both depend on jQuery and bundle A has already loaded it, then bundle B can just reuse the already loaded jQuery file. But if only bundle B is loaded, it uses its own bundled version of the jQuery library.

There is a host bundle, as in the fictional example above, our bundle A. In Plone the host bundle is the main Mockup bundle. Add-ons can add bundles called "remotes" which are initialized for Module Federation by the host bundle.

See also

Webpack's documentation on Module Federation.

Use Module Federation#

If you created an add-on with a Mockup pattern, and you want to include the respective JavaScript code in your theme code, then the following instructions are for you.

Starting with the webpack configuration that you get when creating a Barceloneta theme package via plonecli, add the following.

Create a new entry point index.js which only imports the normal entry point.

import("./patterns");

Next add the Module Federation plugin in webpack.config.js. There is a configuration factory mf_config which you can use for that. Add the following line near the top of the file.

const mf_config = require("@patternslib/dev/webpack/webpack.mf");

Import all the dependencies you want to share. Potentially these are the ones from Patternslib, Mockup, and your own dependencies. You can add the Patternslib and Mockup dependencies, even if you are not using them.

const package_json = require("./package.json");
const package_json_mockup = require("@plone/mockup/package.json");
const package_json_patternslib = require("@patternslib/patternslib/package.json");

Then find the following line.

config = patternslib_config(env, argv, config, ["@plone/mockup"]);

Below this line add the following.

config.plugins.push(
    mf_config({
        name: "myaddon",
        filename: "myaddon-remote.min.js",
        remote_entry: config.entry["myaddon.min"],
        dependencies: {
            ...package_json_patternslib.dependencies,
            ...package_json_mockup.dependencies,
            ...package_json.dependencies,
        },
    })
);

Replace the name myaddon with your add-on bundle's unique name. Replace the file name myaddon-remote.min.js with the file name you want to use for your remote bundle. Finally replace myaddon.min with the corresponding key in config.entry that points to your index.js.

For a full and basic example, see the Patterns generator pat-PATTERN-TEMPLATE or any other Pattern add-on in the patternslib GitHub organization. For a complex example with Mockup integration see plone.app.mosaic and Mockup itself.

Special case: global modules jQuery and Bootstrap#

To preserve compatibility with older add-ons and JavaScript implementations, the modules jQuery and Bootstrap are stored in the global window namespace. Constructs like the following still work:

(function($) {
    // JS code which uses $
})(jQuery);