Skip to content

Technical Architecture

IVG-Design edited this page Sep 24, 2025 · 4 revisions

Technical Architecture

Understanding how DevMirror works under the hood.

Core Technology

DevMirror is built on Puppeteer-core and the Chrome DevTools Protocol (CDP) to capture console output.

Why Puppeteer-core?

  • Lightweight: No bundled Chrome/Chromium download
  • Flexible: Works with any Chrome/Chromium installation
  • Protocol Access: Direct CDP access for console capture
  • Cross-Platform: Works on Windows, macOS, Linux
  • Reliable: Battle-tested by millions of developers

Architecture Overview

VS Code Extension
    ↓
DevMirror CLI
    ↓
Puppeteer-core
    ↓
Chrome DevTools Protocol
    ↓
Target Application (Browser/CEF/Node)

How It Works

1. Connection Phase

DevMirror uses Puppeteer-core to:

  • Detect running Chrome/Chromium instances
  • Connect via WebSocket to debug port
  • Establish CDP session
// Simplified connection logic
const browser = await puppeteer.connect({
  browserWSEndpoint: 'ws://localhost:9222/devtools/browser/...',
  defaultViewport: null
});

2. Console Capture

Using Chrome DevTools Protocol events:

  • Runtime.consoleAPICalled - Console method calls
  • Runtime.exceptionThrown - Uncaught exceptions
  • Log.entryAdded - Browser logs
  • Page.javascriptDialogOpening - Alerts/confirms

3. Log Processing

DevMirror processes each console event:

  1. Extracts message type (log, warn, error, info)
  2. Serializes complex objects
  3. Preserves stack traces
  4. Formats timestamps
  5. Writes to log file

Chrome DevTools Protocol (CDP)

What is CDP?

  • Protocol for debugging/profiling Chrome
  • WebSocket-based communication
  • JSON-RPC message format
  • Used by Chrome DevTools, Puppeteer, Playwright

Key CDP Domains Used

Runtime Domain:

  • Execute JavaScript
  • Monitor console API
  • Handle exceptions

Page Domain:

  • Page lifecycle events
  • Navigation monitoring
  • Dialog handling

Network Domain:

  • Request/response tracking
  • WebSocket monitoring
  • Cache control

Log Domain:

  • Browser logs
  • Violation reports
  • Deprecation warnings

Connection Modes

CDP Mode (Standard Browser)

// Connect to standard Chrome
puppeteer.connect({
  browserURL: 'http://localhost:9222',
  defaultViewport: null
});
  • Default port: 9222
  • Works with: Chrome, Chromium, Edge, Brave
  • Use for: Web applications

CEF Mode (Chrome Embedded Framework)

// Connect to CEF application using direct CDP connection
// No browser launch required - connects to existing CEF debug port
  • Default port: Configurable via config.cefPort
  • Works with: Adobe CEP, Electron with CEF
  • Use for: Desktop applications

Node Mode (Not Supported)

// Node.js debugging is not currently supported
// Use CDP mode for browser-based applications only
  • Default port: N/A
  • Works with: Not supported
  • Use for: Not supported
  • Status: Not implemented

Puppeteer-core vs Puppeteer

Feature Puppeteer Puppeteer-core
Chrome included Yes (~170MB) No
Package size ~170MB ~3MB
Auto-download Yes No
Chrome detection Automatic Manual
Use case Testing Connecting to existing Chrome

DevMirror uses puppeteer-core because:

  1. Smaller package size
  2. Uses your existing Chrome
  3. Works with any Chromium-based browser
  4. No unnecessary Chrome downloads

Chrome Detection

DevMirror uses a simple Chrome detection strategy:

Windows

  • Default path: C:\Program Files\Google\Chrome\Application\chrome.exe
  • Override via: chromePath in config or VS Code settings

macOS

  • Default path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
  • Override via: chromePath in config or VS Code settings

Linux

  • Default command: google-chrome
  • Override via: chromePath in config or VS Code settings

Note: For custom Chrome installations, set the chromePath in your DevMirror configuration or VS Code settings.

Performance Considerations

Memory Usage

  • Puppeteer-core: ~30MB
  • CDP connection: ~10MB per page
  • Log buffering: Configurable

CPU Impact

  • Minimal when idle: <1%
  • During capture: 2-5%
  • Serialization overhead: Negligible

Network Overhead

  • WebSocket connection: Minimal
  • Message size: ~1KB per log
  • Compression: Supported

Security

Local-Only by Default

  • Connections restricted to localhost
  • No external network access
  • No data sent outside

Permission Model

  • Read-only console access
  • No page modification
  • No script injection (default)

Isolation

  • Separate CDP session
  • No interference with DevTools
  • Independent of page state

Advanced Features

Object Serialization

Complex objects are serialized:

console.log({ deep: { nested: { object: true }}});
// Captured as formatted JSON

Stack Trace Preservation

Error stack traces maintained:

Error: Something went wrong
  at function1 (app.js:10:5)
  at function2 (app.js:20:10)

Async Log Handling

Handles async console calls:

setTimeout(() => console.log('Delayed'), 1000);
// Still captured

Multi-Page Support

Captures from all pages/frames:

  • Main page
  • iframes
  • Pop-ups
  • Web Workers

Troubleshooting Protocol Issues

Debug CDP Connection

# Check if CDP is available
curl http://localhost:9222/json

# Response shows debuggable targets

Enable Verbose Logging

DevMirror uses console output for logging. Check the VS Code Output panel (DevMirror channel) or terminal output for debugging information.

Monitor WebSocket Traffic

# Using Chrome DevTools
chrome://inspect/#devices

Common CDP Errors

Target closed

  • Page was closed
  • Browser crashed
  • Connection lost

Protocol error

  • Incompatible Chrome version
  • Invalid CDP command
  • Timeout exceeded

WebSocket error

  • Port not available
  • Firewall blocking
  • Wrong endpoint

Browser Compatibility

Browser Version Support
Chrome 89+ Full
Chromium 89+ Full
Edge 89+ Full
Brave 1.20+ Full
Opera 75+ Partial
Firefox - No (uses different protocol)
Safari - No (uses different protocol)

Future Enhancements

  • WebDriver BiDi support (cross-browser)
  • Firefox DevTools Protocol support
  • Safari Web Inspector support
  • Native Node.js integration
  • Performance profiling capture
  • Network request logging

Resources

The Problem

When VS Code extensions update, their installation path changes (e.g., from ivgdesign.devmirror-0.4.72 to ivgdesign.devmirror-0.4.75), breaking any hardcoded paths in package.json scripts.

The Solution: Shim Pattern

DevMirror uses a stable shim file that remains at the same location and dynamically resolves the current extension path:

Workspace Root
└── .vscode/
    └── devmirror/
        ├── cli.js (or cli.cjs for ESM)  # Stable shim
        └── config.json                   # Current paths

How It Works

  1. On Extension Activation: Creates/updates the shim and config
  2. Shim Script: Reads config.json to find current CLI path
  3. Package.json: Uses relative path to stable shim location
  4. Result: Scripts survive extension updates

ESM Support

  • Detects "type": "module" in package.json
  • Creates .cjs shim for ESM packages
  • Creates .js shim for CommonJS packages

Monorepo Support

  • Calculates relative paths from each package.json to workspace root
  • Works with nested package.json files
  • Maintains cross-platform compatibility

Clone this wiki locally