or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cookie-management.mdhttp-client.mdindex.mdplatform-runtime.mdplugin-development.mdwebview-management.md
tile.json

webview-management.mddocs/

WebView Management

WebView configuration and path management for hybrid applications. The WebView management system provides essential functionality for configuring how web content is served and accessed within native WebView containers on mobile platforms.

Capabilities

WebView Plugin

Plugin interface for managing WebView server paths and asset handling in hybrid applications.

/**
 * WebView plugin interface extending base Plugin
 */
interface WebViewPlugin extends Plugin {
  /** Set the server asset path for WebView */
  setServerAssetPath(options: WebViewPath): Promise<void>;
  /** Set the server base path for WebView */
  setServerBasePath(options: WebViewPath): Promise<void>;
  /** Get the current server base path */
  getServerBasePath(): Promise<WebViewPath>;
  /** Persist the server base path */
  persistServerBasePath(): Promise<void>;
}

/**
 * WebView path configuration
 */
interface WebViewPath {
  /** File system path or URL */
  path: string;
}

Usage Examples:

import { WebView } from "@capacitor/core";

// Set server base path for serving web assets
await WebView.setServerBasePath({
  path: '/android_asset/public'
});

// Set asset path for static resources
await WebView.setServerAssetPath({
  path: '/android_asset/public/assets'
});

// Get current server base path
const currentPath = await WebView.getServerBasePath();
console.log('Current base path:', currentPath.path);

// Persist the current configuration
await WebView.persistServerBasePath();

Server Path Configuration

Methods for configuring how the WebView serves web content and static assets.

/**
 * Set the server asset path for static resources
 * @param options Path configuration for assets
 */
setServerAssetPath(options: WebViewPath): Promise<void>;

/**
 * Set the server base path for web content
 * @param options Path configuration for base server
 */
setServerBasePath(options: WebViewPath): Promise<void>;

/**
 * Get the current server base path
 * @returns Current path configuration
 */
getServerBasePath(): Promise<WebViewPath>;

/**
 * Persist the current server base path configuration
 */
persistServerBasePath(): Promise<void>;

Usage Examples:

import { WebView } from "@capacitor/core";

// Configuration for Android platform
async function configureAndroidWebView() {
  // Set base path for main web content
  await WebView.setServerBasePath({
    path: '/android_asset/public'
  });

  // Set separate path for static assets (images, CSS, JS)
  await WebView.setServerAssetPath({
    path: '/android_asset/public/static'
  });

  // Verify configuration
  const basePath = await WebView.getServerBasePath();
  console.log('Configured base path:', basePath.path);

  // Persist configuration for future app launches
  await WebView.persistServerBasePath();
}

// Configuration for iOS platform
async function configureiOSWebView() {
  // iOS typically uses different path structure
  await WebView.setServerBasePath({
    path: 'public'
  });

  await WebView.setServerAssetPath({
    path: 'public/assets'
  });
}

// Dynamic path configuration based on app state
async function configureWebViewForEnvironment(isDevelopment: boolean) {
  if (isDevelopment) {
    // Development mode - serve from development server
    await WebView.setServerBasePath({
      path: 'http://localhost:3000'
    });
  } else {
    // Production mode - serve from bundled assets
    await WebView.setServerBasePath({
      path: '/android_asset/public'
    });
  }

  await WebView.persistServerBasePath();
}

WebView Path Management Patterns

Common patterns for managing WebView paths in different application scenarios.

Usage Examples:

import { WebView, Capacitor } from "@capacitor/core";

// Platform-specific WebView configuration
class WebViewManager {
  async initialize() {
    const platform = Capacitor.getPlatform();
    
    switch (platform) {
      case 'android':
        await this.configureAndroid();
        break;
      case 'ios':
        await this.configureiOS();
        break;
      case 'web':
        // No WebView configuration needed for web
        console.log('Running in browser - no WebView configuration needed');
        break;
    }
  }

  private async configureAndroid() {
    await WebView.setServerBasePath({
      path: '/android_asset/public'
    });

    await WebView.setServerAssetPath({
      path: '/android_asset/public/assets'
    });

    console.log('Android WebView configured');
  }

  private async configureiOS() {
    await WebView.setServerBasePath({
      path: 'public'
    });

    await WebView.setServerAssetPath({
      path: 'public/assets'
    });

    console.log('iOS WebView configured');
  }

  async updateBasePath(newPath: string) {
    await WebView.setServerBasePath({ path: newPath });
    await WebView.persistServerBasePath();
    
    const updatedPath = await WebView.getServerBasePath();
    console.log('Updated base path to:', updatedPath.path);
  }

  async getCurrentConfiguration(): Promise<WebViewPath> {
    return await WebView.getServerBasePath();
  }
}

// Multi-environment WebView setup
class EnvironmentWebViewManager {
  private readonly environments = {
    development: {
      basePath: 'http://localhost:3000',
      assetPath: 'http://localhost:3000/assets'
    },
    staging: {
      basePath: '/android_asset/staging',
      assetPath: '/android_asset/staging/assets'
    },
    production: {
      basePath: '/android_asset/public',
      assetPath: '/android_asset/public/assets'
    }
  };

  async configureForEnvironment(env: keyof typeof this.environments) {
    const config = this.environments[env];
    
    await WebView.setServerBasePath({
      path: config.basePath
    });

    await WebView.setServerAssetPath({
      path: config.assetPath
    });

    await WebView.persistServerBasePath();
    
    console.log(`WebView configured for ${env} environment`);
  }

  async switchEnvironment(newEnv: keyof typeof this.environments) {
    console.log(`Switching WebView to ${newEnv} environment`);
    await this.configureForEnvironment(newEnv);
    
    // Might require app restart or page reload for changes to take effect
    if (Capacitor.isNativePlatform()) {
      console.log('Environment switched - consider restarting app');
    }
  }
}

// Usage in app initialization
const webViewManager = new WebViewManager();
const envManager = new EnvironmentWebViewManager();

// Initialize WebView on app start
async function initializeApp() {
  try {
    await webViewManager.initialize();
    
    // Configure for specific environment
    const isProduction = process.env.NODE_ENV === 'production';
    const environment = isProduction ? 'production' : 'development';
    
    await envManager.configureForEnvironment(environment);
    
    console.log('WebView initialization complete');
  } catch (error) {
    console.error('Failed to initialize WebView:', error);
  }
}

// Hot reload support for development
async function enableHotReload() {
  if (process.env.NODE_ENV === 'development') {
    await WebView.setServerBasePath({
      path: 'http://localhost:3000'
    });
    
    console.log('Hot reload enabled - serving from development server');
  }
}

// Asset path optimization
class AssetPathOptimizer {
  async optimizeForPlatform() {
    const platform = Capacitor.getPlatform();
    
    if (platform === 'android') {
      // Android optimization
      await WebView.setServerAssetPath({
        path: '/android_asset/optimized'
      });
    } else if (platform === 'ios') {
      // iOS optimization
      await WebView.setServerAssetPath({
        path: 'optimized'
      });
    }
  }

  async preloadCriticalAssets() {
    // This would typically be handled by the WebView's asset loading
    // but can be configured through path management
    
    const currentPath = await WebView.getServerBasePath();
    console.log('Critical assets will be loaded from:', currentPath.path);
  }
}

Error Handling and Validation

Best practices for handling WebView configuration errors and validating paths.

Usage Examples:

import { WebView, Capacitor } from "@capacitor/core";

class WebViewConfigValidator {
  async validateAndConfigure(basePath: string, assetPath?: string) {
    try {
      // Validate paths before setting
      if (!this.isValidPath(basePath)) {
        throw new Error(`Invalid base path: ${basePath}`);
      }

      await WebView.setServerBasePath({ path: basePath });

      if (assetPath) {
        if (!this.isValidPath(assetPath)) {
          throw new Error(`Invalid asset path: ${assetPath}`);
        }
        await WebView.setServerAssetPath({ path: assetPath });
      }

      // Verify configuration was applied
      const configuredPath = await WebView.getServerBasePath();
      if (configuredPath.path !== basePath) {
        console.warn('Base path configuration may not have been applied correctly');
      }

      await WebView.persistServerBasePath();
      return true;

    } catch (error) {
      console.error('WebView configuration failed:', error);
      await this.applyFallbackConfiguration();
      return false;
    }
  }

  private isValidPath(path: string): boolean {
    // Basic path validation
    if (!path || typeof path !== 'string') {
      return false;
    }

    // Check for valid URL or file path
    try {
      new URL(path);
      return true; // Valid URL
    } catch {
      // Not a URL, check if it's a valid file path
      return path.startsWith('/') || path.match(/^[a-zA-Z]:/) || !path.includes('://');
    }
  }

  private async applyFallbackConfiguration() {
    console.log('Applying fallback WebView configuration');
    
    const platform = Capacitor.getPlatform();
    const fallbackPaths = {
      android: '/android_asset/public',
      ios: 'public',
      web: '/' // Not used, but for completeness
    };

    try {
      await WebView.setServerBasePath({
        path: fallbackPaths[platform as keyof typeof fallbackPaths] || fallbackPaths.web
      });
      
      console.log('Fallback configuration applied successfully');
    } catch (error) {
      console.error('Even fallback configuration failed:', error);
    }
  }

  async getCurrentConfig(): Promise<{
    basePath: string;
    isValid: boolean;
    platform: string;
  }> {
    try {
      const pathConfig = await WebView.getServerBasePath();
      return {
        basePath: pathConfig.path,
        isValid: this.isValidPath(pathConfig.path),
        platform: Capacitor.getPlatform(),
      };
    } catch (error) {
      console.error('Failed to get current WebView configuration:', error);
      return {
        basePath: '',
        isValid: false,
        platform: Capacitor.getPlatform(),
      };
    }
  }
}

// Usage with error handling
const validator = new WebViewConfigValidator();

async function safeWebViewSetup() {
  const success = await validator.validateAndConfigure('/android_asset/public');
  
  if (success) {
    console.log('WebView configured successfully');
  } else {
    console.log('WebView configuration failed, using fallback');
  }

  const config = await validator.getCurrentConfig();
  console.log('Current WebView config:', config);
}