@capgo/capacitor-webview-crash
v8.1.4
Published
Capacitor plugin for detecting WebView crash recovery and restarting long-running WebViews natively.
Downloads
18,580
Maintainers
Readme
@capgo/capacitor-webview-crash
Detect recovered Capacitor WebView crashes, restart dead WebViews natively, and optionally recycle long-running WebViews on a fixed interval before memory pressure turns into an OOM.
What It Does
- Stores a native crash marker when Android reports
onRenderProcessGone. - Hooks the iOS WebView termination callback and persists equivalent crash metadata.
- Restarts the WebView natively after crashes so recovery does not depend on a still-running JavaScript runtime.
- Can restart the WebView on a fixed native interval for kiosk, POS, signage, telemetry, and other always-on apps.
- Lets JavaScript request a native WebView restart with
restartWebView()when the app wants to proactively recycle memory. - Exposes the marker through an event, a polling method, and a simulation helper for testing recovery flows.
- Ships a web implementation that simulates the same recovery flow with local storage.
What It Does Not Do
- Prevent the underlying WebView crash from happening.
- Restore lost in-memory JavaScript state automatically.
- Replace application-level state persistence. Persist critical state before enabling scheduled restarts.
Compatibility
| Plugin version | Capacitor compatibility | Maintained | | -------------- | ----------------------- | ---------- | | v8.*.* | v8.*.* | ✅ | | v7.*.* | v7.*.* | On demand | | v6.*.* | v6.*.* | On demand |
Policy:
- New plugins start at version
8.0.0(Capacitor 8 baseline). - Backward compatibility for older Capacitor majors is supported on demand.
Install
You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command:
npx skills add https://github.com/cap-go/capacitor-skills --skill capacitor-pluginsThen use the following prompt:
Use the `capacitor-plugins` skill from `cap-go/capacitor-skills` to install the `@capgo/capacitor-webview-crash` plugin in my project.If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:
npm install @capgo/capacitor-webview-crash
npx cap syncUsage
import { WebViewCrash } from '@capgo/capacitor-webview-crash';
await WebViewCrash.addListener('webViewRestoredAfterCrash', async (info) => {
console.log('Recovered after a WebView crash', info);
await WebViewCrash.clearPendingCrashInfo();
});
await WebViewCrash.addListener('webViewRestoredAfterRestart', async (info) => {
console.log('Recovered after a native WebView restart', info);
await WebViewCrash.clearPendingCrashInfo();
});
const pending = await WebViewCrash.getPendingCrashInfo();
if (pending.value) {
console.log('Pending crash or restart marker', pending.value);
}Use simulateCrashRecovery() in development or automated tests to exercise your recovery UI without forcing a real native WebView crash.
Call restartWebView() when the current JavaScript runtime decides the native WebView should be replaced:
await WebViewCrash.restartWebView();The call writes a pending marker with reason: 'manualRestart', then native code restarts the WebView. Android recreates the host Activity. iOS rebuilds the Capacitor bridge view so a new WKWebView is created instead of reloading the current page.
Native Auto Restart
Configure the plugin in capacitor.config.ts so restart decisions happen in native code, even when the JavaScript runtime is unavailable:
import type { CapacitorConfig } from '@capacitor/cli';
import type { WebViewCrashPluginConfig } from '@capgo/capacitor-webview-crash';
const webViewCrash: WebViewCrashPluginConfig = {
// Keep native crash recovery enabled. This is the default.
restartOnCrash: true,
// Use a 5-field cron schedule in the device local timezone.
// Do not combine restartCron with an active restartIntervalMs.
restartCron: '0 3 * * *',
// Optional delay before restarting after a crash.
restartAfterCrashDelayMs: 0,
};
const config: CapacitorConfig = {
plugins: {
WebViewCrash: webViewCrash,
},
};
export default config;Use scheduled restarts for apps that stay open for days: kiosk screens, control-room dashboards, point-of-sale terminals, warehouse scanners, vehicle tablets, or any Capacitor app that cannot rely on users force-closing it. The restart is native, writes a pending marker with reason: 'periodicRestart', and then creates a fresh WebView.
Set restartIntervalMs to a maintenance window that your product can tolerate, or set restartCron for a wall-clock schedule such as 0 3 * * * for a daily 03:00 restart. restartCron uses 5-field cron syntax in the device local timezone and supports *, lists, ranges, and steps. Do not configure both schedules at once: native initialization throws a fatal config error when restartCron is set and restartIntervalMs is greater than 0. The user will get a fresh JavaScript runtime, so persist unsaved form state, queued events, and in-progress work before enabling a short interval or cron schedule.
Config Type
export interface WebViewCrashPluginConfig {
restartOnCrash?: boolean;
restartIntervalMs?: number;
restartCron?: string;
restartAfterCrashDelayMs?: number;
}Platform Notes
- iOS: Uses method swizzling on Capacitor's
WebViewDelegationHandlerto persist crash metadata before Capacitor reloads the WebView. Manual and scheduled restarts rebuild the Capacitor bridge view so a newWKWebViewinstance is created. No extra permissions are required. - Android: Registers a Capacitor
WebViewListenerand persists crash metadata fromonRenderProcessGone. Crash and scheduled restarts reset the bridge and recreate the host activity, giving the app a fresh WebView. No extra permissions are required. - Web: There is no real browser crash detection. The web implementation only simulates the recovery flow with local storage.
Documentation
API
getPendingCrashInfo()clearPendingCrashInfo()simulateCrashRecovery()restartWebView()addListener('webViewRestoredAfterCrash' | 'webViewRestoredAfterRestart', ...)removeAllListeners()- Interfaces
- Type Aliases
Capacitor API for recovered WebView crash and restart detection.
getPendingCrashInfo()
getPendingCrashInfo() => Promise<PendingCrashInfoResult>Returns the pending native crash or restart marker, if one exists.
Returns: Promise<PendingCrashInfoResult>
clearPendingCrashInfo()
clearPendingCrashInfo() => Promise<void>Clears the stored marker after the app has handled recovery.
simulateCrashRecovery()
simulateCrashRecovery() => Promise<PendingCrashInfoResult>Creates a fake crash marker so recovery flows can be tested locally.
Returns: Promise<PendingCrashInfoResult>
restartWebView()
restartWebView() => Promise<PendingCrashInfoResult>Stores a manual restart marker and asks native code to create a fresh WebView.
On Android this recreates the host Activity. On iOS this rebuilds the Capacitor bridge view so a new WKWebView
instance is created instead of reloading the current page.
Returns: Promise<PendingCrashInfoResult>
addListener('webViewRestoredAfterCrash' | 'webViewRestoredAfterRestart', ...)
addListener(eventName: 'webViewRestoredAfterCrash' | 'webViewRestoredAfterRestart', listenerFunc: (info: WebViewCrashInfo) => void) => Promise<PluginListenerHandle>Fires after a new JavaScript runtime attaches a listener and a matching marker is still pending.
| Param | Type |
| ------------------ | -------------------------------------------------------------------------------- |
| eventName | 'webViewRestoredAfterCrash' | 'webViewRestoredAfterRestart' |
| listenerFunc | (info: WebViewCrashInfo) => void |
Returns: Promise<PluginListenerHandle>
removeAllListeners()
removeAllListeners() => Promise<void>Removes all plugin listeners.
Interfaces
PendingCrashInfoResult
Pending crash or restart marker returned to JavaScript.
| Prop | Type | Description |
| ----------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| value | WebViewCrashInfo | null | Stored crash or restart metadata, or null when no marker is pending. |
WebViewCrashInfo
Metadata captured natively after the previous WebView process died or was restarted.
| Prop | Type | Description |
| ---------------------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------- |
| platform | WebViewCrashPlatform | Platform that detected and stored the marker. |
| timestamp | number | Unix timestamp in milliseconds for when the marker was written. |
| timestampISO | string | ISO-8601 version of timestamp. |
| reason | WebViewCrashReason | Platform-specific reason for the crash or restart marker. |
| url | string | Last known WebView URL when the marker was written. |
| didCrash | boolean | Android-only hint from RenderProcessGoneDetail.didCrash(). |
| rendererPriorityAtExit | number | Android-only renderer priority reported at exit. |
| appState | WebViewCrashAppState | iOS-only application state captured when the marker was written. |
PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
| remove | () => Promise<void> |
Type Aliases
WebViewCrashPlatform
Platform that produced the stored marker.
'android' | 'ios' | 'web'
WebViewCrashReason
Native reason reported for the previous WebView failure or restart.
'renderProcessGone' | 'webContentProcessDidTerminate' | 'periodicRestart' | 'manualRestart' | 'simulated'
WebViewCrashAppState
Best-effort application state captured on iOS when the WebView process died.
'active' | 'inactive' | 'background' | 'unknown'
