r/FlutterDev • u/narukarudra_10 • 1h ago
Plugin I built webview_ultra: flutter_inappwebview features with official webview_flutter footprint (~200 KB vs ~6 MB) + Windows support
Hey everyone,
Whenever I needed advanced WebView capabilities in Flutter—such as headless execution, modal in-app browsers, typed bidirectional JS-to-Dart RPC bridges, or fine-grained load progress handling—the standard choice was almost always flutter_inappwebview.
While powerful, it often adds significant binary weight (~5–8 MB) and relies on a large custom native platform layer that can be tricky to debug across OS updates. On the other hand, Google’s official webview_flutter is lightweight and uses native Pigeon bindings, but requires tons of boilerplate for common patterns (like reactive rebuilds, JS promise handling, or desktop support).
To bridge this gap, I created webview_ultra.
What it does differently:
Lightweight Core (~200 KB): Built directly on top of the official webview_flutter Pigeon engine for Android, iOS, and macOS, paired with Microsoft Edge WebView2 on Windows. Zero extra native bloat.
Zero-Screen-Rebuild Reactive State: Instead of calling setState on every URL or progress update, WebviewUltraController exposes granular ValueNotifier instances. Subtrees update independently using widgets like WebviewTitleBuilder, WebviewProgressBuilder, and WebviewHistoryBuilder.
Typed Bidirectional JS Bridge: Send and receive typed JSON-RPC messages and Promises between Dart and JavaScript with cross-compatibility for window.webview_ultra.callHandler(...).
Turnkey Features Included:
Drop-in 1-line widget with built-in progress indicators and pull-to-refresh
HeadlessWebviewUltra for off-screen tasks (token parsing, preheating, scraping)
InAppBrowserUltra modal wrapper
Regex-based content and ad-filtering
Quick Example:
Dart
// Reactive progress + 1-line setup without rebuilding the parent widget
Scaffold(
appBar: AppBar(
title: WebviewTitleBuilder(
controller: controller,
builder: (context, title, _) => Text(title.isEmpty ? 'Loading...' : title),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(2.0),
child: WebviewProgressBuilder(
controller: controller,
builder: (context, progress, _) => progress < 1.0
? LinearProgressIndicator(value: progress)
: const SizedBox.shrink(),
),
),
),
body: WebviewUltra(
controller: controller,
initialUrl: 'https://flutter.dev',
pullToRefresh: true,
),
);
Links:
pub.dev: pub.dev/packages/webview_ultra
GitHub: github.com/Narukarudra10/webview_ultra
I’d love to hear your thoughts, feedback, or any edge cases you've run into with WebView state management in Flutter!