At some point I’ve realized that my latest project project needed a more flexible and

I’ve already implemented something similar here and I realized the codebase is quite old (still object oriented, not using hooks, etc)

The principles are still the same, the end goal is to fight monolith code bases

How do you fight the monolith? How do you avoid ending up into spaghetti code where every module depends on many modules in an entangled ball of code?

With the plugin-first method. The plugin-first method has 4 simple rules

  1. Every feature is a plugin
  2. All files related to a plugin are packaged in the same folder
  3. The code in plugins is allowed to import from any folders (components, helpers, etc) but not from another plugin
  4. If you remove the plugin, the application must not break

The last rule is the most important and a consequence of the other 3, the code doesn’t have only to be readable but also easy to remove: if it does, it’s easy to replace, refactor and extend.

What’s the different between a component and a plugin? A component is a shared building block of the application, a plugin is an additional feature of the application and, by definition, it can be removed without breaking it.

Let’s make a quick example, let’s try to build a simple app where the menu items of the toolbar are “additional” feature defined using plugins .

How does it work in practice? A plugin definition where React views are associated with arbitrary “regions” of the frontend (and some optional parameters), for example the Dashboard menu item

import { definePlugin } from 'code-plug';
import { DashboardToolbarItem } from './views/dahboard-toolbar-item';

definePlugin('dashboard', ({ register }) => {
  register(
    'toolbar',
    ShareFormMenuItem, // a simple toolbar button
    {
      label: 'Form'
    }
  );
});

And for example another menu item for the user profile page

import { definePlugin } from 'code-plug';
import { UserProfileToolbarItem } from './views/user-profile-toolbar-item';

definePlugin('user-profile', ({ register }) => {
  register(
    'toolbar',
    UserProfileToolbarItem,
    {
      label: 'My profile'
    }
  );
});