Micro‑Frontend Architecture for Meituan HR System
Meituan’s HR platform adopts a micro‑frontend architecture where a central Portal container registers isolated sub‑projects via a global route array, namespaces CSS, unifies shared libraries through a custom require system, and deploys static assets with PM2, delivering a single‑page experience, independent releases, and minimal bundle overhead.
Micro‑frontend, proposed by ThoughtWorks in 2016, brings the micro‑service idea to the browser, turning a single‑page monolith into a collection of small front‑end applications that can be developed, tested and released independently.
Meituan, a large internet company, needed to improve the efficiency of its internal management systems. The HR system, composed of more than 30 micro‑frontends and over 1,000 pages, is presented to users as a single‑page application while each sub‑project remains isolated for developers.
The solution introduces a "Portal" project that acts as a container and a set of "sub‑projects" that provide only resource files (js, css, fonts, images). The portal handles user login, menu permissions, global error handling and data tracking.
Application registration mechanism
Sub‑projects register their routes to a global window.app.routes array. The portal renders a custom Router component (based on react‑router) that merges all routes into a single routing tree.
let Router = <Router fetchMenu={fetchMenuHandle} routes={routes} app={App} history={history}>During registration, each sub‑project calls window.app.init(namespace, reducers) to mount its Redux reducers and to create a scoped container for modal dialogs.
app.init = async function (namespace, reducers) { ... }Project scope control
All CSS is namespaced using a PostCSS plugin that prefixes selectors with .namespace-kaoqin, preventing style leakage between sub‑projects.
.namespace-kaoqin .attendance-record { height: 100%; position: relative; }JS library version unification
The portal redefines common libraries (e.g., React, React‑DOM) via app.define and forces sub‑projects to import them through window.app.require, ensuring a single version across the whole system.
app.define('react', require.context('react', true, /.\/lib\/[^\/]+\.js$/), 'react.js');Webpack externals replace direct require('react') calls with window.app.require('react') during the build of sub‑projects.
module.exports = function (context, request, callback) { if (libs.indexOf(request.split('/', 1)[0]) !== -1) { callback(null, `var window.app.require('${request}')`); } else { callback(); } };Build and deployment
After building, the portal and sub‑projects generate static assets that are uploaded to the server. The portal’s entry files ( entry‑xx.js, index.html) are regenerated, and the front‑end service (Node server) is restarted using PM2 for hot deployment.
The deployment process includes:
Fetching code, installing dependencies and building on the CI machine.
Uploading build artifacts to the server.
Running node index.js to start the service.
Static services can achieve hot updates without a restart, but Meituan uses a Node service layer and PM2 for reliable restarts.
Benefits
Single‑page experience with on‑demand loading and smooth interaction.
Micro‑frontend isolation improves stability and granularity control.
Minimal overhead: 30+ sub‑projects add only ~12 KB to the entry bundle.
Overall, the micro‑frontend approach enables flexible composition of HR functionalities (attendance, leave, approval, finance) and can be abstracted into a reusable library for other business domains.
Meituan Technology Team
Over 10,000 engineers powering China’s leading lifestyle services e‑commerce platform. Supporting hundreds of millions of consumers, millions of merchants across 2,000+ industries. This is the public channel for the tech teams behind Meituan, Dianping, Meituan Waimai, Meituan Select, and related services.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
