Componentization Development Practices at Meituan: From Version 1.0 to 3.0
Meituan’s componentization journey progressed from early resource‑centric modules (1.0) through mature lifecycle, data‑binding, and Flux integration (2.0) to a React‑based, NPM‑distributed, Reduce‑bundled, Turbo‑enhanced ecosystem (3.0), systematically reducing front‑end complexity while boosting reuse, performance, and full‑stack development efficiency.
Introduction
A senior engineer once said:
Controlling complexity is the essence of computer programming.As front‑end development complexity grows, component‑based development emerged, flourishing with frameworks such as FIS and React. Meituan faced rapid business expansion and a growing engineering team, and went through several stages—introducing componentization to solve resource integration, enhancing component capabilities to boost efficiency, and rebuilding a next‑generation solution for full‑stack development and shared construction—to "control complexity".
Componentization 1.0: Resource Reorganization
In Meituan’s early days, front‑end resources were organized by page or business‑page collections (e.g., order.js for order pages, account.css for account pages). This worked for a long time but began to show drawbacks as the business scaled.
Resource redundancy – growing pages and interactions caused CSS/JS bloat; loading an entire module just for a single function became common.
Unclear mapping – developers relied on grep to locate dependencies, leading to stale files.
Difficult unit testing – page‑level granularity made modules tightly coupled and hard to automate.
In 2013, after researching FIS and BEM, Meituan built a lightweight componentization solution with three main improvements:
Aggregate front‑end resources by functional component.
Automatically load CSS/JS that match conventions.
Separate business data from rendering data.
Example: the search box at the top of Meituan is a component.
www/component/smart-box/
├── smart-box.js # interaction
├── smart-box.php # data generation & component config
├── smart-box.scss # styles
├── smart-box.tpl # markup
└── test
├── default.js # automated test
└── default.php # test pageUsing the component is straightforward:
echo View::useComponent('smart-box', ['keyword' => $keyword]);Key benefits:
On‑demand loading – only necessary resources are fetched.
Clear mapping – all resources needed by a component reside in the same directory.
Easy testing – each component is a minimal, testable unit (e.g., via Phantom).
Centralized resource scheduling also opens space for advanced performance optimizations such as component‑level BigRender and resource merging.
Componentization 2.0: Maturity
Lifecycle
Components need lifecycle hooks to expose interfaces for complex page requirements (e.g., binding after a payment‑password component finishes). Both Web Components and React provide such hooks, and Meituan adopted a similar model.
The component lifecycle includes:
init – initialize root node and configuration.
fetch – load CSS and JS.
render – render content (default is BigRender).
ready – bind data and events.
update – handle data updates.
destroy – clean up listeners and DOM nodes.
Components also expose pause and resume for fine‑grained control. The following code shows how Meituan orchestrates lifecycle with promises and custom events:
var afterLoadList = [];
Y.all('[data-component]').each(function (node) {
var component = new Y.mt.Component(node);
component.after('init', function (e) {
if (e.config.afterLoad) {
e.component.pause();
afterLoadList.push(e.component);
}
});
component.start();
});
Y.on('load', function () {
afterLoadList.forEach(function (component) {
component.resume();
});
});Data Binding
Inspired by Angular, Meituan introduced a declarative data‑binding syntax that works both on the client and during server rendering.
<ul class="addressList">
<li mt-bind-repeat="addr in addrList" mt-bind-html="addr.text"></li>
</ul>
<script>
Y.use(['mt-bind','mt-scope'], function(){
Y.mt.bind.init(document.body);
var scope = Y.one('.addressList').getScope();
scope.$set('addrList', [
{text: "first address"},
{text: "second address"}
]);
});
</script>This approach enables fast visual feedback for display‑heavy pages.
Flux
To coordinate data across multiple components, a global message bus (Flux) was added. After refactoring a complex purchase page with component + Flux, inter‑module interactions became clearer.
Componentization 3.0: Reboot
By the end of 2014, new challenges emerged:
Node‑based full‑stack development opened front‑back rendering possibilities.
YUI was discontinued, requiring a new resource management solution.
Rapidly growing business demanded shared component libraries.
Meituan responded with three pillars:
React‑based page components distributed via NPM for shared development.
Browserify‑based bundler “Reduce” to package resources.
Engineering platform “Turbo” to streamline component usage.
React
React’s data binding, lifecycle, server rendering, and Flux concepts aligned perfectly with Meituan’s needs, prompting a shift to React for version 3.0.
NPM + Reduce
NPM handles component publishing and installation (the “distribution” side), while Reduce bundles JS, CSS, images, and fonts for fast browser delivery (the “aggregation” side).
smart-box/
├── package.json # component metadata
├── smart-box.jsx # React component
├── smart-box.scss # styles
└── test
└── main.js # test {
"style": "./smart-box.scss"
}After requiring the component, Reduce ensures that JS, CSS, images, and fonts are all delivered to the browser.
var SmartBox = require('@mtfe/smart-box');
var IndexPage = React.createClass({
render: function() {
return (
<Header>
<SmartBox keyword={this.props.keyword} />
</Header>
);
}
});
module.exports = IndexPage;Turbo
Turbo adds a suite of middleware and tools on top of the Node framework to make component development smooth:
Supports universal (isomorphic) rendering for early content display.
Simplifies Flux flow for clearer data streams.
Integrates ImmutableJS to keep store data immutable.
Uses cursor mechanisms for synchronous data access.
Provides Hot Module Replacement for rapid iteration.
These improvements let engineers focus on business logic while enjoying a robust component ecosystem.
Conclusion
The iterative practice of identifying pain points, researching solutions, and applying improvements has driven Meituan’s componentization from 1.0 to 3.0. The approach effectively mitigates rising complexity, cultivates a “small‑and‑beautiful” engineering mindset, and fosters a culture of shared component development that will continue to influence front‑end practices.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
