WebView Integration
Understand how the Lingu SDK uses WebView for a seamless chat experience.
Hybrid Architecture
The Lingu React Native SDK uses a hybrid approach that combines the best of both worlds:
| Component | Technology | Purpose |
|---|---|---|
| UI Layer | WebView | Consistent, beautiful chat interface |
| API Layer | Native | Fast, reliable network requests |
| Storage | AsyncStorage | Persistent message history |
Why WebView?
Advantages
- Consistent UI: Same pixel-perfect interface on iOS and Android
- Rapid Updates: UI improvements without app store updates
- Smaller Bundle: Core UI shipped via web, reducing app size
- Feature Parity: New features available instantly across platforms
How It Works
sequenceDiagram
participant User
participant WebView as WebView (UI)
participant Native as Native Layer
participant API as Lingu API
User->>WebView: Types message
WebView->>Native: postMessage()
Native->>API: HTTP Request
API-->>Native: AI Response
Native->>WebView: Inject response
WebView-->>User: Display messageCommunication Bridge
The SDK creates a bridge between WebView and React Native:
Web → Native
// Inside WebView
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'SEND_MESSAGE',
payload: { text: 'Hello!' }
}));Native → Web
// React Native side
webViewRef.current?.injectJavaScript(`
window.receiveMessage(${JSON.stringify(message)});
`);WebView Configuration
The SDK configures the WebView optimally:
<WebView
source={{ uri: WIDGET_URL }}
javaScriptEnabled={true}
domStorageEnabled={true}
mixedContentMode="compatibility"
allowsInlineMediaPlayback={true}
onMessage={handleMessage}
// ... other configs
/>Security Settings
| Setting | Value | Reason |
|---|---|---|
javaScriptEnabled | true | Required for chat functionality |
domStorageEnabled | true | Local data storage |
allowsFullscreenVideo | false | Not needed |
allowsBackForwardNavigationGestures | false | Prevent accidental navigation |
Native API Benefits
While using WebView for UI, the SDK makes native API calls for:
1. Network Requests
Native HTTP requests are faster and more reliable than WebView network calls:
// Native fetch instead of WebView fetch
const response = await fetch(API_URL + '/message', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
},
body: JSON.stringify({ message, sessionId }),
});2. Session Management
Sessions are managed natively for better reliability:
// Heartbeat runs in native code
setInterval(() => {
api.sendHeartbeat(sessionId);
}, 30000); // Every 30 seconds3. Local Storage
Messages are persisted using AsyncStorage:
import AsyncStorage from '@react-native-async-storage/async-storage';
// Save messages
await AsyncStorage.setItem('lingu_messages', JSON.stringify(messages));
// Restore on app open
const saved = await AsyncStorage.getItem('lingu_messages');Offline Support
The hybrid architecture enables basic offline functionality:
| Feature | Offline Behavior |
|---|---|
| View message history | Works (from AsyncStorage) |
| Send new messages | Queued until online |
| Receive new messages | Requires connection |
Performance Optimization
1. Lazy Loading
The WebView loads only when the user opens the chat:
const [isOpen, setIsOpen] = useState(false);
return (
<>
<FloatingButton onPress={() => setIsOpen(true)} />
{isOpen && <LinguWebView />}
</>
);2. Preloading
For faster open times, preload the WebView in the background:
// Preload WebView but keep it hidden
<View style={{ height: 0, overflow: 'hidden' }}>
<LinguWebView />
</View>3. Caching
Static assets are cached for faster subsequent loads:
<WebView
cacheEnabled={true}
cacheMode="LOAD_CACHE_ELSE_NETWORK"
/>Custom WebView Integration
For advanced use cases, you can integrate the WebView manually:
import { WebView } from 'react-native-webview';
import { LinguAPI } from '@lingu/react-native-sdk';
const WIDGET_URL = 'https://widget.uselingu.app';
function CustomChat() {
const webViewRef = useRef<WebView>(null);
const api = new LinguAPI('your-api-key');
const handleMessage = async (event) => {
const data = JSON.parse(event.nativeEvent.data);
if (data.type === 'SEND_MESSAGE') {
const response = await api.sendMessage(data.payload.text, sessionId);
webViewRef.current?.injectJavaScript(`
window.receiveMessage(${JSON.stringify(response)});
`);
}
};
return (
<WebView
ref={webViewRef}
source={{ uri: WIDGET_URL }}
onMessage={handleMessage}
javaScriptEnabled={true}
/>
);
}Debugging
Inspect WebView Content
For iOS (Safari):
- Enable Safari Web Inspector on device
- Open Safari on Mac → Develop → [Device Name]
For Android (Chrome):
- Enable USB debugging on device
- Open
chrome://inspectin Chrome
Log Bridge Messages
const handleMessage = (event) => {
console.log('WebView message:', event.nativeEvent.data);
// ... handle message
};