<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Mashroom Server - Medium]]></title>
        <description><![CDATA[The official Medium publication for the Mashroom Server open source project, an Integration Platform for Microfrontends. - Medium]]></description>
        <link>https://medium.com/mashroom-server?source=rss----504447fa34a5---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Mashroom Server - Medium</title>
            <link>https://medium.com/mashroom-server?source=rss----504447fa34a5---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 15 May 2026 15:52:31 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/mashroom-server" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[OpenMicrofrontends Specification Released]]></title>
            <link>https://medium.com/mashroom-server/openmicrofrontends-specification-released-cb1b3ce084a0?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/cb1b3ce084a0</guid>
            <category><![CDATA[micro-frontends]]></category>
            <dc:creator><![CDATA[Jürgen Kofler]]></dc:creator>
            <pubDate>Mon, 10 Nov 2025 13:25:27 GMT</pubDate>
            <atom:updated>2025-11-10T13:52:08.885Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kUbySpOhvO3ZeG8aa_Sl0Q.png" /></figure><p>The <a href="https://open-microfrontends.org/"><em>OpenMicrofrontends</em></a> project aims to provide a formal specification for Microfrontends provided by a server. Think of it as <a href="https://www.openapis.org/">OpenAPI</a> for <em>Microfrontends</em>.</p><p>The project just released version 1.0.0 of the specification and a generator to create type-safe integration code on the Microfrontend- and Host Application-side.</p><p>Example Description:</p><pre>$schema: https://open-microfrontends.org/schemas/1-0-0.json<br>openMicrofrontends: 1.0.0<br>servers:<br>- url: &#39;http://localhost:7890&#39;<br>  description: Local Test Server<br>microfrontends:<br>- name: My First Microfrontend<br>  assets:<br>    basePath: /public<br>    js:<br>      moduleSystem: ESM<br>      initial:<br>        - Microfrontend.js<br>  rendererFunctionName: startMyFirstMicrofrontend<br>  config:<br>    schema:<br>      type: object<br>      properties:<br>        welcomeMessage:<br>          type: string<br>      required: [&quot;welcomeMessage&quot;]<br>    default:<br>      welcomeMessage: Hello World!<br>  messages:<br>    ping:<br>      publish: true<br>      subscribe: true<br>      schema:<br>        type: object<br>        properties:<br>          ping:<br>            const: true<br>        required: [&quot;ping&quot;]</pre><p>Find out more on the <a href="https://open-microfrontends.org/">project homepage</a>.</p><p>The upcoming <em>Mashroom Server</em> v3 will include first class support for <em>OpenMicrofrontends</em> compliant Microfrontends!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cb1b3ce084a0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/openmicrofrontends-specification-released-cb1b3ce084a0">OpenMicrofrontends Specification Released</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mashroom Server 2.9 released]]></title>
            <link>https://medium.com/mashroom-server/mashroom-server-2-9-released-d73bd8152cf8?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/d73bd8152cf8</guid>
            <category><![CDATA[micro-frontends]]></category>
            <category><![CDATA[mashroom]]></category>
            <dc:creator><![CDATA[Jürgen Kofler]]></dc:creator>
            <pubDate>Mon, 23 Jun 2025 14:17:23 GMT</pubDate>
            <atom:updated>2025-06-23T14:17:23.034Z</atom:updated>
            <content:encoded><![CDATA[<p>Version 2.9 of the Microfrontend Integration Platform <a href="https://www.mashroom-server.com/">Mashroom Server</a> has been released today.</p><p>This is mainly a maintenance release with a lot of 3rd party libraries upgraded and some code improved.</p><h3>Notable changes</h3><ul><li>Support for <em>Node.js 24</em> added</li><li>With <em>Node.js 24</em> all <em>Mashroom</em> config files can now be written in TypeScript (because the types are automatically stripped, check <a href="https://nodejs.org/docs/latest-v24.x/api/typescript.html#typescript-features">https://nodejs.org/docs/latest-v24.x/api/typescript.html#typescript-features</a> for limitations)<br>An example <em>mashroom.ts</em> main config file could look like this:</li></ul><pre>import type {MashroomServerConfig} from &#39;@mashroom/mashroom-json-schemas/type-definitions&#39;;<br><br>const serverConfig: MashroomServerConfig = {<br>    name: &#39;My Server&#39;,<br>    port: 5050,<br><br>    // ...<br>};<br><br>export default serverConfig;</pre><ul><li>Dropped support for <em>Node.js 18</em></li><li>Made sure the <em>redirectUrl</em> parameter of the Portal login and logout route cannot be abused to redirect to arbitrary hosts (and to obscure the actual referrer)</li></ul><p>As usual, you can check the <a href="https://github.com/nonblocking/mashroom/blob/master/CHANGELOG.md">CHANGELOG</a> for a list of all changes.</p><p>To try out the new <em>Mashroom Server </em>version: Clone the <a href="https://github.com/nonblocking/mashroom-portal-quickstart">Mashroom Portal Quickstart</a> repository and follow instructions in the README!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d73bd8152cf8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/mashroom-server-2-9-released-d73bd8152cf8">Mashroom Server 2.9 released</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mashroom Server 2.8 released]]></title>
            <link>https://medium.com/mashroom-server/mashroom-server-2-8-released-63b619ecc120?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/63b619ecc120</guid>
            <category><![CDATA[micro-frontends]]></category>
            <category><![CDATA[mashroom-server]]></category>
            <dc:creator><![CDATA[Jürgen Kofler]]></dc:creator>
            <pubDate>Thu, 03 Apr 2025 11:56:53 GMT</pubDate>
            <atom:updated>2025-04-03T11:56:52.905Z</atom:updated>
            <content:encoded><![CDATA[<p>Version 2.8 of the Microfrontend Integration Platform <a href="https://www.mashroom-server.com/">Mashroom Server</a> has been released today.</p><h3>New Features</h3><h4>Theme Overhaul</h4><p>We have improved the style of the default Theme and introduced a <em>Dark Mode</em>. The theme also exposes now a lot of CSS variables that can be used in Apps to align the style.</p><figure><img alt="Dark Mode" src="https://cdn-images-1.medium.com/max/1024/1*K9HG9XQdaNUxnq52m6FLOg.png" /></figure><p>Additionally, we added the possibility to pass a override CSS file that can be used to customize the theme:</p><pre>&quot;Mashroom Portal Default Theme&quot;: {<br>    &quot;darkMode&quot;: &quot;auto&quot;,<br>    &quot;styleFile&quot;: &quot;./defaultThemeOverrides.css&quot;<br>},</pre><pre>:root {<br>  --mashroom-portal-color-primary: green;<br>}</pre><h4>Improved Sandbox App</h4><p>The Sandbox App shows now a permanent link for the current session that can easily be shared with other people.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/967/1*2AdNzXRJCrkpB3JkEzK7lQ.png" /></figure><p>Furthermore it shows now unavailable (non permitted) Apps in the selection, just to make clear what the problem is in case a user expects a specific App.</p><h4>New App Gallery App</h4><p>We have introduced a new App Gallery that shows all registered Apps with some details and screenshots.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IUMwFhCXvY7gdgCF9fu73A.png" /></figure><h4>Simplified Server-Side Rendering</h4><p>The client-side bootstrap of an App receives now a flag that indicates if the App has been rendered on the server-side. This can be used to decide if you need to hydrate or just client-side render.</p><pre>if (portalAppSetup.serverSideRendered) {<br>   root = hydrateRoot(portalAppHostElement, (<br>       &lt;App /&gt;<br>   ));<br>} else {<br>   // Default: render on client side<br>   root = createRoot(portalAppHostElement);<br>   root.render((<br>       &lt;App /&gt;<br>   ));<br>}</pre><p>The server-side bootstrap can now return some script that needs to be injected into the header. This is useful if you want to pass some state to the client-side. Or if the UI framework also creates some script during server-side rendering (like Svelte).</p><pre>const ssrBootstrap: MashroomPortalAppPluginSSRBootstrapFunction = async (portalAppSetup) =&gt; {<br>    const {appId} = portalAppSetup;<br>    <br>    // TODO: Load data and render<br>    let someLoadedData = {};<br>    let html = &#39;&#39;;<br>    <br>    return {<br>      html,<br>      injectHeadScript: `<br>        window[&#39;__my_data_${appId}&#39;] = ${JSON.stringify(someLoadedData)};<br>      `<br>     };<br>};</pre><h3>Bugfixes</h3><ul><li>Fixed handling of multiple Modal Apps at the same time: Only the latest is shown at a time and on close the next one (the one “below”) will get visible.</li><li>Fixed the errors that were occurring in some plugins when <em>mashroom-monitoring-metrics-collector</em> was not present</li></ul><p>Checkout the <a href="https://github.com/nonblocking/mashroom/blob/master/CHANGELOG.md">CHANGELOG</a> for a list of all changes.</p><p>To try out the new <em>Mashroom Server </em>version: Clone the <a href="https://github.com/nonblocking/mashroom-portal-quickstart">Mashroom Portal Quickstart</a> repository and follow instructions in the README!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=63b619ecc120" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/mashroom-server-2-8-released-63b619ecc120">Mashroom Server 2.8 released</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mashroom Server 2.7 released]]></title>
            <link>https://medium.com/mashroom-server/mashroom-server-2-7-released-bb09037f0ac2?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/bb09037f0ac2</guid>
            <category><![CDATA[micro-frontends]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[mashroom]]></category>
            <dc:creator><![CDATA[Jürgen Kofler]]></dc:creator>
            <pubDate>Mon, 08 Jul 2024 13:35:48 GMT</pubDate>
            <atom:updated>2024-07-08T13:35:47.905Z</atom:updated>
            <content:encoded><![CDATA[<p>Version 2.7 of the Microfrontend Integration Platform <a href="https://www.mashroom-server.com/">Mashroom Server</a> has been released today.</p><h3>Notable features</h3><h4>New authentication expiration strategies</h4><p>It is now possible to configure what should happen if the authentication expires in the Portal. Until now the strategy was to just reload the current page, now you can choose between multiple strategies:</p><ul><li><em>stayOnPage</em></li><li>reload (Default, same behaviour as before)</li><li><em>redirect</em> (redirect to another page)</li><li><em>displayDomElement</em> (set <em>display: block</em> on the DOM element with given ID)</li></ul><p>Can be configured like this:</p><pre>&quot;Mashroom Portal WebApp&quot;: {<br>  &quot;authenticationExpiration&quot;: {<br>    &quot;warnBeforeExpirationSec&quot;: 30,<br>    &quot;onExpiration&quot;: {<br>      &quot;strategy&quot;: &quot;stayOnPage&quot;<br>    }<br>  }<br>}</pre><p>Please note, the <em>warnBeforeAuthenticationExpiresSec</em> and <em>autoExtendAuthentication</em> properties have been removed from the config schema but are still recognised and will be merged into the new config object.</p><p>A configuration like the one above would let the Portal stay on the page after session expiration and just show a message:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*S2Awn7SzKmhXf-cohK7dxg.png" /></figure><h4>Portal Proxy can add x-forwarded-* headers</h4><p>If enabled, the Portal Proxy automatically adds the following headers (and merges them with incoming headers):</p><ul><li>x-forwarded-for</li><li>x-forwarded-host</li><li>x-forwarded-proto</li></ul><p>Can be enabled like this:</p><pre>&quot;Mashroom Http Proxy Services&quot;: {<br>    &quot;createForwardedForHeaders&quot;: true<br>}</pre><h3>Bugfixes</h3><ul><li>VHost Mapper Plugin: Replaces the absolute location header URLs with the relative path if the host matches the frontend host. This saves an unnecessary round trip if the protocol does not match the frontend protocol.</li><li>Session Plugin: Use session cookies by default, otherwise the session could expire on the “client-side” which is kinda weird.</li></ul><p>Checkout the <a href="https://github.com/nonblocking/mashroom/blob/master/CHANGELOG.md">CHANGELOG</a> for a list of all changes.</p><p>To try out the new <em>Mashroom Server </em>version: Clone the <a href="https://github.com/nonblocking/mashroom-portal-quickstart">Mashroom Portal Quickstart</a> repository and follow instructions in the README!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bb09037f0ac2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/mashroom-server-2-7-released-bb09037f0ac2">Mashroom Server 2.7 released</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mashroom Server 2.6 released]]></title>
            <link>https://medium.com/mashroom-server/mashroom-server-2-6-released-e81af26ef71a?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/e81af26ef71a</guid>
            <category><![CDATA[micro-frontends]]></category>
            <category><![CDATA[mashroom]]></category>
            <dc:creator><![CDATA[Jürgen Kofler]]></dc:creator>
            <pubDate>Sat, 06 Apr 2024 09:37:21 GMT</pubDate>
            <atom:updated>2024-04-06T09:37:21.466Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HaUpk2n5FIWvSwh_" /><figcaption>Photo by <a href="https://unsplash.com/@jjying?utm_source=medium&amp;utm_medium=referral">JJ Ying</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Version 2.6 of the Microfrontend Integration Platform <a href="https://www.mashroom-server.com/">Mashroom Server</a> has been released today.</p><p>This is manly maintenance release with no breaking changes. We have updated all 3rd party libraries and introduced some measures to improve supply chain safety.</p><h3>Notable changes and fixes</h3><ul><li>HTTP Proxy: We have added support for transforming the request/response body. Proxy interceptors can now return <em>streamTransformers</em> (implementing <a href="https://nodejs.org/api/stream.html#class-streamtransform">stream.Transform</a>) and can be used to compress/encrypt the communication to backend servers. <br>Compression example:</li></ul><pre>import zlib from &#39;node:zlib&#39;;<br><br>export default class MyInterceptor implements MashroomHttpProxyInterceptor {<br>   async interceptRequest(targetUri) {<br>       if (targetUri.startsWith(&#39;https://my-backend-server.com&#39;)) {<br>           return {<br>               addHeaders: {<br>                   &#39;content-encoding&#39;: &#39;gzip&#39;,<br>               },<br>               streamTransformers: [<br>                   zlib.createGzip(),<br>               ],<br>           };<br>       }<br>   }<br>   async interceptResponse(targetUri, existingHeaders) {<br>       if (targetUri.startsWith(&#39;https://my-backend-server.com&#39;) <br>&amp;&amp; existingHeaders[&#39;content-encoding&#39;] === &#39;gzip&#39;) {<br>           return {<br>               removeHeaders: [<br>                   &#39;content-encoding&#39;,<br>               ],<br>               streamTransformers: [<br>                   zlib.createGunzip(),<br>               ],<br>           };<br>       }<br>   }<br>}</pre><ul><li>Fixed the problem that remote subscriptions can receive the same message multiple times if subscription patterns overlap.<br>See issue <a href="https://github.com/nonblocking/mashroom/issues/115">#115</a></li><li>Mashroom modules are now built in a safe environment with lifecycle scripts of 3rd party libraries disabled. Additionally provenance attestations are generated and can be checked via <em>npm audit signatures</em> and on <a href="https://www.npmjs.com/">npmjs.com</a>:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/781/1*pRA7wsh7BwkkFs8DNLX2tw.png" /></figure><p>To try out the new <em>Mashroom Server </em>version: Clone the <a href="https://github.com/nonblocking/mashroom-portal-quickstart">Mashroom Portal Quickstart</a> repository and follow instructions in the README!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e81af26ef71a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/mashroom-server-2-6-released-e81af26ef71a">Mashroom Server 2.6 released</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mashroom Server 2.5 released]]></title>
            <link>https://medium.com/mashroom-server/mashroom-server-2-5-released-39c2d5026ccd?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/39c2d5026ccd</guid>
            <category><![CDATA[micro-frontends]]></category>
            <category><![CDATA[mashroom]]></category>
            <dc:creator><![CDATA[Jürgen Kofler]]></dc:creator>
            <pubDate>Wed, 10 Jan 2024 10:32:45 GMT</pubDate>
            <atom:updated>2024-01-10T10:32:45.081Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*P9YGxd_WFX5tjlqJ" /><figcaption>Photo by <a href="https://unsplash.com/@karlsolano?utm_source=medium&amp;utm_medium=referral">Karl Solano</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Version 2.5 of the Microfrontend Integration Platform <a href="https://www.mashroom-server.com/">Mashroom Server</a> has been released today.</p><p>With this release we focused on housekeeping, like cleaning up the code base and upgrading or removing/replacing deprecated and unmaintained libraries.</p><h3>Notable changes and fixes</h3><ul><li>We discovered and fixed a potential memory leak that occurred when Remote App servers didn’t answer requests (or the network just dropped the connection). Now all requests have a proper timeout set and sockets will be closed and removed.</li><li>The File Store doesn’t check for external changes with every access anymore, but waits the configured <em>checkExternalChangePeriodMs</em> (default 100ms). This reduces I/O and should slightly improve the performance.</li><li>The default HTTP proxy (for API calls) has been rewritten because <em>node-http-proxy</em> is no longer maintained. The new implementation uses the Stream API introduced with Node.j 10, which has an improved error handling and resource cleanup.</li><li>Mashroom uses now the <a href="https://opentelemetry.io/docs/specs/otel/metrics">OpenTelemetry</a> SDK for metrics. To add custom metrics you can still use the <em>MashroomMonitoringMetricsCollectorService</em> or directly the OpenTelemetry API, like so:</li></ul><pre>const collectorService: MashroomMonitoringMetricsCollectorService = req.pluginContext.services.metrics.service;<br><br>const meterProvider = collectorService.getOpenTelemetryMeterProvider();<br>const meter = meterProvider.getMeter(&#39;my_meter&#39;);<br>const counter = meter.createCounter(&#39;http_request_counter&#39;, {<br>    description: &#39;HTTP Request Counter&#39;,<br>});<br><br>counter.add(1);</pre><h3>Breaking Changes</h3><ul><li>The most breaking changes are related to metrics:<br>- The metrics collector service API (<em>MashroomMonitoringMetricsCollectorService) </em>has been changed<br>- Some metrics have been renamed <br>- The way how you can fetch metrics from a specific PM2 worker via inter-process communication has changed</li><li>The type of <em>request.session</em> is no longer <em>any</em>, so if you want to add custom properties to the <em>session</em> you have to extend the type like this:</li></ul><pre>declare module &#39;express-session&#39; {<br>  interface SessionData {<br>    foo?: string;<br>  }<br>}</pre><ul><li><strong>Support for Node.js 16 has been dropped</strong></li><li>For more details, checkout the <a href="https://github.com/nonblocking/mashroom/blob/master/CHANGELOG.md">CHANGELOG</a></li></ul><p>To try out the new <em>Mashroom Server </em>version: Clone the <a href="https://github.com/nonblocking/mashroom-portal-quickstart">Mashroom Portal Quickstart</a> repository and follow instructions in the README!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=39c2d5026ccd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/mashroom-server-2-5-released-39c2d5026ccd">Mashroom Server 2.5 released</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kubernetes Microfrontend Platform Demo updated]]></title>
            <link>https://medium.com/mashroom-server/kubernetes-microfrontend-platform-demo-updated-e628b4eddfa9?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/e628b4eddfa9</guid>
            <category><![CDATA[mashroom]]></category>
            <category><![CDATA[micro-front-end]]></category>
            <dc:creator><![CDATA[Jürgen Kofler]]></dc:creator>
            <pubDate>Thu, 15 Jun 2023 15:13:57 GMT</pubDate>
            <atom:updated>2023-06-15T15:13:57.521Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/911/1*FmseBVOd7SHBJnEf2iTgfg.png" /></figure><p>We have overhauled our <a href="https://github.com/nonblocking/microfrontend-platform-kubernetes">Microfrontend Platform Demo</a> and fixed a few problems.</p><ul><li>We tried to simplify and slim down the <a href="https://k3d.io/">k3d</a> based demo; the script sets now up the whole platform in (under 5min on a M1 Pro)</li><li>Works now on Apple Silicon chips (ARM64)</li><li>Common services and Microfrontends are now in different namespaces and the Portal is set up to search Microfrontends in namespaces with specific labels</li><li>The Microfrontend deploy scripts create now a new version with every build which automatically busts the browser cache</li><li>New Microfrontend versions are now registered faster (&lt; 60sec)</li><li>All components updated to the latest version</li></ul><p>Check it out: <a href="https://github.com/nonblocking/microfrontend-platform-kubernetes">https://github.com/nonblocking/microfrontend-platform-kubernetes</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e628b4eddfa9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/kubernetes-microfrontend-platform-demo-updated-e628b4eddfa9">Kubernetes Microfrontend Platform Demo updated</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mashroom Server 2.4 released]]></title>
            <link>https://medium.com/mashroom-server/mashroom-server-2-4-released-3fdb7af4e11a?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/3fdb7af4e11a</guid>
            <category><![CDATA[micro-frontends]]></category>
            <category><![CDATA[mashroom]]></category>
            <dc:creator><![CDATA[Jürgen Kofler]]></dc:creator>
            <pubDate>Fri, 09 Jun 2023 07:14:04 GMT</pubDate>
            <atom:updated>2023-06-09T07:24:42.428Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*0jgkPgtuUDLeuW1PBJCESw.png" /><figcaption>Improved HTTP Proxy metrics</figcaption></figure><p>Version 2.4 of the Microfrontend Integration Platform <a href="https://www.mashroom-server.com/">Mashroom Server</a> has been released today.</p><h3>Improved HTTP/WebSocket Proxy</h3><p>The <em>mashroom-http-proxy</em> plugin (amongst others used to forward <em>Microfrontend</em> requests to the backend) allows now a more fine grained pool configuration.</p><p>For HTTP/S request you can now not only limit the number of sockets per target host, but also the total sockets and the number of waiting requests per host. The latter can limit the damage by unresponsive backends, because it prevents reverse proxy connection pools from filling up.</p><p>For WebSocket connections you can now limit the connections per host and the total connections.</p><p>Example configuration:</p><pre>{<br>    &quot;plugins&quot;: {<br>        &quot;Mashroom Http Proxy Services&quot;: {<br>            &quot;poolMaxTotalSockets&quot;: 100,<br>            &quot;poolMaxSocketsPerHost&quot;: 10,<br>            &quot;poolMaxWaitingRequestsPerHost&quot;: 100,<br>            &quot;socketTimeoutMs&quot;: 60000,<br>            &quot;wsMaxConnectionsTotal&quot;: 2000,<br>            &quot;wsMaxConnectionsPerHost&quot;: 500<br>        }<br>    }<br>}</pre><p>Additionally, the HTTP Proxy Plugin exposes new metrics like the number of sockets and waiting requests per host (see screenshot at the top).</p><h3>Messaging via Redis Pub/Sub</h3><p><em>Redis</em> can now be used as external messaging broker (besides AMQP and MQTT). An external messaging broker is necessary if you want to send messages to/from 3rd party systems in your <em>Microfrontend,</em> or to other browser instances of the same or other users.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*Wwdju3z75kOTXDXTab18UA.gif" /></figure><h3>Other notable changes and fixes</h3><ul><li>Support for Node.js 20, support for 14 has been dropped</li><li>There are a number of small breaking changes, checkout the <a href="https://github.com/nonblocking/mashroom/blob/master/CHANGELOG.md">CHANGELOG</a></li></ul><p>To try out the new <em>Mashroom Server </em>version: Clone the <a href="https://github.com/nonblocking/mashroom-portal-quickstart">Mashroom Portal Quickstart</a> repository and follow instructions in the README!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3fdb7af4e11a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/mashroom-server-2-4-released-3fdb7af4e11a">Mashroom Server 2.4 released</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Webpack Module Federation in Mashroom Portal]]></title>
            <link>https://medium.com/mashroom-server/using-webpack-module-federation-in-mashroom-portal-2e3b8e12d5a8?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/2e3b8e12d5a8</guid>
            <category><![CDATA[micro-frontends]]></category>
            <category><![CDATA[mashroom]]></category>
            <category><![CDATA[module-federation]]></category>
            <dc:creator><![CDATA[Jürgen Kofler]]></dc:creator>
            <pubDate>Mon, 13 Mar 2023 07:31:31 GMT</pubDate>
            <atom:updated>2023-03-17T15:33:17.021Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/930/1*y9gFr0C0AbJb_ia-h71ggg.jpeg" /></figure><p><em>Mashroom Portal</em> treats Microfrontends as blackbox and doesn’t care which UI Framework and which bundler is used. But if you have a lot of Microservices with the same Vendor libraries built with <a href="https://webpack.js.org/">webpack</a> it makes sense to enable <a href="https://webpack.js.org/concepts/module-federation/">Module Federation</a>, because it can lead to significant reduced bundle sizes and faster loading.</p><p>Note: I already covered generic (bundler independent) ways to reduce the bundle sizes in this <a href="https://medium.com/mashroom-server/ways-to-minimize-microfrontend-bundle-sizes-876b2bbc115b">article</a>.</p><h3>Differences to the typical Microfrontend approach with Module Federation</h3><p>If you use Module Federation in conjunction with <em>Mashroom Portal</em> there are a few main differences compared to a typical setup:</p><ol><li>There is no Host App. In <em>Mashroom Server</em> there is no Host/Shell App that takes over the whole browser and is responsible for loading <em>remote</em> components or Apps. As mentioned before, <em>Mashroom</em> treats all Microservices as blackboxes which shouldn’t expose any global variables except a <em>bootstrap</em>. So, Modules Federation cannot share anything out-of-the-box because global webpack variables such as <em>__webpack_share_scopes__</em> are missing.</li><li>Only <em>Mashroom Portal</em> knows where the <em>remotes </em>are. Only <em>Mashroom Portal</em> knows which Apps exist and how to load them. So, that cannot be done by Module Federation.</li><li>The remote containers need to be initialised manually. Because auf 2., Module Federation cannot not automatically initialise the containers and enable sharing, so, the <a href="https://webpack.js.org/concepts/module-federation/#dynamic-remote-containers">Dynamic Remote Containers</a> approach needs to be used.</li></ol><h3>Working Solution</h3><h4>Starting Situation</h4><p>Lets say we have a bunch of simple React Apps with the following setup:</p><p>Bootstrap:</p><pre>// index.tsx<br>const bootstrap: MashroomPortalAppPluginBootstrapFunction = <br>  (portalAppHostElement, portalAppSetup, clientServices) =&gt; {<br>    const {appConfig, user} = portalAppSetup;<br>    const {messageBus} = clientServices;<br><br>    const root = createRoot(portalAppHostElement);<br>    root.render(&lt;App appConfig={appConfig} messageBus={messageBus}/&gt;);<br><br>    return {<br>        willBeRemoved: () =&gt; {<br>            root.unmount();<br>        }<br>    };<br>};<br><br>window.startMyReactApp = bootstrap;</pre><p>Mashroom Plugin Config:</p><pre>&quot;mashroom&quot;: {<br>    &quot;devModeBuildScript&quot;: &quot;build&quot;,<br>    &quot;plugins&quot;: [<br>        {<br>            &quot;name&quot;: &quot;My React App&quot;,<br>            &quot;type&quot;: &quot;portal-app2&quot;,<br>            &quot;clientBootstrap&quot;: &quot;startMyReactApp&quot;,<br>            &quot;resources&quot;: {<br>                &quot;js&quot;: [<br>                    &quot;index.js&quot;<br>                ]<br>            },<br>            &quot;local&quot;: {<br>                &quot;resourcesRoot&quot;: &quot;./dist&quot;<br>            }<br>        }<br>    ]<br>}</pre><p>Webpack Config:</p><pre>// webpack.config.js<br>module.exports = {<br>    entry: __dirname + &#39;/src/index.tsx&#39;,<br>    output: {<br>        path: __dirname + &#39;/dist&#39;,<br>        filename: &#39;index.js&#39;,<br>    },<br>};</pre><h4>Switch to async loading</h4><p>To make sharing work we first of all have to load the actual App asynchronously via <em>import().</em> So, copy <em>index.tsx</em> to <em>bootstrap.tsx</em> and export it as default:</p><pre>// bootstrap.tsx<br>const bootstrap: MashroomPortalAppPluginBootstrapFunction = <br>  (portalAppHostElement, portalAppSetup, clientServices) =&gt; {<br>    const {appConfig, user} = portalAppSetup;<br>    const {messageBus} = clientServices;<br><br>    const root = createRoot(portalAppHostElement);<br>    root.render(&lt;App appConfig={appConfig} messageBus={messageBus}/&gt;);<br><br>    return {<br>        willBeRemoved: () =&gt; {<br>            root.unmount();<br>        }<br>    };<br>};<br><br>export default bootstrap;</pre><p>And (for the moment) create a new <em>index.tsx</em> with that just imports the bootstrap:</p><pre>// index.tsx<br>const bootstrap: MashroomPortalAppPluginBootstrapFunction = <br>  (portalAppHostElement, portalAppSetup, clientServices) =&gt; {<br>    const bootstrap = await import(&#39;./bootstrap&#39;);<br>    return bootstrap.default(portalAppHostElement, portalAppSetup, clientServices);<br>};<br><br>window.startMyReactApp = bootstrap;</pre><p>Also, make sure you have a proper code splitting configuration, which means the chunks names contain the content hash to prevent caching problems:</p><pre>output: {<br>    path: __dirname + &#39;/dist&#39;,<br>    filename: &#39;index.js&#39;,<br>    chunkFilename: &#39;chunk.[contenthash].js&#39;, // Change<br>},</pre><h4>Create a Module Federation container for sharing</h4><p>Next step is to configure the ModuleFederationPlugin: We create a container with a unique name and export is as <em>app.js</em>. But most importantly, we shared the vendor libraries:</p><pre>// webpack.config.js<br>const { ModuleFederationPlugin } = require(&#39;webpack&#39;).container;<br>const { dependencies } = require(&#39;./package.json&#39;);<br><br>module.exports = {<br>  // ...<br>  plugins: [<br>      new ModuleFederationPlugin({<br>          name: &#39;__my_react_app__&#39;,<br>          filename: &#39;app.js&#39;,<br>          exposes: {<br>              bootstrap: __dirname + &#39;/src/bootstrap.tsx&#39;,<br>          },<br>          shared: {<br>              react: {<br>                  singleton: true,<br>                  requiredVersion: dependencies.react,<br>              },<br>              &#39;react-dom&#39;: {<br>                  singleton: true,<br>                  requiredVersion: dependencies[&#39;react-dom&#39;],<br>              },<br>              // Other libraries<br>          },<br>      })<br>  ]<br>}</pre><p>Please note, we use the <em>singleton</em> flag here for <em>react</em> and <em>react-dom</em> because those libraries use a global state and shared UI components wouldn’t work otherwise. This is typically not recommended, because <em>singleton</em> means to share a library even if the version does not match.</p><p>We also have to add the created <em>app.js</em> to the resources to load by <em>Mashroom Portal</em>:</p><pre>&quot;resources&quot;: {<br>    &quot;js&quot;: [<br>        &quot;app.js&quot;,<br>        &quot;index.js&quot;<br>    ]<br>},</pre><h4>Load the App with enabled sharing</h4><p>The last step is to fix the App bootstrapping so the Vendor libraries are actually shared among different Apps on a Portal page.</p><p>What we do is we follow the guideline for <a href="https://webpack.js.org/concepts/module-federation/#dynamic-remote-containers">Dynamic Remote Containers</a> but additionally manually expose the <em>__webpack_share_scopes__</em> variable to the <em>window</em> object. So, the resulting <em>index.tsx</em> would look like this:</p><pre>// index.tsx<br>const bootstrap: MashroomPortalAppPluginBootstrapFunction = async (<br>    portalAppHostElement,<br>    portalAppSetup,<br>    clientServices,<br>) =&gt; {<br>    const sharedScopes = window.MASHROOM_WEBPACK_SHARED_SCOPE || __webpack_share_scopes__;<br>    window.MASHROOM_WEBPACK_SHARED_SCOPE = sharedScopes;<br>    await __webpack_init_sharing__(&#39;default&#39;);<br>    await __my_react_app__.init(sharedScopes.default);<br>    const bootstrapModule = await __my_react_app__.get(&#39;bootstrap&#39;);<br>    const bootstrap = bootstrapModule();<br>    return bootstrap.default(portalAppHostElement, portalAppSetup, clientServices);<br>};<br><br>window.startMyReactApp = bootstrap;</pre><p>For TypeScript you also have to add these declarations:</p><pre>declare const __my_react_app__: any; // Module Federation container<br>declare const __webpack_share_scopes__: any;<br>declare const __webpack_init_sharing__: any;<br>declare global {<br>    interface Window {<br>        MASHROOM_WEBPACK_SHARED_SCOPE: any;<br>        startMyReactApp: MashroomPortalAppPluginBootstrapFunction;<br>    }<br>}</pre><h4>Optional: Unload all chunks properly</h4><p>It you need to unload Apps dynamically or want to use hot reload it is necessary to manually remove all chunks by deleting the global variable <em>webpackChunk_&lt;npm_module_name&gt;</em> (e.g. for my-react-app this would be <em>webpackChunk_my_react_app</em>):</p><pre>// bootstrap.tsx<br>const bootstrap: MashroomPortalAppPluginBootstrapFunction = <br>  (portalAppHostElement, portalAppSetup, clientServices) =&gt; {<br>    // ...<br>    return {<br>        willBeRemoved: () =&gt; {<br>            delete window.webpackChunk_my_react_app;  // Add this<br>            root.unmount();<br>        }<br>    };<br>};<br><br>export default bootstrap;</pre><p>And thats it, if you apply this change to all of your Microfrontends they will automatically share the Vendor libraries (if the versions match or <em>singleton</em> is set).</p><p>I’ve adapted <em>mashroom-portal-demo-react-app</em> and <em>mashroom-portal-demo-react-app2</em> in the <a href="https://github.com/nonblocking/mashroom">Mashroom git repo</a> and it really makes a difference:</p><p>Before:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MYVc26D3gWgHE7WY8t239Q.png" /></figure><p>After:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x9UX0EcTMk8lR1pBycAKvg.png" /></figure><p>So, the App loaded secondly (the right one) is about 120k smaller, which is approximately the size of the React runtime.</p><h4>Possible disadvantages</h4><ul><li>All Teams contributing Microfrontends need to use webpack as a bundler</li><li>The approach leads to a lot more chunks and additional HTTP requests that could impact the performance of the initial loading if you have a lot of Microfrontends on a page (because of the Browser connection limitation)</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2e3b8e12d5a8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/using-webpack-module-federation-in-mashroom-portal-2e3b8e12d5a8">Using Webpack Module Federation in Mashroom Portal</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[GraphQL Plugin for Mashroom Server]]></title>
            <link>https://medium.com/mashroom-server/graphql-plugin-for-mashroom-server-acf0467e8c17?source=rss----504447fa34a5---4</link>
            <guid isPermaLink="false">https://medium.com/p/acf0467e8c17</guid>
            <category><![CDATA[mashroom]]></category>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[graphql]]></category>
            <dc:creator><![CDATA[Milan Heimschild]]></dc:creator>
            <pubDate>Sun, 19 Feb 2023 10:35:21 GMT</pubDate>
            <atom:updated>2023-02-19T10:35:21.234Z</atom:updated>
            <content:encoded><![CDATA[<p>Although the family of <em>Mashroom Server</em> plugins is continually growing, there still might by an extra functionality you would need to fulfil requirements of your project.</p><p>In this article I demonstrate how to extend <em>Mashroom Server </em>functionality by ability to define GraphQL interfaces with this 3rd party plugin.</p><p><a href="https://graphql.org/">GraphQL</a> is an open-source query and manipulation language for APIs. In contrast with REST it allows client to define structure of data required from server.</p><p>Key concept of the <a href="https://www.mashroom-server.com">Mashroom server</a> is its pluggable system. Except its tiny core — everything is just a <a href="https://www.mashroom-server.com/documentation/docs/html/#keyconcepts">plugin</a>. You write a new API for your app, or just a middleware checking or enriching incoming request — you do it by creating a new plugin.</p><p>This concept is also reused in GraphQL Plugin for <em>Mashroom Server</em>. You create a new plugin defining your schema and <em>Mashroom Server</em> exposes it as an API.</p><p>Before you create first GraphQL Schema, you need to install Mashroom GraphQL plugin to allow <em>Mashroom Server</em> to recognize and to load GraphQL Schemas.</p><pre>npm i -S mashroom-graphql-server</pre><p>After successful installation, you can start to create your first GraphQL Schema.</p><p>Whole example can be found in this <a href="https://github.com/mheimschild/mashroom-graphql-plugin/tree/master/src/testserver/packages/plugin-graphql-test">repository</a></p><p>Each plugin has to have proper definition. Place it in separate <em>mashroom.json</em> file or just into <em>package.json</em></p><pre>{<br>  &quot;name&quot;: &quot;Mashroom GraphQL Person Plugin&quot;,<br>  &quot;type&quot;: &quot;mashroom-graphql-plugin&quot;,<br>  &quot;bootstrap&quot;: &quot;./dist/bootstrap.js&quot;,<br>  &quot;defaultConfig&quot;: {<br>    &quot;pubSub&quot;: &quot;memory&quot;<br>  }<br>}</pre><p>When <em>Mashroom Server</em> detects a plugin it tries to load and bootstrap it. Therefore — a bootstrap method needs to be created too</p><pre>const bootstrap: MashroomGraphQLPluginBootstrapFunction = (pluginName, config, contextHolder, pubSub) =&gt; {<br>  return Promise.resolve(new PersonGraphQLPlugin(pubSub));<br>}</pre><p>Now it’s time to create GraphQL schema</p><pre>getSchema(): DocumentNode | Array&lt;DocumentNode&gt; | string | Array&lt;string&gt; {<br>  return gql`<br>    type Person {<br>      id: ID!<br>    }<br><br>    type Query {<br>      personByName(id: ID!): Person<br>      createPerson(id: ID!): Person<br>    }<br>    <br>    type Subscription {<br>      personCreated: Person<br>    }<br>  `;<br>}<br><br>getResolvers(): IResolvers | Array&lt;IResolvers&gt; {<br>    return {<br>      Query: {<br>        personByName: (parent, args) =&gt; {<br>          return {<br>            id: args.id,<br>          };<br>        },<br><br>        createPerson: (parent, args) =&gt; {<br>          setTimeout(() =&gt; {<br>            this.getPubSub().publish(&#39;PERSON_CREATED&#39;, {<br>              personCreated: {<br>                id: args.id,<br>              },<br>            });<br>          }, 1500);<br>        },<br>      },<br>      Subscription: {<br>        personCreated: {<br>          subscribe: () =&gt; this.getPubSub().asyncIterator([&#39;PERSON_CREATED&#39;]),<br>        },<br>      },<br>    }<br>  }</pre><p>To run <em>Mashroom Server</em> with GraphQL and Websocket support you need to create a customer starter:</p><pre>const { server, expressApp, loggerFactory } = await mashroomServerContextFactory(resolve(&#39;src&#39;, &#39;testserver&#39;));<br><br>await server.start();<br><br>await startGraphQLServer(server._httpServer, expressApp, loggerFactory);</pre><p>Once started, open <a href="http://localhost:5050/graphql">http://localhost:5050/graphql</a> in your web browser.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*niwwiEO6Pl1FkpiDJkRPTg.png" /><figcaption>GraphQL UI</figcaption></figure><p>You can define as many GraphQL Schemas as you need. Mashroom GraphQL Plugin stitches them together fully automatically.</p><h4>Links and references</h4><p><a href="https://www.npmjs.com/package/mashroom-graphql-plugin">Mashroom GraphQL Plugin</a></p><p><a href="https://github.com/mheimschild/mashroom-graphql-plugin/tree/master/src/testserver/packages/plugin-graphql-test">Example used in the article</a></p><p><a href="https://www.mashroom-server.com/documentation/docs/html/">Mashroom Documentation</a></p><p><a href="https://graphql.org/">GraphQL</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=acf0467e8c17" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mashroom-server/graphql-plugin-for-mashroom-server-acf0467e8c17">GraphQL Plugin for Mashroom Server</a> was originally published in <a href="https://medium.com/mashroom-server">Mashroom Server</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>