-
Notifications
You must be signed in to change notification settings - Fork 1
Debug
eQuantic.UI provides professional debugging tools similar to Next.js, with development-only features that help you identify and fix issues quickly.
The framework automatically detects the environment using IWebHostEnvironment.IsDevelopment() and exposes it to the browser via:
window.__EQ_DEV__; // true in development, false in productionAll development tools are conditionally loaded based on this flag.
The logger provides consistent, prefixed logging that only outputs in development mode.
import { logger } from "@equantic/ui-runtime";
// Development only (silenced in production)
logger.debug("Component state:", state);
logger.info("API call completed");
// Always logs (even in production)
logger.warn("Deprecated API used");
logger.error("Failed to load data:", error);| Method | Output | Production | Prefix |
|---|---|---|---|
debug() |
Console debug | ❌ Silenced | [eQuantic.UI] |
info() |
Console info | ❌ Silenced | [eQuantic.UI] |
warn() |
Console warn | ✅ Always | [eQuantic.UI] |
error() |
Console error | ✅ Always | [eQuantic.UI] |
In browser DevTools, you can filter by the prefix:
[eQuantic.UI]
The logger is implemented in src/eQuantic.UI.Runtime/src/utils/logger.ts:
const isDev = typeof window !== "undefined" && window.__EQ_DEV__;
export const logger = {
debug(...args: any[]) {
if (isDev) console.debug("[eQuantic.UI]", ...args);
},
info(...args: any[]) {
if (isDev) console.info("[eQuantic.UI]", ...args);
},
warn(...args: any[]) {
console.warn("[eQuantic.UI]", ...args);
},
error(...args: any[]) {
console.error("[eQuantic.UI]", ...args);
},
};The error overlay provides a full-screen, Next.js-style error UI that appears automatically when runtime errors occur.
- Automatic Capture: Catches unhandled errors and promise rejections
-
C# stack traces ✨: the overlay is source-map aware — it fetches each bundle's
.js.map, decodes it (src/dev/source-map.ts+src/dev/stack-remapper.ts), and rewrites the Call Stack as the original C# frames, plus a snippet of the failing C# source line. Falls back to the JS view if no map is available. (This is what makes the "0 JS knowledge" promise real at debug time — a C# developer sees C#, not transpiled JavaScript.) -
Keyboard Support: Press
Escto close -
Development Only: Never appears in production (loaded via a dynamic
import()in dev) - Clean UX: Red header, monospace font, scrollable content
The error overlay automatically displays for:
- Unhandled Errors: Any uncaught exception in JavaScript
- Promise Rejections: Unhandled async errors
// These will trigger the error overlay in dev mode
throw new Error("Something went wrong");
Promise.reject("Async error");
await fetch("/api/data"); // If fetch fails and not caught┌─────────────────────────────────────────────┐
│ ⚠️ Build Error Close (Esc)│
├─────────────────────────────────────────────┤
│ │
│ Error message here │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ Stack trace: │ │
│ │ at MyComponent.render (page.js:42) │ │
│ │ at Reconciler.patch (reconciler.js:12)│ │
│ │ ... │ │
│ └─────────────────────────────────────────┘ │
│ │
├─────────────────────────────────────────────┤
│ This error overlay only appears in │
│ development. Fix the error to continue. │
└─────────────────────────────────────────────┘
You can manually show errors in the overlay:
import { errorOverlay } from "@equantic/ui-runtime/dev";
if (window.__EQ_DEV__) {
errorOverlay.show({
message: "Custom error message",
stack: error.stack,
componentStack: "Component hierarchy...",
});
}// Programmatically clear
errorOverlay.clear();
// User actions
// - Press Esc key
// - Click "Close" buttonThe error overlay is implemented in src/eQuantic.UI.Runtime/src/dev/error-overlay.ts:
class ErrorOverlay {
private overlay: HTMLDivElement | null = null;
private errors: ErrorInfo[] = [];
show(error: ErrorInfo) {
if (!window.__EQ_DEV__) return; // Dev only
this.errors.push(error);
this.render();
}
clear() {
this.errors = [];
if (this.overlay) {
this.overlay.remove();
this.overlay = null;
}
}
private render() {
// Creates full-screen overlay with error details
}
}
export const errorOverlay = new ErrorOverlay();
// Auto-capture errors
if (window.__EQ_DEV__) {
window.addEventListener("error", (event) => {
errorOverlay.show({
message: event.message,
stack: event.error?.stack,
});
});
window.addEventListener("unhandledrejection", (event) => {
errorOverlay.show({
message: `Unhandled Promise Rejection: ${event.reason}`,
stack: event.reason?.stack,
});
});
}eQuantic.UI generates source maps for debugging C# code in the browser.
Chrome DevTools:
- Open DevTools (F12)
- Go to Sources tab
- Find
webpack://or file paths in the tree - Set breakpoints directly in TypeScript/C# source
- Inspect state, props, and local variables
The compiler generates V3 source maps that map JavaScript back to original C# source:
{
"version": 3,
"sources": ["Page.cs"],
"mappings": "AAAA;AACA;...",
"names": ["MyComponent", "Render", "state"]
}This allows you to:
- Set breakpoints in C# code
- Step through C# logic
- Inspect C# variable names
- See original line numbers in stack traces
To inspect component state and props:
// In browser console
window.__EQ_DEBUG = true; // Enable debug mode
// Components expose their state
const component = document.querySelector(
'[data-component-id="abc"]',
).__component;
console.log(component.state);
console.log(component.props);For debugging SSR vs CSR rendering issues:
test("SSR matches CSR", async ({ page }) => {
// Get SSR HTML
const ssrResponse = await page.goto("http://localhost:5000");
const ssrHtml = await ssrResponse.text();
// Wait for CSR hydration
await page.waitForLoadState("networkidle");
const csrHtml = await page.content();
// Compare
expect(normalizeHtml(ssrHtml)).toBe(normalizeHtml(csrHtml));
});Debug C# code normally with Visual Studio or VS Code:
- Set breakpoints in
.csfiles - Run with debugger attached:
dotnet run - Breakpoints hit during:
- Server-side rendering (SSR)
- Server Action invocations
- Component compilation
Monitor Server Actions in browser DevTools:
- Open Network tab
- Filter by
_equantic/actions - Inspect:
- Request payload (method name, arguments)
- Response data
- Timing information
- Errors (with stack traces)
When using IRequireAssets, verify that dependencies are correctly injected:
- Inspect Source: Open browser "View Page Source" and search for the script/style tags.
- Network Tab: Check if the external URLs (e.g., CDNs) are loading successfully (Status 200).
- Deduplication: Verify that multiple components didn't inject the same script twice.
- Order: Stylesheets should appear before scripts for proper rendering.
If assets are missing in the initial HTML:
- Verify the component implements
IRequireAssets. - Ensure
AddUI()is called inProgram.cs. - Check if the
AssetCollectionis correctly gathering the assets during the render pass.
The reconciler tracks performance metrics in development mode:
// Enable performance tracking
window.__EQ_PERF = true;
// View metrics
console.table(window.__EQ_PERF_DATA);Metrics include:
- Render Time: How long each component took to render
- Diff Time: Time spent in reconciler
- DOM Operations: Number of actual DOM changes
- Event Listeners: Active listener count
Monitor compilation times:
dotnet build -v:detailedLook for:
-
CompileEQuanticUItarget duration - Number of components compiled
- TypeScript generation time
- Bun bundling time
Symptom: boot() never executes, GET /_equantic/runtime.js returns 404
Solution: Ensure SDK package includes runtime.js and CopyEQuanticRuntime target executes
# Check if runtime exists in SDK package
unzip -l ~/.nuget/packages/equantic.ui.sdk/0.1.1/equantic.ui.sdk.0.1.1.nupkg | grep runtime
# Force rebuild
dotnet clean
dotnet build -v:n # Check for "Copying runtime.js" messageSymptom: Server-rendered HTML is themed, but client-side rendering isn't
Root Cause: the theme bridge blob was not adopted at boot
Solution:
- Verify runtime.js loads before component scripts
- Check browser console for
[eQuantic.UI] Boot process started - Inspect
window.__EQ_THEME__in console - should contain the serialized theme
Symptom: Can't debug original C# code in browser DevTools
Solution:
- Ensure
sourcemap: truein vite.config.ts - Check that
.mapfiles exist inwwwroot/_equantic/ - Enable source maps in browser DevTools settings
- Clear browser cache and rebuild
Symptom: Errors logged to console but no overlay
Checks:
- Is
window.__EQ_DEV__true? (Check in console) - Is error overlay imported? (Check runtime.js includes it)
- Is error overlay CSS loaded? (Check for
#equantic-error-overlaystyles)
Force Show:
// Manually trigger overlay
import { errorOverlay } from "@equantic/ui-runtime/dev";
errorOverlay.show({ message: "Test error" });- Use Logger Liberally: Add debug logs during development, they're free in production
-
Test Both Modes: Always test with
DevelopmentandProductionenvironment - Monitor Network: Keep DevTools Network tab open to catch failed Server Actions
- Enable Source Maps: Always build with source maps in development
- Use Error Overlay: Don't suppress errors - let the overlay show them
For production issues:
- Server Logs: Check ASP.NET Core logs for Server Action errors
-
Browser Console: Only
warnanderrorlogs appear - Sentry/AppInsights: Integrate error tracking services
-
Source Maps: Optionally deploy
.mapfiles to separate server for production debugging
Before reporting issues:
- Check browser console for errors
- Verify
window.__EQ_DEV__is true (dev) or false (prod) - Confirm runtime.js loads (Network tab)
- Check the theme bridge blob (
window.__EQ_THEME__) - Test with browser cache disabled
- Try in incognito/private mode
- Compare SSR HTML with CSR HTML
- Check MSBuild output for warnings
- Verify NuGet packages are correct versions
- Runtime Architecture - Understanding the runtime system
- Build Flow - How compilation and bundling works
- Performance - Optimization techniques