Extensions

Start using extensions and runtime plugins

This guide is an entry point for working with extensions

What is an extension

Extension is a reusable, isolated part of your application. It can contain any kind of source logic modifications, source being either a theme or an extension.

Extensions allow to modify the source logic without editing the source code. The idea is to write additional logic - plugins, in order to intercept the initial logic and modify it in runtime.

Build configuration (webpack and babel) can also be modified from extensions.

Initialize a project

Assuming that you have some project you are willing to use mosaic in, install Mosaic in your project by following any setup guide: Next.js, CRA or Webpack. If you want to start a project from scratch, just create it with Next, CRA or manually with Webpack and follow the same steps.

Prepare the source logic

A namespace should be set for the piece of functionality we are willing to make available for plugins. Using the "magic comment" syntax is the most convenient option to do it. Our Babel plugin transforms this syntax into a simple function invocation.

In this guide, you will operate with the code depicted below, located in the corresponding directory.

./src/router.js
/* @namespace Router/getRoutes */ 
function getRoutes(options) { 
    return [ 
        '/home',
        '/my-account'
    ] 
}

const routes = getRoutes(); // routes + additional routes (from plugins)! 
app.setRoutes(routes)

Create a package

Within your project, create a directory for your Mosaic modules (extensions). Conventionally, it is <root>/packages

.
├── 📁 packages/
   └── 📁 @vendor/
       └── 📁 additional-routes/
           └── 📄 package.json
├── 📁 src/
   └── 📄 router.js
└── 📄 package.json

In that directory, create a module with proper package.json additional fields, seen below. It is very important for this module to be recognised as Mosaic module by the plugin system.

./packages/@vendor/additional-routes/package.json
{
    "mosaic": {
        "type": "extension"
    }
}

Install and enable the module

Install it into the package it interacts with. Remember to launch one of the scripts below in order to apply your installation!

./package.json
{
    "scripts": {
        ...
        // TODO provide a linker package
        "postupdate": "...-scripts link",
        "postinstall": "...-scripts link"
    },
    "dependencies": {
        "@vendor/additional-route": "file:relative/path/to/the/module"
    }
}

Remember to enable it afterwards!

package.json
{
    "mosaic": {
        "extensions": {
            "@vendor/additional-route": true
        }
    }
}

Write a plugin

Create a plugin declaration file in the proper directory - src/plugin/

Remember that there is a naming convention for these files - their names should end with .plugin.js

Manipulate the initial logic as you wish! You may have several plugins on a single namespace, if they are compatible with each other all of them will work!

packages/@vendor/additional-route/src/plugin/math.plugin.js
const plugin = (args, callback) => {
    console.log(args);     // [options]
    console.log(callback); // function getRoutes(options) {...}

    const originalRoutes = callback(...args); // ['/home', '/my-account']
    const additionaloutes = ['/cart', '/contact-us'];
    
    return [
        ...originalRoutes, 
        ...additionalRoutes
    ];
};

export default {
    'Router/getRoutes': {
        function: plugin
    }
}

See it in work!

Let's launch the project and see what the initial code will give us. If you followed the guide correctly, you will see that the behavior of getRoutes function has changed and now it acts as follows!

It will also log some stuff into the console (explained above).

const routes = getRoutes(); // ['/home', '/my-account', '/cart', '/contact-us']

Acknowledge other extensions' features

The plugin system, although is one of the main features of Mosaic, is not the only one. To find out more about it, check out the in-depth guide dedicated to it.

Extensions can contain not only runtime logic, but also build configuration modifications.

Last updated