Dynamic Flutter Architecture and Flap System for Mobile App Development
The article details Meituan’s Flap system, a static‑DSL‑based dynamic Flutter architecture that converts Dart code into JSON, loads it at runtime, and delivers cross‑platform, low‑cost, high‑performance updates, reducing package size and release cycles while preserving native Flutter rendering quality.
Flutter’s dynamic update has become an unavoidable topic. This article starts with Flutter’s characteristics, then describes the Meituan Takeaway team’s exploration of dynamicization, including design ideas, core principles, and business experience. The perspective is not limited to the framework itself but also discusses what the technical team needs to do when solving problems.
1. Introduction
Flutter’s cross‑platform advantage in consistency and rendering performance has earned it a good reputation. However, package size and dynamic update remain major concerns for large‑scale Internet companies.
Dynamicization shortens the release path, reduces the original package size, improves download willingness, and strengthens online quality maintenance. Consequently, dynamicization is a topic that cannot be avoided, similar to RN and Weex.
Meituan’s MTFlutter team began researching dynamicization in September 2019 and has already launched it in multiple business modules under the internal project name “Flap”.
2. Flap’s Features and Advantages
Flap aims to provide a complete solution rather than a transitional one. Its core goals are:
Generality : maintain multi‑platform support without platform differences.
Low Cost : align with the Flutter ecosystem and convert existing Flutter pages with minimal effort.
Applicability : avoid large, unstable packages.
High Performance : retain Flutter’s excellent rendering performance.
2.1 Core Goals
These goals guide the selection of the dynamicization scheme.
2.2 Dynamicization Options
a. Product Replacement – Flutter once offered a Code‑Push solution (later discontinued). The official statement highlighted performance and security concerns.
To comply with store policies, any solution would be limited to JIT on Android and interpreted code on iOS. We are not confident about the performance and security of such a solution.
b. AOT with JIT – Flutter builds AOT binaries for release, but supporting JIT on top of AOT would increase the package size by >20 MB, which defeats the purpose of size reduction.
c. Dynamic DSL Generation (runtime JS) – Similar to RN, but incurs heavy JS‑to‑Dart communication overhead and breaks the Flutter development experience.
d. Static DSL Generation – Convert Dart source to a JSON‑based DSL offline using the official Analyzer library, then ship the DSL as a compressed package. This approach preserves Flutter/Dart development experience, eliminates platform differences, and meets the low‑cost and high‑performance goals.
2.3 Project Architecture
The architecture is divided into three zones:
Development‑stage assets: correct and Flap‑compliant Dart source.
DSL converter: produces JSON DSL describing page hierarchy and logic.
Runtime environment: loads symbols, builds Dart objects, and renders the dynamic page.
3. Flap’s Principles and Challenges
3.1 Converter Principle
The converter relies on AST (Abstract Syntax Tree) generated by the Dart Analyzer and transforms it into a DSL (Domain‑Specific Language) represented as JSON.
Example of a simple widget conversion (the DSL is shown after de‑compression):
// widget.dart
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) => Text('Hello');
}Corresponding DSL (simplified):
{"class":"MyWidget","extends":"StatelessWidget","build":{"type":"Text","value":"Hello"}}The conversion process handles various AST node types (class, method, variable, statement, etc.) and maps them to ten standard JSON structures.
3.2 Runtime Principle
The runtime consists of two phases: Prepare and Running. Prepare registers symbols (classes, methods, fields) as Dart objects; Running parses the received DSL and constructs the UI.
Key technique – the universal Function.apply() method enables invoking any function (including constructors) with positional and named arguments at runtime:
external static apply(Function function, List positionalArguments, [Map<Symbol, dynamic> namedArguments]);To map string identifiers to actual functions, a Proxy‑Mirror table is built:
{
'EdgeInsets': {
'fromLTRB': (left, top, right, bottom) => EdgeInsets.fromLTRB(left, top, right, bottom),
// ...other functions
},
// ...other classes
}Instance methods, getters, and setters are stored similarly, e.g.:
// instance method
"inflateSize": (instance, size) => instance.inflateSize(size),
// getter
"horizontal": (instance) => instance.horizontal,
// setter
"last": (List instance, dynamic value) => instance.last = value,Custom classes are represented by meta‑objects (FlapVariable, FlapFunction) that allow the runtime to evaluate statements and expressions. Evaluation follows a Scope chain (global → class → local) to resolve variables and functions.
Example of an IfStatement evaluation:
class IfStatement extends Statement {
dynamic condition = undefined;
Body thenBody;
Body elseBody;
ProcessResult evaluate(Scope scope) {
bool conditionValue = condition.evaluate(scope);
if (conditionValue) {
return thenBody(Scope);
} else {
return elseBody(Scope);
}
}
}Scope is a doubly‑linked structure where each level points to its outer and inner scopes, enabling variable lookup across the hierarchy.
3.3 Challenges
Large workload and long‑term patience required for converter, runtime, and ecosystem construction.
Complex project architecture demands careful modular design (parser, intermediate, runtime) following single‑responsibility and minimal‑knowledge principles.
Numerous edge‑case bugs (e.g., static‑method‑to‑constructor conversion, nested loops, function reference execution) need systematic debugging.
4. Ecosystem Support
Flap provides a complete ecosystem covering development, release, testing, and operations.
4.1 Stability
IDE syntax‑checking plugin detects unsupported syntax early.
Gradual rollout and fallback mechanisms (e.g., AOT fallback when Flap crashes).
Integration with Meituan’s internal dynamic release platform (DD) for fine‑grained rule control.
4.2 Speed
Two‑level cache (memory + disk) plus real‑time update ensures minute‑level dynamic releases. Loading time is typically tens of milliseconds; remote fetches stay around one second.
4.3 Accuracy
Fine‑grained dynamicization can target whole pages or individual widgets via the @Flap annotation:
@Flap('close_protect')
class CloseProtectWidget extends StatelessWidget {
// UI and logic implementation
}At runtime, FlapWidgetContainer(widgetId: 'kangaroo_card') loads the corresponding DSL‑generated widget.
4.4 Automation
Automatic import handling (full package paths required).
Proxy‑Mirror generation on demand using the reflectable package.
One‑click toolchain for building, publishing, and monitoring Flap modules.
5. Business Practice and Results
Two main scenarios:
Converting existing Flutter pages to dynamic pages by adding @Flap and letting the toolchain generate DSL.
Developing new pages directly with the Flap stack.
Practical experience includes:
Work‑around unsupported syntax and record issues.
Regularly update IDE plugin rules.
Coordinate release schedules across Android, QA, and PM.
Restrict critical permissions to a few senior admins.
Deployment results show multiple pages (both full‑page and widget‑level) successfully running with average FPS > 58 and rendering latency between 7 ms and 96 ms, comparable to native Flutter performance.
6. Conclusion and Outlook
Flap’s static‑DSL + runtime interpretation achieves a complete Flutter dynamicization solution, shortening release cycles and improving online issue resolution. Future work will focus on expanding complex syntax support, further ecosystem building, and exploring cross‑stack integration via the Flap DSL.
References
Gilad Bracha, The Dart Programming Language , 2015.
Flutter issue #14330 – Code Push/Hot Update.
Analyzer package 0.39.10.
VS Code Extension API.
Flutter Core Technology and Practice (Geekbang).
App Store Review Guidelines.
Authors
Shang Xian – Front‑end technology expert at Meituan (since 2015). Yang Chao – Senior front‑end engineer at Meituan (since 2016). Song Tao – Senior front‑end engineer at Meituan (since 2018).
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.
