| name | vapp-skill |
| description | VApp Native Bridge Runtime 架构文档。解释 VApp 的事件驱动 Native Bridge 设计,包括 TurboModule、NotificationCenter 分发、Protocol-oriented 服务查找。当用户提及 VApp、RN Bridge、Native Bridge、TurboModule、callNative 时自动触发。 |
VApp Native Bridge Runtime Skill
Overview
VApp uses an event-driven Native Bridge architecture.
The JS layer never directly invokes Objective-C business classes.
Instead, all calls go through a unified TurboModule bridge + NotificationCenter dispatch system.
The architecture is designed to provide:
- Dynamic module dispatch
- Decoupled business implementations
- Protocol-oriented service lookup
- Runtime extensibility
- Cross-platform bridge consistency
Core Runtime Flow
JS
↓
callNative({ module, func, params })
RTNNBTurboModule.callNative()
↓
NSNotificationCenter post("RNCallNativeNotifacation")
RNCommonModule.note()
↓
dynamic selector dispatch
Concrete RN Module
↓
Business Service Lookup
NBVAppManager.service(protocol)
↓
Concrete Service Implementation
Business executes
↓
NSNotificationCenter post("RNCallBackNotifacation")
RTNNBTurboModule.callBack()
↓
resolve(result)
↓
JS Promise resolved
Detailed Call Chain
1. JS Layer
JS initiates a native call through a unified bridge API:
callNative({
module: 'ProtocolBridge',
func: 'readValues',
params,
})
Characteristics:
- module: target native module
- func: target native method
- params: serializable payload
- returns Promise
2. TurboModule Entry
RTNNBTurboModule.callNative()
Responsibilities:
- Receive JS invocation
- Convert payload
- Post bridge notification
- Manage callback lifecycle
- Maintain Promise resolve/reject mapping
This layer does NOT contain business logic.
3. Notification Dispatch
NSNotificationCenter
postNotificationName:@"RNCallNativeNotifacation"
Payload:
- module
- func
- params
- callbackId
Purpose:
- Completely decouple JS bridge from business modules
- Allow runtime dynamic module registration
4. RNCommonModule Dynamic Dispatch
All bridge modules inherit from:
RNCommonModule
Each module listens to:
RNCallNativeNotifacation
Core logic:
selector(funcName:)
Example:
readValues:
Dynamic runtime dispatch is performed using Objective-C selector reflection.
5. Glue Layer (Bridge Module)
Example:
RNProtocolBridgeModule.readValues()
Responsibilities:
- Parameter validation
- DTO conversion
- Bridge adaptation
- Service routing
This layer should remain thin.
It should NOT contain real business logic.
6. Service Locator
NBVAppManager.service(NBProtocolBridgeProtocol)
This acts as a protocol-based dependency resolver.
Characteristics:
- Protocol-oriented architecture
- Runtime service discovery
- Loose coupling
- Replaceable implementations
7. Business Implementation
Example:
ProtocolBridgeServiceImpl.readValues()
This is the actual business execution layer.
Responsibilities:
- Real business logic
- Data access
- Native capability invocation
- Async task orchestration
8. Callback Flow
After business execution completes:
NSNotificationCenter
postNotificationName:@"RNCallBackNotifacation"
Then:
RTNNBTurboModule.callBack()
Finally:
resolve(result)
Result returns back to JS Promise.
Architectural Principles
1. Event Driven
Bridge communication is based on NotificationCenter.
Advantages:
- Loose coupling
- Dynamic extensibility
- Easier pluginization
2. Protocol-Oriented Design
Business services are resolved by protocol instead of concrete class.
service(NBProtocolBridgeProtocol)
Advantages:
- Better modularity
- Easier testing
- Replaceable implementations
3. Thin Bridge Layer
RN modules are glue layers only.
They should NOT:
- Contain business logic
- Access database directly
- Perform complex orchestration
4. Runtime Dynamic Dispatch
Method dispatch uses Objective-C runtime selectors.
selector("methodName:")
Advantages:
- Dynamic extensibility
- Configurable routing
- Low boilerplate
Tradeoffs:
- Runtime safety reduced
- Requires strict naming conventions
Recommended Layer Responsibilities
| Layer | Responsibility |
|---|
| JS | API invocation |
| TurboModule | Bridge transport |
| NotificationCenter | Event routing |
| RNCommonModule | Dynamic dispatch |
| RNxxxModule | Glue layer |
| Service Locator | Dependency resolution |
| ServiceImpl | Business implementation |
Important Conventions
Selector Naming
All exposed methods must follow:
methodName:
Example:
readValues:
writeValues:
fetchConfig:
Bridge Modules Must Be Stateless
Bridge modules should only:
- Receive payload
- Convert payload
- Forward request
Avoid storing state inside RN modules.
Callback IDs
Every async bridge call should contain:
callbackId
Used for Promise resolution mapping.
Example End-to-End Flow
JS
→ callNative()
TurboModule
→ post RNCallNativeNotifacation
RNProtocolBridgeModule
→ readValues:
NBVAppManager
→ resolve service
ProtocolBridgeServiceImpl
→ execute business logic
Service
→ post RNCallBackNotifacation
TurboModule
→ resolve Promise
JS
→ await result
Recommended AI Understanding
When generating code for this architecture, AI should follow these rules:
- Business logic belongs in ServiceImpl
- RN Modules are glue layers only
- Communication is notification-driven
- Service lookup is protocol-oriented
- JS never directly accesses business services
- Dynamic selector dispatch is core infrastructure
- Bridge layer should remain highly generic
- All async operations return through callback notifications
Typical Extension Flow
To add a new native capability:
- Add JS API
- Add RNxxxModule selector method
- Define Protocol
- Register ServiceImpl
- Implement business logic
- Return callback through notification
No TurboModule modification is required.