Frontend Development 22 min read

Micro Frontends: Concepts, Implementation, and Lessons from the Shangling Project

This article explains the concept of micro frontends, why they are needed, their core principles such as technology‑agnostic integration, centralized routing, isolation, communication, version management and performance, and details a real‑world implementation using the qiankun framework in the Shangling project, including code snippets and future challenges.

JD Retail Technology
JD Retail Technology
JD Retail Technology
Micro Frontends: Concepts, Implementation, and Lessons from the Shangling Project

Web applications have evolved from mixed front‑end/back‑end architectures to fully separated front‑ends, leading to larger, more complex projects that require splitting. Micro frontends provide a strategy to decompose large front‑end applications into independent, deployable modules while preserving a seamless user experience.

What is a micro frontend? It is a technical approach that allows multiple teams to build independent, deployable web applications that can be integrated into a single page, similar to the concept of micro‑services for back‑end systems.

Why use micro frontends? They address challenges of scaling, team collaboration, and user experience by enabling independent development, technology‑stack agnosticism, centralized routing, and isolated execution environments.

Core principles include:

Technology‑agnostic integration (Vue, React, Angular, jQuery, etc.)

Centralized routing managed by the main application

Independent development and deployment of sub‑applications

Simple integration similar to iFrame but with better performance

Consistent developer experience across sub‑apps

The Shangling project adopted the qiankun framework (built on single‑spa ) to implement micro frontends. The main app registers sub‑apps, handles routing, and provides a sandbox for isolation.

Running principle (simplified):

Browser loads the main application.

Main app registers sub‑applications with name, entry URL, container, and activation rule.

When a route matches, the sub‑app’s HTML template is fetched.

The framework parses the template, loads JavaScript and CSS, creates a sandbox (using Proxy or snapshot), and mounts the sub‑app.

Prefetching loads other sub‑apps during idle time for faster subsequent activation.

Routing rule example used in the project:

Each sub‑app corresponds to a top‑level route; secondary menus are flattened; related pages share a second‑level route.

Isolation techniques :

CSS isolation via naming conventions, Shadow DOM , or runtime CSS transformers (the project uses naming conventions and enables Shadow DOM in qiankun).

JavaScript sandbox using ProxySandbox (fallback to SnapshotSandbox when Proxy is unavailable).

Inter‑application communication can be achieved with native CustomEvent or qiankun’s initGlobalState API. Example code:

// Create event
let event = new CustomEvent('event-a', { detail: 'hello' });
// Listen
document.addEventListener('event-a', function(e) { console.log(e.detail); });
// Dispatch
document.dispatchEvent(event);
// Main app: init global state
import { initGlobalState, MicroAppStateActions } from 'qiankun';
const actions: MicroAppStateActions = initGlobalState(state);
actions.onGlobalStateChange((state, prev) => { console.log(state, prev); });
actions.setGlobalState(state);
// Sub app: use props to communicate
export function mount(props) {
  props.onGlobalStateChange((state, prev) => { console.log(state, prev); });
  props.setGlobalState(state);
}

Version management ensures users receive the latest sub‑app versions by hashing static assets and invalidating HTML template caches via Nginx headers.

Performance optimizations follow standard web‑front‑end best practices: reducing favicon size, minimizing cookies, compressing assets with Gzip, leveraging CDN, HTTP/2, preloading, and on‑demand loading of resources.

Integration steps with qiankun :

import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
  { name: 'module-overview', entry: 'https://overview.selling.cn', container: '#root-view', activeRule: '/overview' },
  { name: 'module-shop', entry: 'https://info.selling.cn', container: '#root-view', activeRule: '/shop' }
]);
start({ prefetch: true });

Typical sub‑app lifecycle functions (Vue/TS example):

export async function bootstrap() { console.log('[vue] vue app bootstraped'); }
export async function mount(props) { render(props); }
export async function unmount() { instance.$destroy(); instance.$el.innerHTML = ''; instance = null; }
if (!window.__POWERED_BY_QIANKUN__) { render(); }

Configuration files such as vue.config.js , public-path.js , main.ts , and router.ts are adjusted to support UMD builds, cross‑origin headers, and dynamic base routes when running under qiankun.

The article also discusses challenges (increased bundle size from multiple tech stacks, debugging complexity, limited benefits for small projects) and future work (shared component libraries, dynamic sub‑app registration, menu caching, scaffolding, gray releases, low‑code development).

Finally, the author invites developers to join the team, providing a contact email for recruitment.

performance optimizationIntegrationFrontend Architectureqiankunmicro frontendsjavascript sandbox
JD Retail Technology
Written by

JD Retail Technology

Official platform of JD Retail Technology, delivering insightful R&D news and a deep look into the lives and work of technologists.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.