Combine independent SPAs, implemented in different technologies and bundled with arbitrary tools, on Portal pages via drag and drop. Even existing ones can easily be re-used as Microfrontend.
SPAs can even be deployed on separate servers; we call them Remote Portal Apps.
SPAs can be launched multiple times on the same page with different configurations. And they can communicate with each other via front-side message bus.
The Mashroom Portal is fully capable of hybrid rendering and supports SPAs with server-side rendering.
So, the initial page is rendered server-side (including the initial markup of the SPAs if they support SSR) and the succeeding pages are dynamically built on the client-side. Very similar to how Next.js works, but independent from the UI framework.
If the SSR of an SPA takes too long, the Portal automatically switches to the client-side.
Mashroom can also integrated completely server-side rendered Express based Webapps.
In fact, the Mashroom Portal and the Login screen are developed as standalone Express Webapps.
All registered SPAs can also be loaded dynamically via JavaScript API.
This can be used to build dynamic cockpits, which load Apps based on user interaction and capabilities defined in the metadata of registered SPAs. Checkout this demo.
It can also be used to build Composite Apps, which use other, registered SPAs as building blocks.
Mashroom Server ships with a bunch of Kubernetes integration plugins. Most notable it can scan specific namespaces and services for compatible SPAs and register them automatically.
So, new compatible SPAs (Remote Portal Apps) deployed on Kubernetes become automatically available in the Portal after a few seconds.
Check out this Demo Platform.
Mashroom Server comes with a lot of built in security mechanisms and pluggable providers.
It supports ACLs and role based permissions, for example for pages and Apps.
There are existing plugins for OpenID Connect and LDAP/AD.
Mashroom Portal automatically provides API proxies for all Portal Apps (SPAs).
This avoids CORS troubles and protects the actual backends from direct access.
The proxy supports HTTP based APIs (REST, GraphQL) and WebSockets.
The Portal is themable, so, the same SPAs can be used for multiple brands. A prerequisite is that all SPAs use global classes or CSS variables exposed by the themes.
Themes can be built using any existing Express compatible template engine.
Mashroom Server is heavily performance optimised. The server is stateless and can be scaled idefinitely. Page and App configuration and security data is cached in-memory or in Redis. Server-side rendering and full CDN support guarantees a fast page delivery.
For developers Mashroom Server supports hot reload of all plugins.
It also comes with a Sandbox for SPA testing. It allows it to start SPAs with different configuration and to simulate message bus communication and different size factors.
Mashroom Server gathers comprehensive data for monitoring, which can be exposed in Prometheus format or as PM2 custom metrics.
It logs context information (such as User, Browser, which SPA caused an error) with every statement. The log format is fully configurable.
It also comes with a simple Admin UI under /mashroom, which can be used to check server status and the loaded plugins.
Get Started
The easiest way to start is to checkout and run the Mashroom Portal Quickstart, which comes with a few sample plugins:
git clone https://github.com/nonblocking/mashroom-portal-quickstart cd mashroom-portal-quickstart npm run setup npm start
Afterwards open http://localhost:5050 in your browser. Test users are: john/john and admin/admin.
The Admin UI will be available at http://localhost:5050/mashroom
How does it work?
Mashroom Server is basically just a plugin loader that scans npm packages for plugin definitions (in package.json or mashroom.json) and loads them at runtime. Such a plugin could be an Express webapp or a SPA or more generally all kind of code it knows how to load, which is determined by the available plugin loaders. Plugin loaders itself are also just plugins, so it is possible to add any type of custom plugin type.
Additionally, Mashroom Server provides a plugin context on the server-side and client-side with access to (extensible services), security, logging facility and more.
Example: Integrate a SPA
First of all you need a bootstrap that will be called by Mashroom Portal with a host element to integrate into and a context (user, ...):
import React from 'react'; import {render, unmountComponentAtNode} from 'react-dom'; import App from './App'; import type {MashroomPortalAppPluginBootstrapFunction} from '@mashroom/mashroom-portal/type-definitions'; const bootstrap: MashroomPortalAppPluginBootstrapFunction = (portalAppHostElement, portalAppSetup, clientServices) => { const {appConfig, user} = portalAppSetup; const {messageBus} = clientServices; render(<App appConfig={appConfig} messageBus={messageBus}/>, portalAppHostElement); return { willBeRemoved: () => { unmountComponentAtNode(portalAppHostElement); } }; }; (global as any).startReactDemoApp = bootstrap;
And then you need to add some metadata to package.json or in a separate mashroom.json file:
{ "$schema": "https://www.mashroom-server.com/schemas/mashroom-plugins.json", "devModeBuildScript": "build", "plugins": [ { "name": "Mashroom Portal Demo React App", "type": "portal-app2", "clientBootstrap": "startReactDemoApp", "resources": { "js": ["bundle.js"] }, "local": { "resourcesRoot": "./dist", }, "defaultConfig": { "title": "Demo React App", "category": "Demo", "appConfig": { "markdownMessage": "Some message", "pingButtonLabel": "Send Ping" } } } ] }
Why Microfrontends
Microfrontends extend the Microservice idea to frontend development. Analogous to the Microservice approach integration is the hard part and this is where Mashroom Server comes to the rescue. Also analogous to the Microservice approach Microfrontends don‘t always fit but there are many reasons why it could be the right choice.
Possible reasons
- Your frontend is huge and simple not maintainable as a monolith
- You have multiple (probably distributed) teams with different skill sets and want to minimize the coordination overhead
- You are tired of having the Webframework A vs Webframework B debate over and over again and want to make the teams responsible of selecting their own technology stack. Even if they change their opinion over time, the costs of rewriting Microfrontends should be relatively low
- You want to develop some frontend components only once and use everywhere. In different web pages, in Portals, maybe even within fat clients or mobile apps
- Maintenance and further development of your existing Frontend Monolith is terrible slow and expensive: You could add new functionality in form of Microfrontends and gradually decompose the Monolith into smaller components
- You want to extract some components from existing SPA‘s and use elsewhere
- Your teams are used to Java Portlet development, but you‘re looking for an approach that gives you more universally applicable components
- You need to scale rapidly and want to hire new developers: They will be instantly productive by letting them build greenfield SPA‘s with their favorite technology