Component Lifecycle
Track LWC mount/unmount events and render counts with per-instance isolation, Locker Service-safe timing, and zero-effort multi-instance support.
Knowing when a component shows up and how often it re-renders is half the battle for UI performance. Triton ships two helpers for this — trackComponentLifecycle and trackComponentRender — and both work transparently across multiple instances of the same component on a single page.
trackComponentLifecycle(event)
Call this in connectedCallback and disconnectedCallback to log mount and unmount events. The accepted strings are 'connected' and 'disconnected'.
connectedCallback() {
this.triton = new Triton().bindToComponent('AccountDashboard');
this.triton.trackComponentLifecycle('connected');
}
disconnectedCallback() {
this.triton.trackComponentLifecycle('disconnected');
}Each call produces a TYPE.COMPONENT_LIFECYCLE log entry with:
summary=Component lifecycle: <componentName> - <event>action=lifecycle-connectedorlifecycle-disconnected
These records are great for spotting components that mount unexpectedly, churn through DOM updates, or never get torn down properly (a common Aura → LWC migration headache).
trackComponentRender()
Call from renderedCallback. Each invocation increments a per-instance counter and emits a TYPE.COMPONENT_RENDER log entry.
The log entry includes:
summary=Component render: <componentName>details=Render count: <n>— useful for spotting components that re-render an order of magnitude more than expected.
renderedCallback fires on every reactive update. If you instrument a noisy component, expect a lot of records. Combine with a sampling strategy (e.g. only log every Nth render) if you need to keep volume in check.
Per-Instance Isolation
When you call bindToComponent('ProductSearch'), Triton mints a UUID v4 behind the scenes and stores tracking data under a key like:
That means three instances of <c-product-search> on the same page produce three independent streams of render counts, lifecycle events, and custom marks — even though the component name is identical.
You don't need to manage instance IDs yourself — the proxy returned by bindToComponent carries them implicitly. The component name you pass is the grouping key (so dashboards can roll up across instances), and the UUID is the uniqueness key (so individual instances don't clobber each other's data).
Initialization Timing
Where to bind depends on whether your component uses @wire. Same rule as in LWC logging:
Without
@wire— bind and calltrackComponentLifecycle('connected')insideconnectedCallback.With
@wire— bind in the constructor so the logger exists before wire callbacks fire, but still calltrackComponentLifecycle('connected')fromconnectedCallbackfor the mount semantics to be accurate.
Locker Service-Safe Timing
Lifecycle and render entries timestamp themselves with Date.now() directly, and the broader profiling stack uses a getCurrentTime() helper that prefers performance.now() and silently falls back to Date.now() when the Performance API is restricted under Locker Service.
You don't need to special-case Locker Service in your code — every profiling helper in this section is built to degrade gracefully.
What Happens Without bindToComponent
Both lifecycle and render helpers check the binding first. If you call them on an unbound logger:
…they emit a console warning (Triton performance tracking requires bindToComponent() to be called first) and return. Nothing crashes; you just won't see the records.
Best Practices
Pair every
trackComponentLifecycle('connected')with atrackComponentLifecycle('disconnected'). Missing disconnects are the smoking gun for memory-leak-shaped problems.Add
trackComponentRender()early in the rollout to baseline normal render counts — once you have that baseline, regressions stand out instantly.Use the component name to your advantage: keep it stable and human-readable (the class name is usually the right call), so logs are easy to group and search.
Last updated