perf(webkit): enable page cache and smooth scrolling for faster page transitions
- commit
- 76e6e0a2c95678ff22653ae7fddb211f653cc641
- author
- bnema · · 2025-10-23 22:06 UTC
- committer
- bnema · · 2025-10-24 17:33 UTC
- parent
- 54adfbb
- signature
- GPG Unverified
2B82207D370127A0The key is unknown
3 files · +64 -21
M internal/app/browser/webview.go +13 -11
| @@ -43,17 +43,19 @@ func (app *BrowserApp) buildWebkitConfig() (*webkit.Config, error) { | |||
| 43 | 43 | ||
| 44 | 44 | // Build WebKit configuration with data directories for persistence | |
| 45 | 45 | cfg := &webkit.Config{ | |
| 46 | - | UserAgent: buildUserAgent(app.config), | |
| 47 | - | EnableJavaScript: true, | |
| 48 | - | EnableWebGL: true, | |
| 49 | - | EnableMediaStream: true, | |
| 50 | - | HardwareAcceleration: true, | |
| 51 | - | DefaultFontSize: app.config.Appearance.DefaultFontSize, | |
| 52 | - | MinimumFontSize: 8, | |
| 53 | - | DataDir: webkitData, | |
| 54 | - | CacheDir: webkitCache, | |
| 55 | - | AppearanceConfigJSON: app.buildAppearanceConfigJSON(), | |
| 56 | - | CreateWindow: true, // Default to creating a window for standalone WebViews | |
| 46 | + | UserAgent: buildUserAgent(app.config), | |
| 47 | + | EnableJavaScript: true, | |
| 48 | + | EnableWebGL: true, | |
| 49 | + | EnableMediaStream: true, | |
| 50 | + | HardwareAcceleration: true, | |
| 51 | + | DefaultFontSize: app.config.Appearance.DefaultFontSize, | |
| 52 | + | MinimumFontSize: 8, | |
| 53 | + | EnablePageCache: true, // Instant back/forward navigation (bfcache) | |
| 54 | + | EnableSmoothScrolling: true, // Smooth scrolling animations | |
| 55 | + | DataDir: webkitData, | |
| 56 | + | CacheDir: webkitCache, | |
| 57 | + | AppearanceConfigJSON: app.buildAppearanceConfigJSON(), | |
| 58 | + | CreateWindow: true, // Default to creating a window for standalone WebViews | |
| 57 | 59 | } | |
| 58 | 60 | ||
| 59 | 61 | return cfg, nil | |
| @@ -43,17 +43,19 @@ func (app *BrowserApp) buildWebkitConfig() (*webkit.Config, error) { | |||||
| 43 | 43 | ||||
| 44 | // Build WebKit configuration with data directories for persistence | 44 | // Build WebKit configuration with data directories for persistence | ||
| 45 | cfg := &webkit.Config{ | 45 | cfg := &webkit.Config{ | ||
| 46 | - | UserAgent: buildUserAgent(app.config), | 46 | + | UserAgent: buildUserAgent(app.config), |
| 47 | - | EnableJavaScript: true, | 47 | + | EnableJavaScript: true, |
| 48 | - | EnableWebGL: true, | 48 | + | EnableWebGL: true, |
| 49 | - | EnableMediaStream: true, | 49 | + | EnableMediaStream: true, |
| 50 | - | HardwareAcceleration: true, | 50 | + | HardwareAcceleration: true, |
| 51 | - | DefaultFontSize: app.config.Appearance.DefaultFontSize, | 51 | + | DefaultFontSize: app.config.Appearance.DefaultFontSize, |
| 52 | - | MinimumFontSize: 8, | 52 | + | MinimumFontSize: 8, |
| 53 | - | DataDir: webkitData, | 53 | + | EnablePageCache: true, // Instant back/forward navigation (bfcache) |
| 54 | - | CacheDir: webkitCache, | 54 | + | EnableSmoothScrolling: true, // Smooth scrolling animations |
| 55 | - | AppearanceConfigJSON: app.buildAppearanceConfigJSON(), | 55 | + | DataDir: webkitData, |
| 56 | - | CreateWindow: true, // Default to creating a window for standalone WebViews | 56 | + | CacheDir: webkitCache, |
| 57 | + | AppearanceConfigJSON: app.buildAppearanceConfigJSON(), | |||
| 58 | + | CreateWindow: true, // Default to creating a window for standalone WebViews | |||
| 57 | } | 59 | } | ||
| 58 | 60 | ||||
| 59 | return cfg, nil | 61 | return cfg, nil | ||
M pkg/webkit/types.go +17 -8
| @@ -45,6 +45,13 @@ type Config struct { | |||
| 45 | 45 | // MinimumFontSize in pixels | |
| 46 | 46 | MinimumFontSize int | |
| 47 | 47 | ||
| 48 | + | // Performance optimizations | |
| 49 | + | // EnablePageCache enables back/forward cache for instant navigation | |
| 50 | + | EnablePageCache bool | |
| 51 | + | ||
| 52 | + | // EnableSmoothScrolling enables smooth scrolling animations | |
| 53 | + | EnableSmoothScrolling bool | |
| 54 | + | ||
| 48 | 55 | // DataDir is the directory for persistent data (cookies, localStorage, etc.) | |
| 49 | 56 | DataDir string | |
| 50 | 57 | ||
| @@ -63,13 +70,15 @@ type Config struct { | |||
| 63 | 70 | // GetDefaultConfig returns a Config with sensible defaults | |
| 64 | 71 | func GetDefaultConfig() *Config { | |
| 65 | 72 | return &Config{ | |
| 66 | - | UserAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36", | |
| 67 | - | EnableJavaScript: true, | |
| 68 | - | EnableWebGL: true, | |
| 69 | - | EnableMediaStream: true, | |
| 70 | - | HardwareAcceleration: true, | |
| 71 | - | DefaultFontSize: 16, | |
| 72 | - | MinimumFontSize: 8, | |
| 73 | - | CreateWindow: true, // Default to standalone window | |
| 73 | + | UserAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36", | |
| 74 | + | EnableJavaScript: true, | |
| 75 | + | EnableWebGL: true, | |
| 76 | + | EnableMediaStream: true, | |
| 77 | + | HardwareAcceleration: true, | |
| 78 | + | DefaultFontSize: 16, | |
| 79 | + | MinimumFontSize: 8, | |
| 80 | + | EnablePageCache: true, // Instant back/forward navigation | |
| 81 | + | EnableSmoothScrolling: true, // Better UX | |
| 82 | + | CreateWindow: true, // Default to standalone window | |
| 74 | 83 | } | |
| 75 | 84 | } | |
| @@ -45,6 +45,13 @@ type Config struct { | |||||
| 45 | // MinimumFontSize in pixels | 45 | // MinimumFontSize in pixels | ||
| 46 | MinimumFontSize int | 46 | MinimumFontSize int | ||
| 47 | 47 | ||||
| 48 | + | // Performance optimizations | |||
| 49 | + | // EnablePageCache enables back/forward cache for instant navigation | |||
| 50 | + | EnablePageCache bool | |||
| 51 | + | ||||
| 52 | + | // EnableSmoothScrolling enables smooth scrolling animations | |||
| 53 | + | EnableSmoothScrolling bool | |||
| 54 | + | ||||
| 48 | // DataDir is the directory for persistent data (cookies, localStorage, etc.) | 55 | // DataDir is the directory for persistent data (cookies, localStorage, etc.) | ||
| 49 | DataDir string | 56 | DataDir string | ||
| 50 | 57 | ||||
| @@ -63,13 +70,15 @@ type Config struct { | |||||
| 63 | // GetDefaultConfig returns a Config with sensible defaults | 70 | // GetDefaultConfig returns a Config with sensible defaults | ||
| 64 | func GetDefaultConfig() *Config { | 71 | func GetDefaultConfig() *Config { | ||
| 65 | return &Config{ | 72 | return &Config{ | ||
| 66 | - | UserAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36", | 73 | + | UserAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36", |
| 67 | - | EnableJavaScript: true, | 74 | + | EnableJavaScript: true, |
| 68 | - | EnableWebGL: true, | 75 | + | EnableWebGL: true, |
| 69 | - | EnableMediaStream: true, | 76 | + | EnableMediaStream: true, |
| 70 | - | HardwareAcceleration: true, | 77 | + | HardwareAcceleration: true, |
| 71 | - | DefaultFontSize: 16, | 78 | + | DefaultFontSize: 16, |
| 72 | - | MinimumFontSize: 8, | 79 | + | MinimumFontSize: 8, |
| 73 | - | CreateWindow: true, // Default to standalone window | 80 | + | EnablePageCache: true, // Instant back/forward navigation |
| 81 | + | EnableSmoothScrolling: true, // Better UX | |||
| 82 | + | CreateWindow: true, // Default to standalone window | |||
| 74 | } | 83 | } | ||
| 75 | } | 84 | } | ||
M pkg/webkit/webview.go +34 -2
| @@ -46,6 +46,9 @@ type WebView struct { | |||
| 46 | 46 | onWorkspaceNavigation func(direction string) bool // Workspace pane navigation | |
| 47 | 47 | onPaneModeShortcut func(action string) bool // Pane mode shortcuts (enter, actions, exit) | |
| 48 | 48 | isPaneModeActive func() bool // Check if pane mode is active | |
| 49 | + | onLoadStarted func() // Load started event | |
| 50 | + | onLoadCommitted func() // Load committed event (DOM available) | |
| 51 | + | onLoadFinished func() // Load finished event | |
| 49 | 52 | } | |
| 50 | 53 | ||
| 51 | 54 | // NewWebView creates a new WebView with the given configuration | |
| @@ -197,6 +200,13 @@ func (w *WebView) applyConfig() error { | |||
| 197 | 200 | // Enable hardware acceleration if configured | |
| 198 | 201 | settings.SetHardwareAccelerationPolicy(webkit.HardwareAccelerationPolicyAlways) | |
| 199 | 202 | ||
| 203 | + | // Performance optimizations for faster page transitions | |
| 204 | + | // Enable page cache for instant back/forward navigation (bfcache) | |
| 205 | + | settings.SetEnablePageCache(w.config.EnablePageCache) | |
| 206 | + | ||
| 207 | + | // Enable smooth scrolling for better UX | |
| 208 | + | settings.SetEnableSmoothScrolling(w.config.EnableSmoothScrolling) | |
| 209 | + | ||
| 200 | 210 | return nil | |
| 201 | 211 | } | |
| 202 | 212 | ||
| @@ -229,9 +239,31 @@ func (w *WebView) setupEventHandlers() { | |||
| 229 | 239 | // Favicon changed - connect to FaviconDatabase | |
| 230 | 240 | w.setupFaviconHandlers() | |
| 231 | 241 | ||
| 232 | - | // Load changed | |
| 242 | + | // Load changed - track page lifecycle for performance monitoring | |
| 233 | 243 | w.view.ConnectLoadChanged(func(event webkit.LoadEvent) { | |
| 234 | - | // Handle load events if needed | |
| 244 | + | // Avoid calling callbacks if WebView is being destroyed to prevent reference cycles | |
| 245 | + | // especially important when page cache is enabled | |
| 246 | + | if w.IsDestroyed() { | |
| 247 | + | return | |
| 248 | + | } | |
| 249 | + | ||
| 250 | + | switch event { | |
| 251 | + | case webkit.LoadStarted: | |
| 252 | + | // Page load started - could show loading indicator | |
| 253 | + | if w.onLoadStarted != nil { | |
| 254 | + | w.onLoadStarted() | |
| 255 | + | } | |
| 256 | + | case webkit.LoadCommitted: | |
| 257 | + | // Page committed - DOM is now available for interaction | |
| 258 | + | if w.onLoadCommitted != nil { | |
| 259 | + | w.onLoadCommitted() | |
| 260 | + | } | |
| 261 | + | case webkit.LoadFinished: | |
| 262 | + | // Page fully loaded - all resources downloaded | |
| 263 | + | if w.onLoadFinished != nil { | |
| 264 | + | w.onLoadFinished() | |
| 265 | + | } | |
| 266 | + | } | |
| 235 | 267 | }) | |
| 236 | 268 | ||
| 237 | 269 | // TLS error handling - connect to load-failed-with-tls-errors signal | |
| @@ -46,6 +46,9 @@ type WebView struct { | |||||
| 46 | onWorkspaceNavigation func(direction string) bool // Workspace pane navigation | 46 | onWorkspaceNavigation func(direction string) bool // Workspace pane navigation | ||
| 47 | onPaneModeShortcut func(action string) bool // Pane mode shortcuts (enter, actions, exit) | 47 | onPaneModeShortcut func(action string) bool // Pane mode shortcuts (enter, actions, exit) | ||
| 48 | isPaneModeActive func() bool // Check if pane mode is active | 48 | isPaneModeActive func() bool // Check if pane mode is active | ||
| 49 | + | onLoadStarted func() // Load started event | |||
| 50 | + | onLoadCommitted func() // Load committed event (DOM available) | |||
| 51 | + | onLoadFinished func() // Load finished event | |||
| 49 | } | 52 | } | ||
| 50 | 53 | ||||
| 51 | // NewWebView creates a new WebView with the given configuration | 54 | // NewWebView creates a new WebView with the given configuration | ||
| @@ -197,6 +200,13 @@ func (w *WebView) applyConfig() error { | |||||
| 197 | // Enable hardware acceleration if configured | 200 | // Enable hardware acceleration if configured | ||
| 198 | settings.SetHardwareAccelerationPolicy(webkit.HardwareAccelerationPolicyAlways) | 201 | settings.SetHardwareAccelerationPolicy(webkit.HardwareAccelerationPolicyAlways) | ||
| 199 | 202 | ||||
| 203 | + | // Performance optimizations for faster page transitions | |||
| 204 | + | // Enable page cache for instant back/forward navigation (bfcache) | |||
| 205 | + | settings.SetEnablePageCache(w.config.EnablePageCache) | |||
| 206 | + | ||||
| 207 | + | // Enable smooth scrolling for better UX | |||
| 208 | + | settings.SetEnableSmoothScrolling(w.config.EnableSmoothScrolling) | |||
| 209 | + | ||||
| 200 | return nil | 210 | return nil | ||
| 201 | } | 211 | } | ||
| 202 | 212 | ||||
| @@ -229,9 +239,31 @@ func (w *WebView) setupEventHandlers() { | |||||
| 229 | // Favicon changed - connect to FaviconDatabase | 239 | // Favicon changed - connect to FaviconDatabase | ||
| 230 | w.setupFaviconHandlers() | 240 | w.setupFaviconHandlers() | ||
| 231 | 241 | ||||
| 232 | - | // Load changed | 242 | + | // Load changed - track page lifecycle for performance monitoring |
| 233 | w.view.ConnectLoadChanged(func(event webkit.LoadEvent) { | 243 | w.view.ConnectLoadChanged(func(event webkit.LoadEvent) { | ||
| 234 | - | // Handle load events if needed | 244 | + | // Avoid calling callbacks if WebView is being destroyed to prevent reference cycles |
| 245 | + | // especially important when page cache is enabled | |||
| 246 | + | if w.IsDestroyed() { | |||
| 247 | + | return | |||
| 248 | + | } | |||
| 249 | + | ||||
| 250 | + | switch event { | |||
| 251 | + | case webkit.LoadStarted: | |||
| 252 | + | // Page load started - could show loading indicator | |||
| 253 | + | if w.onLoadStarted != nil { | |||
| 254 | + | w.onLoadStarted() | |||
| 255 | + | } | |||
| 256 | + | case webkit.LoadCommitted: | |||
| 257 | + | // Page committed - DOM is now available for interaction | |||
| 258 | + | if w.onLoadCommitted != nil { | |||
| 259 | + | w.onLoadCommitted() | |||
| 260 | + | } | |||
| 261 | + | case webkit.LoadFinished: | |||
| 262 | + | // Page fully loaded - all resources downloaded | |||
| 263 | + | if w.onLoadFinished != nil { | |||
| 264 | + | w.onLoadFinished() | |||
| 265 | + | } | |||
| 266 | + | } | |||
| 235 | }) | 267 | }) | ||
| 236 | 268 | ||||
| 237 | // TLS error handling - connect to load-failed-with-tls-errors signal | 269 | // TLS error handling - connect to load-failed-with-tls-errors signal | ||