PraxisJS

DevTools Decorators

Developer experience decorators — @Debug to expose signals, computed values, and methods in DevTools, and @Trace to instrument component performance.

DevTools Decorators

Decorators that feed data into the DevTools panel. Both are no-ops unless DevTools.init() has been called — so they're safe to leave in production code with zero runtime cost.

Install:

npm install @praxisjs/devtools
pnpm add @praxisjs/devtools
yarn add @praxisjs/devtools
bun add @praxisjs/devtools
import { Debug, Trace } from '@praxisjs/devtools'

@Debug(options?)

Exposes a field, getter, or method in the DevTools panel. What it tracks depends on what it decorates:

On @State() fields

Records every value change in the Signals panel with a 20-entry history. This is the most common use case.

import { Component, State } from '@praxisjs/decorators'
import { Debug } from '@praxisjs/devtools'
import { StatefulComponent } from '@praxisjs/core'

@Component()
class CartStore extends StatefulComponent {
  @Debug({ label: 'Cart Items' })
  @State()
  items: Product[] = []

  @Debug()
  @State()
  total = 0
}

Decorator order

@Debug must be written above @State(). Decorators apply bottom-up, so @State runs first to set up the reactive accessor, then @Debug wraps it to observe changes.

On getters

Tracks a computed value by creating an internal computed() that observes the getter. Changes appear in the Signals panel.

@Debug({ label: 'Has Discount?' })
get hasDiscount() {
  return this.total > 100
}

On methods

Records every method call in the Timeline with arguments, return value, and execution duration in milliseconds.

@Debug()
async fetchProducts() {
  this.items = await api.getProducts()
}

Options:

OptionTypeDescription
labelstringName shown in the panel. Defaults to the field or method name.

@Trace()

Instruments a component class to report lifecycle events and render metrics to the Components panel.

@Trace()
@Component()
class DataGrid extends StatefulComponent {
  @State() rows: Row[] = []

  render() {
    return <table>{/* ... */}</table>
  }
}

Automatically tracks: onBeforeMount, onMount, onBeforeUpdate, onUpdate, onAfterUpdate, onUnmount.

The Components panel shows:

  • Render count and last render duration in ms
  • Mount and unmount timestamps
  • Full lifecycle hook history

Decorator order

@Trace() must be written above @Component() since decorators apply bottom-up.


Production safety

@Debug and @Trace check whether DevTools.init() has been called before doing anything. If it hasn't — which is the case in every production build — they're completely inert. Use a dynamic import to ensure the DevTools package is never bundled into production at all:

// src/main.ts
import { render } from '@praxisjs/runtime'
import { App } from './app'

render(() => <App />, document.getElementById('app')!)

if (import.meta.env.DEV) {
  const { DevTools } = await import('@praxisjs/devtools')
  DevTools.init()
}

→ See DevTools for the full setup guide and panel reference.

On this page