JS Runtimes

Next-Generation Micro-Frontends: Module Federation and SSR Routing in Deno

Master modern micro-frontends. Use Deno's native support for Import Maps and dynamic ES module loaders to compose high-performance micro-frontends with zero build step compilation.

Sachin Sharma
Sachin SharmaCreator
Jun 4, 2026
4 min read
Next-Generation Micro-Frontends: Module Federation and SSR Routing in Deno
Featured Resource
Quick Overview

Master modern micro-frontends. Use Deno's native support for Import Maps and dynamic ES module loaders to compose high-performance micro-frontends with zero build step compilation.

Next-Generation Micro-Frontends: Module Federation and SSR Routing in Deno

For years, micro-frontends (splitting a large web app into independent teams managing isolated components) required complex build setups. Developers had to use Webpack Module Federation, configure bulky loaders, and run slow node-modules resolutions.

This build-time federation created major issues: it coupled micro-apps to specific bundlers, slowed down CI/CD pipelines, and made Server-Side Rendering (SSR) extremely complex to coordinate.

In 2026, modern JS runtimes have solved this. Deno provides native support for Import Maps, URL imports, and ES Modules.

By leveraging Deno's native runtime resolving engine, we can build a dynamic, bundler-free Micro-Frontend Architecture that fetches and mounts remote components at runtime with native Server-Side Rendering support.


⚡ 1. The Deno Native Federation Model

Traditional federation compiles apps into bundle chunks. Deno resolves everything dynamically:

  1. 2.
    Deno Server (Shell App): The main entrypoint. It parses a global Import Map containing remote URLs for micro-app components.
  2. 4.
    Remote Micro-Apps: Standalone micro-apps that publish standard ESM modules (e.g. header.js, footer.js) over HTTP.
  3. 6.
    Dynamic Resolving: Deno dynamically loads, compiles, and renders these remote components on the server, streaming down unified HTML.
  4. 8.
    Client Hydration: The browser uses the same Import Map to load the same remote JS files for client interactivity (hydration) without compile steps.
[Deno Shell Server] ──(Reads Import Map)──> [Fetch Remote Micro-Apps (ESM)]
         │                                                │
         ├──(Server Renders HTML) <───────────────────────┘
         ▼
[Unified Stream HTML] ──> [Browser Client] ──(Hydrates via Import Map)

🏗️ 2. Designing the Global Import Map

Deno uses standard Import Maps. We define our mappings in a JSON structure containing paths to our decentralized micro-services.

json
// import_map.json { "imports": { "react": "https://esm.sh/react@19.0.0", "react-dom/server": "https://esm.sh/react-dom@19.0.0/server", "micro-header": "https://header-app.sachinsharma.dev/components/Header.js", "micro-checkout": "https://checkout-app.sachinsharma.dev/components/Checkout.js" } }

💻 3. Implementing the Deno SSR Shell Server

Now, let's write our Deno shell application. It fetches the remote components dynamically using URL imports and renders them to an HTML string.

javascript
// server.js import { serve } from "https://deno.land/std@0.177.0/http/server.ts"; import React from "react"; import { renderToString } from "react-dom/server"; // 1. Dynamic Imports enabled natively by Deno's runtime! async function renderShell(req) { const url = new URL(req.url); // 2. Fetch components dynamically based on routing path let BodyComponent; if (url.pathname === '/checkout') { // Dynamic import maps resolve 'micro-checkout' to its remote URL const { Checkout } = await import("micro-checkout"); BodyComponent = Checkout; } else { const { DefaultBody } = await import("./components/DefaultBody.js"); BodyComponent = DefaultBody; } const { Header } = await import("micro-header"); // 3. Render unified React tree to String const appHtml = renderToString( React.createElement(React.Fragment, null, React.createElement(Header, { title: "Deno Federated Shell" }), React.createElement(BodyComponent, null) ) ); // 4. Return complete HTML, injecting the import map for client-side hydration! const finalHtml = ` <!DOCTYPE html> <html> <head> <title>Federated Deno App</title> <!-- Inject Import Map natively into Browser --> <script type="importmap"> { "imports": { "react": "https://esm.sh/react@19.0.0", "micro-header": "https://header-app.sachinsharma.dev/components/Header.js", "micro-checkout": "https://checkout-app.sachinsharma.dev/components/Checkout.js" } } </script> </head> <body> <div id="root">\${appHtml}</div> <!-- Client-Side Hydration script --> <script type="module" src="/client-hydration.js"></script> </body> </html> `; return new Response(finalHtml, { headers: { "content-type": "text/html; charset=utf-8" }, }); } serve(renderShell, { port: 8000 }); console.log("🚀 Federated Deno Shell running at http://localhost:8000");

🚀 4. Writing the Micro-App Header Component

Here is how a micro-app publishes its React component. It is a standard ES module with absolute dependencies, requiring no build tools:

javascript
// https://header-app.sachinsharma.dev/components/Header.js import React from "react"; export function Header({ title }) { const [clicks, setClicks] = React.useState(0); return React.createElement("header", { style: { padding: '20px', background: '#202020', color: '#fff' } }, React.createElement("h1", null, title), React.createElement("button", { onClick: () => setClicks(clicks + 1), style: { background: '#00ffff', color: '#000', border: 'none', padding: '5px 10px' } }, `Active Clicks: \${clicks}`) ); }

📊 5. Architectural Benefits

  • Zero Compile Build Steps: You can push updates to the Header micro-app and Deno/Browser shell will load the latest JS file instantly on page refresh.
  • Bundler Agnostic: No Webpack, Vite, or Rollup configurations are shared. Only standard HTTP ESM imports.
  • Lightweight Server Footprint: Deno compiles and caches remote modules on first fetch, delivering native execution speed on subsequent requests.

🏁 6. Conclusion

Deno's native support for standard web APIs like Import Maps and ES Modules simplifies micro-frontend architectures. By fetching and compiling remote JS files dynamically over HTTP on the server, you eliminate complex bundler setups, decouple micro-apps, and deliver clean, server-side rendered applications.

Sachin Sharma

Sachin Sharma

Software Developer

Building digital experiences at the intersection of design and code. Sharing weekly insights on engineering, productivity, and the future of tech.